Loadbalanced High-Availability Apache

Da Inc0Wiki.

Preambolo

Questa guida prevede che i server Apache siano già configurati e funzionanti: se i server sfruttano VirtualHosts ricordate di crearne uno che risponda all'ip virtuale (di seguito è spiegato di cosa si tratta) dei loadbalancer.
L'attuale configurazione è stata effettuata sfruttando 4 macchine virtuali (ubuntu 8.04) virtualizzate con VMWare Server 2.0.

Scopo

Questa guida ha lo scopo di spiegare come configurare due (ma è facile estendere tale numero) server Apache in cluster ad alta disponibilità. Prima dei due server apache posizioneremo un bilanciatore di carico che splitterà il carico sui due (o N) nodi. In quando non vogliamo che il load balancer diventi il "Single Point Of Failure", verrà configurato in alta disponibilità per cui utilizzeremo 2 (ma anche in questo caso si può estendere tale numero) bilanciatori che si controlleranno a vicenda e nel caso uno deceda l'altro prenderà il suo posto in modo trasparente.

Pacchetti Necessari

Sui server web non è necessario installare alcun pacchetto, sui load-balancer sarà invece necessario procedere all'installazione di:
ipvsadm - suite di tool per l'implementazione del Linux Virtual Server
ldirectord - monitor per LVS
heartbeat - software per l'alta affidaibilità

Un po' di teoria...

Come detto useremo 4 macchine virtuali: i due webserver avranno ip 192.168.56.103 e 192.168.56.104 mentre i due load-balancer avranno ip 192.168.56.101 e 192.168.56.102: i bilanciatori saranno inoltre dotati di un ip virtuale, 192.168.56.50, che ruoterà le richieste ai web server e bilancerà il carico.

HA LB.png

Configurazione

Load-balancers

Per permettere ai load-balancer di redirigere il traffico verso i web-server è necessario abilitare l'ip forwarding, modifichiamo quindi /etc/sysctl.conf:

net.ipv4.ip_forward=1

LVS

NOTA: I moduli per l'implementazione del Linux Virtual Server sono resi disponibili compilandli nel kernel attivo sul vostro sistema.
Per prima cosa carichiamo i moduli per l'LVS tramite modprobe e poi, per fare si che vengano caricati automaticamente all'avvio li aggiungiamo in /etc/modules:

ip_vs_dh
ip_vs_ftp
ip_vs
ip_vs_lblc
ip_vs_lblcr
ip_vs_lc
ip_vs_nq
ip_vs_rr
ip_vs_sed
ip_vs_sh
ip_vs_wlc
ip_vs_wrr

Installazione del Software

Procediamo ora all'installazione del software per la gestione del load-balancing e del failover: ipvsadm, ldirectord e heartbeat.

ipvsadm

Una volta installato, assicuratevi che parta all'avvio del sistema:

/etc/default/ipvsadm
# Do not edit! Use 'dpkg-reconfigure ipvsadm'.
#Avvio automatico
AUTO="true"
#Demone master
DAEMON="master"
#Interfaccia
IFACE="eth2"
heartbeat

La configurazione di heartbeat prevede la modifica di 3 file di configurazione

/etc/ha.d/ha.cf
# Log gestiti tramite syslog
logfacility local0

# Interfaccia su cui eseguire il broadcast
bcast eth2

# Interfaccia di multicast
# mcast [dev] [mcast group] [port] [ttl] [loop]
mcast eth2 225.0.0.1 694 1 0

# off: quando il nodo cade, un altro nodo del cluster diventa master MA quando il primo nodo torna online NON ri-diventa automaticamente master
# on:  quando il nodo cade, un altro nodo del cluster diventa master MA quando il primo nodo torna online ri-diventa automaticamente master
auto_failback off

# nome dei nodi (outpit di 'uname -n' sul nodo) che effettuano il load-balance
node vb-ubuntu0
node vb-ubuntu1

# hacluster: utente usato per mandare in esecuzione ''ipfail''
# haclient: gruppo usato per mandare in esecuzione ''ipfail''
respawn hacluster /usr/lib/heartbeat/ipfail
apiauth ipfail gid=haclient uid=hacluster
/etc/ha.d/haresources
vb-ubuntu0 \
 ldirectord::ldirectord.cf \
 LVSSyncDaemonSwap::master \
 IPaddr2::192.168.56.50/24/eth2/192.168.56.255

vb-ubuntu0 : hostname del load balancer
ldirectord::ldirectord.cf : nome del file di configurazione usato per lanciare ldirectord; il path di default è /etc/ha.d
IPaddr2::192.168.56.50/24/eth2/192.168.56.255 : indirizzo ip del server virtuale, netmask, interfaccia ethernet, indirizzo di broadcast della sottorete

