Postfix in alta affidabilità e massima performance con heartbeat, LVS ed ldirectord (3 di 4)

postfix    linux-ha    lvs

La terza fase del progetto prevede la creazione di un servizio bilanciato su una batteria di real server. Verrà trattato il bilanciamento di un servizio di test (Apache 2) per verificare che il carico venga correttamente distribuito sui real server che fanno parte del Linux Virtual Server.

Bilanciamento con Linux

Il bilanciamento del carico con Linux è possibile attraverso Linux Virtual Server, l’insieme di moduli del Kernel progettato per adempiere a questo scopo. Sebbene vi sia la possibilità di configurare il funzionamento di tali moduli attraverso il comando ipvsadm, esiste un programma chiamato ldirectord che consente di impostare regole per il load balancing in maniera automatica partendo da un file di configurazione. Oltre a poter essere configurato affinché effettui il monitoring delle risorse configurate sui real server ldirectord possiede un enorme altro vantaggio: è completamente integrato con heartbeat come risorsa del cluster. Questo significa che associando la risorsa ldirectord all’indirizzo IP virtuale (configurato nella puntata precedente) si potrà avere il servizio di bilanciamento in alta affidabilità, eliminando di fatto lo SPOF (Single Point Of Failure) rappresentato dal bilanciatore operante su un singolo nodo.

Installazione di ldirectord e apache2

L’installazione del pacchetto ldirectord, che comprende tutti gli script necessari all’interfacciamento con heartbeat, può essere effettuata attraverso apt-get:

apt-get install ldirectord-2

tra i file installati insieme al pacchetto particolare attenzione va riservata allo script ldirectord nella cartella /etc/ha.d/resource.d/. Esso infatti è il fulcro dietro al quale opererà il bilanciamento software. Su ciascun real server invece andrà installato il pacchetto apache2 che servirà per i test di bilanciamento:

apt-get install apache2

L’installazione attiverà il demone apache che si metterà in ascolto sulla porta TCP 80.

Configurazione di ldirectord

La configurazione del servizio per convenzione è contenuta nel fie /etc/ha.d/ldirectord.cf ed un esempio della composizione dello stesso si trova nel file /usr/share/doc/ldirectord-2/ldirectord.cf.gz installato con il pacchetto. All’interno del file devono essere presenti un’area generale contenente le direttive globali ed un’area specifica relativa al servizio che si vuole bilanciare. L’area globale contiene le seguenti direttive:

checktimeout=3

Rappresenta i secondi dopo i quali la risorsa non rispondendo viene dichiarata morta.

checkinterval=1

Rappresenta i secondi tra un check e l’altro.

fallback=127.0.0.1:80

Valido solo per i servizi http, indica quale server funzionerà da fallback in caso tutti i server reali vengano dichiarati morti.

autoreload=yes

Stabilisce se ldirectord deve continuamente rileggere il file di configurazione dal disco. Se tale campo è valorizzato a “yes” allora le modifiche effettuate al file di configurazione verranno istantaneamente messe in atto dal demone.

logfile="/var/log/ldirectord.log"
#logfile="local0"

Indica dove verranno scritti i log, se in file predeterminato oppure nei log di sistema (syslog).

quiescent=yes

Permette di stabilire il comportamento di ldirectord di fronte ad un server dichiarato morto, se il valore è “yes” (che è il default), un real server morto non viene rimosso dalla tabella ipvs del kernel, ma il suo peso viene settato a zero, che comporta il non servire più le richieste pervenute al bilanciatore. Se il valore è “no” allora il real server morto viene completamente rimosso dalla tabella ipvs del kernel.

I parametri valorizzati rappresentano il dafult per i real server e possono essere modificati nelle singole dichiarazioni in modo da ottenere l’override degli stessi. Terminata la dichiarazione delle direttive globali l’attenzione è spostata sui servizi bilanciati, che sono dichiarati con una direttiva “virtual”:

virtual=192.168.0.100:80
real=192.168.0.50:80 gate
real=192.168.0.51:80 gate
real=192.168.0.52:80 gate
fallback=127.0.0.1:80 gate
service=http
request="index.html"
receive="It Works!”
virtualhost=www.esempio.com
scheduler=rr
protocol=tcp

Nell’esempio ad essere bilanciato è un servizio http. Questo come ogni virtuale ha tre aspetti essenziali: il metodo con cui le richieste vengono inviate ai real server (parametro real, che definisce il packet forwarding method), il tipo di servizio erogato (parametro service) e la tipologia di bilanciamento (parametro scheduler).

real

Ad un server reale corrisponde un indirizzo IP, una porta ed il metodo con cui i pacchetti passano dal virtuale ai reali. Può essere indicato anche il peso di ciascun real server nel caso in cui se ne possiedano con caratteristiche diverse, tale valore di default è 1 e salvo casi particolari può essere omesso. Essenziale però è il “packet forwarding method” che può essere uno di questi valori:

  • gate: che prevede l’utilizzo del direct routing in cui le richieste arrivano al server reale e questo risponde direttamente al client che ha contattato il servizio bilanciato.
  • masq: che prevede l’utilizzo della tecnica di masquerading (network address translation o NAT), dove le risposte dei server reali passano sempre dal bilanciatore che maschera il traffico in modo che appaia al client come proveniente da se stesso.
  • ipip: che prevede l’incapsulamento dei pacchetti arrivati al server bilanciato per la loro immissione all’interno di una sotto rete composta da interfacce virtuali.

