Un primo esempio di High Availability per Asterisk
Vi sono varie possibilità per ottenere un sistema HA per Asterisk. Quello presentato in questo articolo poggia sull'utilizzo di uCarp, (Common Address Redundancy Protocol) software portato da OpenBSD, alternativa al VRRP di Cisco.
UCARP permette ad una coppia di hosts di condividere uno stesso indirizzo IP virtuale allo scopo di fornire un meccanismo di failover automatico
Caratteristiche notevoli del protocollo CARP sono: leggerezza, interoperabilità tra sistemi operativi diversi e nessuna necessità di ricorrere a collegamenti dedicati tra gli hosts componenti.
Si supponga di voler ottenere una soluzione di ridondanza (un server di backup attivato automaticamente) relativamente ad un server Asterisk cui siano collegati un certo numero di telefoni SIP
Tipicamente l'indirizzo ip che viene loro fornito come proxy è appunto quello del server Asterisk. Utilizzando uCarp, l'indirizzo IP che utilizzeranno sarà un indirizzo virtuale, direttamente gestito da uCarp. Asterisk sarà installato in entrambi i server assieme ad uCarp, che avrà il compito di spostare l'ip virtuale da un server all' altro quando quello attivo, per un qualsiasi motivo, non dovesse piu rispondere.
Cominciamo con uCarp,
Il package da scaricare è http://download.pureftpd.org/pub/ucarp/ucarp-1.3.tar.gz
Una volta decompresso all'interno di una directory di nostra scelta, il modo più semplice di compilare tale package è:
Posizionarsi nella directory contenente il codice sorgente (nello specifico ucarp-1.3) e impartire:
`./configure'.
`make' per compilare il package.
Opzionalmente, `make check' per eseguire dei self-tests compresi nel package.
Infine `make install'
Inizializzarlo è piuttosto semplice.
Chi come il sottoscritto preferisce usare Slackware, può ad esempio inserire il blocco di codice seguente nel file /etc/rc.d/rc.local del primo server
/usr/sbin/ucarp -i eth0 -s 192.168.1.1 -v 1 -p pippo \
-a 192.168.1.10 \
-u /etc/ucarp/virtual-ip-up.sh \
-d /etc/ucarp/virtual-ip-down.sh \
-B -z
Le opzioni utilizzate, istruiscono uCarp ad usare l'interfaccia eth0 (-i eth0), stabiliscono che l'ip del server è 192.168.1.1 (-s 192.168.1.1), assegnano un identificativo numerico condiviso per l'indirizzo IP virtuale, ovvero un numero compreso fra 1 e 255 (-v 1). e la password "pippo" che sarà anch'essa condivisa tra entrambi i nodi uCarp (-p pippo); l'ip virtuale è invece il 192.168.1.10 (-a 192.168.1.10). Le opzioni -u e -d fanno eseguire i relativi script quando il nodo diventa rispettivamente Master (-u) o Backup (-d). L'opzione -B implica che l'esecuzione avvenga in background e -z istruisce uCarp ad eseguire lo script specificato con la opzione -d al momento dello shutdown.
Quando uCarp viene eseguito senza che sia presente una precedente istanza, parte con lo stato di backup e si pone in ascolto per determinare quando debba divenire master. Quando entra nello stato di backup, normalmente esegue lo script specificato con l'opzione -d (downscript). Questo può essere di una certa utilità ad esempio per rimuovere vecchi file temporanei o resettare una interfaccia. In altre circumstanze può essere preferibile non eseguire il downscript se il servizio non è ancora attivo. In tal caso, si usa la opzione --neutral (-n) per non mandare in esecuzione il downscript quando uCarp entra nello stato di backup la prima volta.
Sara sufficente copiare la medesima configurazione sul secondo server, modificando solamente l' indirizzo ip sorgente (-s 192.168.1.2)
Gli script specificati nella configurazione contengono:
virtual-ip-up.sh:
#!/bin/bash
exec 2> /dev/null
/sbin/ip addr add 192.168.1.10/24 dev "$1"
virtual-ip-down.sh:
#!/bin/bash
exec 2> /dev/null
/sbin/ip addr del 192.168.1.10/24 dev "$1"
killall -9 asterisk
A questo punto, in entrambi i server ci basterà eseguire il file /etc/rc.d/rc.local per avviare i due demoni.
Per verificarne il funzionamento potete eseguire il comando
# ip addr
che evidenzierà se l'host in cui viene eseguite ha l'indirizzo IP virtuale configurato.
eth0: mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:14:85:e2:a0:a8 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.2/24 brd 192.168.1.255 scope global eth0
inet 192.168.1.10/24 scope global secondary eth0
inet6 fe80::214:85ff:fee2:a0a8/64 scope link
valid_lft forever preferred_lft forever
Staccando il cavo di rete, o killando ucarp, dopo pochi istanti verrà evidenziato il cambio di stato.
In /var/log/syslog, appariranno delle entry come queste:
Oct 28 00:16:01 blackslack ucarp[8147]: [WARNING] Spawning [/etc/ucarp/vip-down.sh eth0]
Oct 28 00:16:01 blackslack ucarp[8253]: [WARNING] Switching to state: BACKUP
Oct 28 00:16:52 blackslack ucarp[8253]: [WARNING] Switching to state: MASTER
Oct 28 00:16:52 blackslack ucarp[8253]: [WARNING] Spawning [/etc/ucarp/vip-up.sh eth0]
Dopo aver installato uCarp ed esserci accertati del suo funzionamento, possiamo continuare la nostra configurazione per far in modo che il cambio di stato avvenga non solo in caso di fault del server master, ma anche quando Asterisk non dovesse più risultare correttamente operativo.
Utilizzando un altro semplice script, eseguito da cron ogni minuto, possiamo verificare lo stato di asterisk ed eventualmente commutare il servizio sull'altro server:.
#!/bin/bash
ASTCHECK=`/usr/sbin/asterisk -rx "" &>/dev/null; echo $?`
UCARPCHECK=`ps ax|grep /usr/local/sbin/ucarp|grep -v grep|awk '{print $1}'`
if [ "$ASTCHECK" != "0" ]; then
/bin/killall ucarp
/usr/sbin/safe_asterisk
/usr/local/sbin/ucarp -i eth0 -s 192.168.1.2 -v 1 -p pippo \
-a 192.168.1.10 -u /etc/ucarp/virtual-ip-up.sh -d /etc/ucarp/virtual-ip-down.sh -B -z -n
else
if [ "$UCARPCHECK" == "" ]; then
/usr/local/sbin/ucarp -i eth0 -s 192.168.1.2 -v 1 -p pippo \
-a 192.168.1.10 -u /etc/ucarp/virtual-ip-up.sh -d /etc/ucarp/virtual-ip-down.sh -B -z
fi
fi
exit 0;
Alcune considerazioni su questo codice:
Asterisk dovrebbe essere sempre in esecuzione, grazie a safe_asterisk, tuttavia potrebbe essere bloccato, o non rispondere piu a certi comandi/chiamate,
Lo script verifica che asterisk funzioni correttamente.
Nel caso non dovesse rispondere, killeremo uCarp (e di conseguenza pure Asterisk), in tal modo l' altro server diventerebbe MASTER.
Asterisk viene fatto ripartire, e così pure uCarp (in stato di BACKUP ed evitando di rieseguire il downscript).
In tal modo il server non solo ha passato il controllo ad un altro in caso di problemi, ma si è anche reso nuovamente disponibile e funzionante.
Alla successiva riesecuzione dello script in cron, nel caso in cui Asterisk sia regolarmente in funzione, viene fatto solamente un controllo sul funzionamento del demone ucarp, che viene eventualmente riavviato.
Il meccanismo appena illustrato limita a una trentina di secondi, in media, l'outage del server Asterisk
Un problema non da poco
Quando l'indirizzo ip di un peer SIP (oppure IAX) non è conosciuto, un utente non può in alcun modo ricevere una chiamata fino a che il peer non abbia di nuovo effettuato la propria registrazione. Per rimediare a questo inconveniente, che può determinare un allungamento dell'effettivo outage del servizio di qualche minuto, si possono seguire diversi approcci, ad esempio:
- Impostare tutti i peers ad utilizzare un indirizzo IP statico (soluzione, in generale, improponibile).
- Abbassare per tutti il refresh del register, cosicche se vi dovesse essere una commutazione di server, anche i client si renderebbero più velocemente disponibili (soluzione inelegante che pure può implicare un allungamento, seppure decisamente minore, dei tempi di ripristino.
- Utilizzare l'architettura Real Time di Asterisk per memorizzare i dati di ciascun peer in una tabella di database (ad esempio MySQL) ospitata da un terzo server ed accessibile di volta in volta al MASTER uCarp di turno
Dato che questa soluzione introduce nella architettura un ulteriore elemento (il db-server) che può costituire a sua volta uno SPOF (Single Point Of Failure), tale elemento dovrà necessariamente possedere adeguate caratteristiche di affidabilità. In alternativa si può pensare di ospitare il db sui server Asterisk e adottare il meccanismo di replicazione MySQL tra di loro, alternando il ruolo di Master e Slave in sicronia col cambio di stato visto nel presente articolo.
Mi riprometto di trattare l'argomento in um successivo articolo.
Un' ultima considerazione
La soluzione di failover fin qui trattata non considera l'eventualità di gestire l'aspetto della connettività a linee esterne (ad esempio flussi primari E1/T1)
Anche questo aspetto costituirà il tema di un futuro articolo
|