/etc/ha.d/authkeys

File contenente la stringa usata per autenticare i client del load-balance

auth 3
3 md5 StringaRandom

Il file deve essere accessibile in lettura e scrittura al solo proprietario:

# chmod 600 /etc/ha.d/authkeys
ldirectord

Configuriamo ora ldirectord: tale demone NON deve partire automaticamente ma deve essere heartbeat ad avviarlo solo quando necessario. Il file di configurazione di ldirectord è ldirectord.cf e si trova in /etc/ha.d:

/etc/ha.d/ldirectord.cf
# Timeout del check del servizio
checktimeout=10

# Quanto spesso eseguire il controllo
checkinterval=2

# Lettura automatica del file di configurazione
autoreload=no

# Log inviati a syslog
logfile="local0"

#  yes: quando i server reali o di fallback vengono riconosciuti come inattivi, vengono rimossi dalla tabella LVS del kernel.
#  no:  quando i server reali o di fallback vengono riconosciuti come inattivi, il loro peso viene abbassato nella tabella LVS del kernel.
quiescent=no

# IP Virtuale e porta
virtual=192.168.56.50:80
        # Server reali ai quali inoltrare le richieste, porta, metododo di instradamento, peso nella tabella LVS
        real=192.168.56.103:80 gate 1
        real=192.168.56.104:80 gate 2
        # nel caso i due server reali non sono accessibili, viene attivata una rotta verso un server sul quale, ad esempio, è possibile cofigurare una pagina di warning
        fallback=192.168.56.101:80 gate
        #Servizio
        service=http
        #Il controllo viene effettuato richiedendo una pagina html: in questo caso ldirector.html
        request="ldirector.html"
        #Se la pagina richiesta contiene la stringa indicata, il servizio viene considerato attivo
        receive="Test Page"
        #Scheduler usato nella gestione delle richieste
        scheduler=rr
        #Protocollo utilizzato
        protocol=tcp
        #Metodo usato durante il controllo
        checktype=negotiate
Configurazione dei Servizi

Configuriamo a questo punto i servizi: heartbeat deve partire al boot dei load-balancer mentre ldirectord non deve partire automaticamente in quanto, come detto in precedenza, è heartbeat ad avviarlo in base alla necessità. Su ubuntu, per ottenere l'effetto desiderato, potete digitare quanto segue:

# update-rc.d heartbeat start 75 2 3 4 5 . stop 05 0 1 6 .
# update-rc.d -f ldirectord remove
# /etc/init.d/ldirectord stop
# /etc/init.d/heartbeat start 

Web Server

I webserver devono essere in grado di vedere il traffico destinato all'ip virtuale come fosse locale, per fare ciò creiamo una interfaccia virtuale associata al localhost il cui ip sarà identico a quello virtuale e la cui netmask sarà /32, inoltre dobbiamo impedire che tale ip venga annunciato sulla rete tramite ARP.
Per configurare l'interfaccia virtuale basterà modificare /etc/network/interfaces aggiungendo:

iface lo:0 inet static
	address 192.168.56.50
	netmask 255.255.255.255
auto lo:0

L'interfaccia si presenterà così:

lo:0      Link encap:Local Loopback  
          inet addr:192.168.56.50  Mask:255.255.255.255
          UP LOOPBACK RUNNING  MTU:16436  Metric:1

Inibiamo ora la propagazione di tale ip tramite ARP modificando /etc/sysctl.conf:

[...]
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.eth3.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.eth3.arp_ignore = 2

NOTA: eth3 è l'unica interfaccia ethernet attiva sulla macchina virtuale.
Salviamo e applichiamo le modifiche digitando

# sysctl -p

Verifica

LVSSyncDaemonSwap

LVSSyncDaemonSwap è il demone che si occupa della sincronizzazione di LVS, viene installato automaticamente con heartbeat e si trova nella directory /etc/ha.d/resource.d/; eseguiamo la verifica del demone sia sul balancer attivo:

# /etc/ha.d/resource.d/LVSSyncDaemonSwap master status
master running
(ipvs_syncmaster pid: 5069)

e successivamente su quello inattivo:

# /etc/ha.d/resource.d/LVSSyncDaemonSwap master status
master stopped

Un output come il precedente conferma il corretto funzionamento del demone.

LVS

La prima verifica che effettueremo riguarda l'ip virtuale: sul load-balancer attivo digitiamo:

# ip addr sh eth2