La tipologia prevista nel progetto descritto si rifà al metodo gate in quanto i real server risiedono tutti sulla stessa rete (vedi prima puntata). masq è generalmente impiegato quando i real server ed il bilanciatore risiedono su reti differenti, mentre il metodo ipip è tra i tre il più particolare non verrà trattato in questa serie. Approfondimenti in merito agli argomenti descritti, che riguardano LVS nel dettaglio sono disponibili nell’LVS howto, in particolare ai seguenti link :

Direct routing (gate) : http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/LVS-HOWTO.LVS-DR.html

Tun (ipip) : http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/LVS-HOWTO.LVS-Tun.html

Masquerade (masq): http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/LVS-HOWTO.LVS-NAT.html

Service

Il tipo di servizio associato ad un servizio virtuale può essere uno fra ftp, smtp, http, pop, pops, nntp, imap, imaps, ldap, https, dns, mysql, pgsql, sip e none . Il nome di ogni servizio è autoesplicativo. Ldirectord come scritto in precedenza permette anche di effettuare il monitor dei servizi. Questo significa che un servizio oltre a rispondere alla porta associata (che nell’esempio illustrato è la 80) potrà essere interrogato per restituire dei risultati aspettati. Le quattro righe dell’esempio:

service=http
request="index.html"
receive="It Works!”
virtualhost=www.esempio.com

definiscono che il servizio è di tipo http (service), che per i check dovrà essere contattata la pagina index.html (request) e che all’interno di questa dovrà essere contenuto il testo “It Works!” (receive). Il tutto sarà associato al virtual host www.esempio.com. Se questa richiesta non verrà esaudita, il real server verrà dichiarato morto ed escluso quindi dal bilanciamento.

scheduler

L’ultimo parametro da comprendere è quello dello scheduler che rappresenta la tipologia di bilanciamento adottata dall’indirizzo virtuale. I valori possibili per il tipo di scheduler sono i seguenti:

rr – Robin Robin: Distribuisce i lavori equamente sui real server disponibili.

wrr – Weighted Round Robin: assegna i lavori ai real server in base al loro peso. Ad un peso maggiore da parte del real server corrisponderanno più lavori assegnati. Se i server hanno tutti lo stesso peso allora i lavori saranno distribuiti in forma equa.

lc – Least-Connection: assegna più lavori ai server con minor numero di lavori attivi.

wlc – Weighted Least-Connection: assegna più lavori ai server con minor numero di lavori attivi ed in base al peso che è stato loro assegnato. Questo è il default.

lblc – Locality-Based Least-Connection: assegna lavori destinati allo stesso indirizzo IP al medesimo server se questo non è sovraccarico ed è disponibile, in alternativa assegna i lavori ai real server scarichi, ricordando l’associazione nei futuri assegnamenti.

lblcr – Locality-Based Least-Connection with Replication: assegna i lavori destinati allo stesso indirizzo IP al nodo con il minor numero di lavori attivi nel gruppo di server creato per servire le richieste provenienti da questo. Se tutti i nodi del gruppo di server sono sovraccarichi, il lavoro viene accodato al nodo del cluster con il numero minore di lavori che diventa parte del gruppo di server. Se il gruppo di server non è stato modificato per un tempo specifico, allora il server più carico viene rimosso dal gruppo in modo che possa evadere le richieste in coda e garantire di essere replica alle future richieste.

dh – Destination Hashing: assegna i lavori ai real server basandosi sul controllo di un valore di hash assegnato staticamente in base all’indirizzo IP di destinazione.

sh – Source Hashing: assegna i lavori ai real server basandosi sul controllo di un valore di hash assegnato staticamente in base all’indirizzo IP sorgente.

sed – Shortest Expected Delay: assegna un lavoro entrante al real server dal quale si aspetta il minor tempo di attesa. Il tempo di attesa per un lavoro è calcolato con la formula (Ci + 1) / Ui dove Ci è il numero di lavori sul server stesso e Ui è il peso (weight) di questo definito in configurazione.

nq – Never Queue: assegna un lavoro entrante ad un real server inattivo (se c’è) anziché attendere per un real server veloce. Se tutti i real server sono occupati, adotta la tecnica “sed” (vedi sopra) per assegnare il lavoro.

La scelta del tipo di scheduler dipenderà quindi dalla tipologia di servizi impiegati e del tipo di real server dei quali si dispone. Nel caso illustrato lo scheduler è il più semplice, cioè il round robin che assegnerà le richieste in maniera equa su tutti i real server.

Aggiunta del servizio ldirectord a heartbeat

Per fare in modo che heartbeat gestisca la risorsa ldirectord all’interno del file /etc/ha.d/haresources basterà apportare le seguenti modifiche per entrambi i nodi del cluster:

ha-balancer-1 Ipaddr::192.168.0.100/24/eth0 ldirectord::/etc/ha.d/ldirectord.cf

Quanto aggiunto comprende la dichiarazione della risorsa ed il relativo file di configurazione. Per attivare la nuova configurazione sarà sufficiente effettuare il reload del servizio, sempre su entrambi i nodi del cluster:

/etc/init.d/heartbeat reload

La verifica della corretta aggiunta delle regole relative ad LVS è ottenibile attraverso il comando ipvsadm:

/sbin/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.0.100:80 rr
-> 192.168.0.50:80              Route   1      0          0
-> 192.168.0.51:80              Route   1      0          0
-> 192.168.0.52:80              Route   1      0          0

Tale output conferma che esiste un indirizzo virtuale che bilancia su tre server reali alla porta 80. Tutti i server reali sono raggiungibili ed hanno perciò peso 1 (non avendo specificato preferenze di peso nella loro dichiarazione) che comporta un’eguale distribuzione dei lavori.

Abilitazione del packet forwarding

L’ultima operazione da svolgere sul bilanciatore è quella dell’abilitazione del packet forwarding, necessario affinché le richieste possano passare attraverso il server. Tale funzionalità si ottiene abilitando la seguente riga:

net.ipv4.conf.default.forwarding=1

nel file /etc/sysctl.conf e forzando un nuovo caricamento di questo file, che trasferirà nel kernel quanto dichiarato:

sysctl -p

Ovviamente le stesse operazioni dovranno essere effettuate sul nodo del cluster passivo.

Modifiche sui server reali

Prima di effettuare i test di funzionamento è necessario apportare le ultime modifiche ai server reali. Infatti questi devono essere configurati in modo da vedere il traffico diretto all’indirizzo virtuale come locale. Per fare ciò sarà necessario creare un alias dell’interfaccia di loopback che abbia l’indirizzo virtuale e che questo indirizzo non venga annunciato via ARP sulla rete. Per rendere possibile tutto questo nel file /etc/sysctl.conf è necessario aggiungere le seguenti righe:

net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.eth0.arp_announce = 2

Insieme alla dichiarazione della nuova interfaccia nel file /etc/network/interfaces:

auto lo:0
iface lo:0 inet static
address 192.168.0.100
netmask 255.255.255.255
pre-up sysctl -p > /dev/null

L’ultima riga, che effettua un nuovo caricamento delle regole relative a sysctl, attiva le variazioni sul comportamento ARP a livello di kernel. Tali regole saranno attivate con l’interfaccia, attraverso il comando ifup:

ifup lo:0

Il motivo di queste variazioni è insito nella struttura del progetto: quando una richiesta arriva all’indirizzo virtuale e questo la dirige su un real server sarà il real server stesso a rispondere, per via del fatto di possedere lo stesso indirizzo (nell’interfaccia loopback), questo indirizzo però non dovrà essere annunciato sulla rete in modo da non confondere gli switch ed i router implicati nello smistamento dei pacchetti. Va sottolineato che queste variazioni andranno apportate a tutti i real server facenti parte dell’LVS.

Maggiori dettagli su questo tema che può risultare ostico sono ottenibili ai seguenti link:
http://www.ultramonkey.org/3/topologies/hc-ha-lb-eg.html dove viene descritto un progetto simile.
http://kb.linuxvirtualserver.org/wiki/Using_arp_announce/arp_ignore_to_disable_ARP dove vengono descritte le configurazioni possibili per il comportamento degli annunci ARP.

Test di funzionamento

Il test di funzionamento dell’ambiente consiste nel controllo dei log del servizio apache2 su ciascun real server:

tail -f /var/log/apache2/access.log

Inviando poi richieste al sito a mano oppure attraverso software specifici per i test di carico, come http_load si potrà verificare come le richieste vengano correttamente distribuite sui tre server. Un’ulteriore verifica potrà essere effettuata sul bilanciatore dove l’output prodotto dal comando ipvsadm mostrerà per ciascun real server nei campi “ActiveConn” e “InActConn” un numero diverso da zero.

Conclusioni

Nel prossimo articolo, ultimo di questa serie, verrà infine trattata la configurazione di postfix sui real server e l’inclusione del servizio nel bilanciatore.

La serie comprende questi articoli :

Postfix in alta affidabilità e massima performance con heartbeat, LVS ed ldirectord (1 di 4)
Postfix in alta affidabilità e massima performance con heartbeat, LVS ed ldirectord (2 di 4)
Postfix in alta affidabilità e massima performance con heartbeat, LVS ed ldirectord (3 di 4)
Postfix in alta affidabilità e massima performance con heartbeat, LVS ed ldirectord (4 di 4)

Nota :

Questo articolo è originariamente apparso su Tux Journal nell’Ottobre 2008.

Da sempre appassionato del mondo open-source e di Linux nel 2009 ho fondato il portale Mia Mamma Usa Linux! per condividere articoli, notizie ed in generale tutto quello che riguarda il mondo del pinguino, con particolare attenzione alle tematiche di interoperabilità, HA e cloud.
E, sì, mia mamma usa Linux dal 2009.

Tags: , , , , ,