eth2 è l'interfaccia a cui è associato l'ip virtuale, se l'output è

2: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 08:00:27:3d:9a:39 brd ff:ff:ff:ff:ff:ff
    inet 192.168.56.101/24 brd 192.168.56.255 scope global eth2
    inet 192.168.56.50/24 brd 192.168.56.255 scope global secondary eth2
    inet6 fe80::a00:27ff:fe3d:9a39/64 scope link 
       valid_lft forever preferred_lft forever

significa che il bilanciatore funziona. Eseguiamo un'ulteriore verifica digitiamo lo stesso comando (sostituendo ad eth2 l'interfaccia appropriata) sul balancer inattivo:

# ip addr sh eth3
2: eth3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 08:00:27:e6:11:04 brd ff:ff:ff:ff:ff:ff
    inet 192.168.56.102/24 brd 192.168.56.255 scope global eth3
    inet6 fe80::a00:27ff:fee6:1104/64 scope link 
       valid_lft forever preferred_lft forever

Notiamo che, giustamente, a tale interfaccia non è associato l'ip virtuale. A questo punto simuliamo un fault del load-balancer attivo disabilitando l'interfaccia ethernet, fermando il servizio di heartbeat o spegnendo il bilanciatore. Se tutto funziona a dovere, otterremo un output come questo:

# ip add sh eth3
2: eth3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 08:00:27:e6:11:04 brd ff:ff:ff:ff:ff:ff
    inet 192.168.56.102/24 brd 192.168.56.255 scope global eth3
    inet 192.168.56.50/24 brd 192.168.56.255 scope global secondary eth3
    inet6 fe80::a00:27ff:fee6:1104/64 scope link 
       valid_lft forever preferred_lft forever

Osserviamo immediatamente che l'ip virtuale è stato associato alla scheda ethernet del load-balancer ancora attivo: ciò indica che il failover funziona.

ldirectord

Come ricordato più volte in precedenza ldirectord non viene eseguite all'avvio del sistema ma viene spawnato da heartbeat quando è necessario: per verificarne il corretto funzionamento, sul balancer attivo, digitiamo:

# ldirectord /etc/ha.d/ldirectord.cf status
ldirectord for /etc/ha.d/ldirectord.cf is running with pid: 6022

mentre, lo stesso comando, sul balancer inattivo:

# ldirectord /etc/ha.d/ldirectord.cf status
ldirectord is stopped for /etc/ha.d/ldirectord.cf

Se otteniamo output come i precedenti avremo la conferma che anche ldirectord funziona a dovere.

ipvsadm

ipvsadm si occupa di bilanciare il traffico, cambiare il peso delle rotte e il tipo di scheduler. Per verificarne il corretto funzionamento, sul balancer attivo, digitiamo:

# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.56.50:www rr
  -> 192.168.56.103:80               Route   1      49        111       
  -> 192.168.56.104:80               Route   1      51        106 

mentre, lo stesso comando, sul balancer inattivo:

# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

Se otteniamo output come i precedenti avremo la conferma che anche anche ipvsadm funziona a dovere.

Test di bilanciamento - DA RIFARE CON PAGINA DINAMICA PER AVERE CONNESSIONI ATTIVE

Effettuiamo un test di bilanciamento: generiamo N connessioni contemporanee verso l'ip virtuale e sul load-balancer attivo visioniamo quante connessioni vengono redirette ai server reali. Per effettuare questo test useremo un tool chiamato siege; siege sarà eseguire su una macchina che può accedere all'ip virtuale o, nel caso di questa guida, sull'host (la macchina fisica su cui gira VMWare):

# siege -c100 -t5M http://192.168.56.50

Mentre il test viene eseguito, sul balancer attivo, tramite ipvsadm, possiamo monitorare le connesioni dirette ai web-server:

# ipvsadm
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.56.50:www rr
  -> vb-ubuntu2:www               Route   1      49         452       
  -> vb-ubuntu3:www               Route   1      51         452  

Possiamo inoltre simulare dei fault sia dei web-server spegnendoli alternativamente (o entrambi) e dei balancer spegnendoli alternativamente:

Lifting the server siege...      done.
Transactions:		        2729 hits
Availability:		      100.00 %
Elapsed time:		       59.37 secs
Data transferred:	        0.25 MB
Response time:		        0.04 secs
Transaction rate:	       85.97 trans/sec
Throughput:		        0.00 MB/sec
Concurrency:		        1.67
Successful transactions:        2729
Failed transactions:	           0
Longest transaction:	        3.04
Shortest transaction:	        0.00

Credits

Autore: Incubus

E-Mail: theincubus (at) gmail (dot) com