Evoluzione dell’alta affidabilità su Linux: confronto pratico tra Heartbeat classico ed Heartbeat con Pacemaker

33

linux-ha    Pacemaker

Nel precedente articolo è stata affrontata l’evoluzione del progetto Heartbeat, dalla versione iniziale in cui il supporto era limitato a due macchine e con un CRM (Cluster Resource Manager) dalle funzionalità ridotte, per arrivare all’evoluzione del progetto culminata in Pacemaker, il CRM avanzato con il quale è possibile specificare priorità, ordini e dipendenze delle risorse al fine di ottenere il controllo totale su quanto erogato dal cluster.
In questo nuovo articolo viene analizzata a fondo, con un esempio pratico, la configurazione delle due modalità operative di Heartbeat, al fine di effettuare un confronto sul funzionamento del cluster con e senza Pacemaker.

Versioni di Heartbeat ed installazione

Fino alla versione 3 il progetto Heartbeat era un unico monolite contenente tutte le componenti funzionali all’esecuzione del software. L’evoluzione del programma ha comportato la suddivisione dello stesso in sotto progetti, ciascuno sviluppato indipendentemente rispetto agli altri, ma critico per una specifica funzione all’interno dell’architettura cluster.
Ad oggi l’intero progetto Heartbeat è quindi suddiviso in tre componenti:

  1. Heartbeat: comprendente il demone heartbeat, fornitore dell’infrastruttura cluster;
  2. Cluster Glue: un insieme di librerie con scopi specifici:
    • LRM (Local Resource Manager): incaricato di ricevere le istruzioni dal CRM, passarle ai Resource Agents e riportarne l’esito;
    • STONITH (Shoot The Other Node In The Head): incaricato di gestire situazioni ambigue in cui una risorsa potrebbe essere utilizzata contemporaneamente da più nodi;
    • hb_report: incaricato di fornire dettagli sugli errori che si verificano nel sistema;
    • Cluster Plumbing Library:una libreria per la comunicazioni interne al cluster;
  3. Resource Agents: comprendente un insieme di script standard per le risorse del cluster;

A ciascuna di queste componenti corrisponde un pacchetto scaricabile dalla sezione downloads del sito di Heartbeat: http://www.linux-ha.com/wiki/Downloads.
Le maggiori distribuzioni al momento distribuiscono ancora pacchetti di Heartbeat nelle versioni precedenti alla 3.
Scegliendo di utilizzare la versione più recente di ciascun software, è quindi possibile ricompilare manualmente i pacchetti partendo dai sorgenti oppure utilizzare pacchetti ricompilati.
Nel caso si usasse Debian Lenny è possibile dichiarare il seguente repository all’interno del file /etc/apt/sources.list:

deb http://people.debian.org/~madkiss/ha lenny main

Mentre per Ubuntu Hardy Heron i repository sono i seguenti:

deb http://ppa.launchpad.net/ubuntu-ha/ppa/ubuntu karmic main 

Ubuntu Lucid Lynx supporta invece la versione più recente della suite Heartbeat.

Per l’installazione sarà quindi necessario utilizzare lo strumento di gestione pacchetti fornito con la propria distribuzione: apt per Debian ed Ubuntu, yast per SuSe/OpenSuse e yum per CentOS/RedHat.

L’esempio che verrà implementato nel corso dell’articolo prevede la messa in alta affidabilità di due servizi nelle due versioni di Heartbeat: un indirizzo IP ed il webserver apache2. Il presupposto da cui si partirà è quello di avere un cluster composto da due nodi, collegati ciascuno alla rete locale (192.168.1.0/24) e l’uno all’altro da un cavo cross (10.0.0.0/24).

Configurazione di Heartbeat in modalità classica (senza CRM)

Sebbene Heartbeat sia giunto ormai alla versione 3.0.3 ed il CRM sia stato introdotto dalla versione 2, la modalità predefinita con cui il software viene avviato è quella senza CRM.
Qualsiasi configurazione Heartbeat 1.x quindi funzionerà verosimilmente su tutte le versioni successive.
Al di là delle innovazioni a livello software apportate al progetto, il principio di funzionamento senza CRM rimane quindi invariato, così come i file di configurazione necessari al funzionamento del cluster, come illustrato nel precedente articolo.
Il primo di questi è /etc/ha.d/ha.cf, il cui contenuto dovrà essere simile a quanto segue (ed identico in entrambi i nodi):

##      keepalive: how long between heartbeats?
keepalive 1
##      deadtime: how long-to-declare-host-dead?
deadtime 10
##      warntime: how long before issuing "late heartbeat" warning?
warntime 5
##      Very first dead time (initdead)
initdead 20
##      What interfaces to unicast heartbeats over?
ucast eth1 10.0.0.1
ucast eth1 10.0.0.2
ucast eth0 192.168.1.86
ucast eth0 192.168.1.66
##      Should we autofailback?
auto_failback off
##      Who is part of the cluster?
node    debian-lenny-nodo1
node    debian-lenny-nodo2
##      Network monitoring
ping 192.168.1.50
respawn hacluster /usr/lib/heartbeat/ipfail
apiauth ipfail gid=haclient uid=hacluster

I commenti presenti all’interno del listato rendono le opzioni autoesplicative. Particolare attenzione va posta relativamente ad alcune opzioni:

auto_failback si riferisce alle risorse: se impostata ad “on” nel momento in cui una risorsa effettua uno switch su un nodo differente dall’attuale (per via di un malfunzionamento di quest’ultimo) nel momento in cui il nodo tornerà attivo la risorsa effettuerà un nuovo switch.

ping definisce un indirizzo ip che verrà usato come riferimento per capire se un nodo è parte della rete: “vedendo” l’indirizzo indicato il nodo avrà coscienza di essere presente sulla rete. A tutti gli effetti l’ip indicato è considerato un nodo del cluster, pertanto dovrà essere un ip affidabile, ad esempio quello del gateway di rete. E’ inoltre possibile definire un gruppo di ip, attraverso la direttiva ping_group in modo da non affidarsi ad un unico host per il monitoring.

respawn e apiauth definiscono rispettivamente un comando e l’utente con cui questo deve essere lanciato. Insieme alla definizione del nodo ping completano la parte di monitoraggio della connettività necessaria ad Heartbeat per regolarsi in caso di connettività limitata od assente.

Le ultime tre opzioni descritte, come apparirà chiaro in seguito, risultano di importanza critica in configurazioni senza CRM.

Il secondo file essenziale alla costruzione del cluster è /etc/ha.d/haresources:

debian-lenny-nodo1 IPaddr::192.168.1.200/24/eth0 apache2

Il contenuto definisce il nodo master per le due risorse definite: l’indirizzo ip 192.168.1.200 (associato all’interfaccia eth0) e apache2, il demone che controlla il webserver. Entrambe le risorse verranno quindi, in condizioni normali, avviate sul nodo identificato come debian-lenny-nodo1.

L’ultimo file ad essere creato è /etc/ha.d/authkeys e contiene le informazioni per la sicurezza delle comunicazioni tra i due nodi. Non essendo vincolante ai fini del progetto avere una comunicazione criptata tra i nodi, il contenuto del file può essere il seguente:

auth 1
1 crc

Che sta ad indicare come non esisterà sicurezza nella comunicazione fra i nodi (eccettuato il controllo sulla corruzione dei pacchetti).

Prima di avviare il demone per la prima volta ed effettuare i test è necessario accertarsi che il demone apache non venga avviato al boot del sistema, poiché verrà gestito da heartbeat. In Debian/Ubuntu si può rimuovere così:

# update-rc.d -f apache2 remove

Mentre in RedHat/Centos/Opensuse il comando da usare è chkconfig:

# chkconfig --level 123456 apache2 off

A questo punto è possibile avviare su entrambi i nodi il demone heartbeat:

# /etc/init.d/heartbeat start

dopo alcuni minuti i servizi dovrebbero salire sul nodo che secondo quanto impostato nella configurazione sarà master, debian-lenny-nodo1. Il tutto è verificabile attraverso il controllo sullo stato dell’interfaccia eth0:0:

# ifconfig eth0:0
eth0:0    Link encap:Ethernet  HWaddr 08:00:27:59:18:22  
          inet addr:192.168.1.200  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Interrupt:10 Base address:0xd020 

E sull’effettiva esecuzione del demone apache2:

# ps -ef| grep apache
root      2052     1  0 11:30 ?        00:00:00 /usr/sbin/apache2 -k start
www-data  2053  2052  0 11:30 ?        00:00:00 /usr/sbin/apache2 -k start
www-data  2054  2052  0 11:30 ?        00:00:00 /usr/sbin/apache2 -k start
www-data  2057  2052  0 11:30 ?        00:00:00 /usr/sbin/apache2 -k start

Test di Heartbeat in modalità classica (senza CRM)

Il comportamento nelle varie situazione del demone heartbeat è osservabile attraverso il principale file di log di sistema, su entrambi i nodi:

tail -f /var/log/syslog

Primo test: disconnessione cavo LAN

Il primo test riguarderà la disconnessione del cavo di rete LAN relativo al nodo master, l’operazione genererà alcune righe di log, la più importante delle quali, sull’unico nodo rimasto attivo in rete, riporterà quanto segue:

...
ResourceManager[14403]: [14415]: info: Acquiring resource group: debian-lenny-nodo1 IPaddr::192.168.1.200/24/eth0 apache2
...

l’indicazione è chiara: le risorse sono state acquisite dal nodo secondario. A rilevare l’assenza di connettività è stato, come precedentemente illustrato, l’esegubile ipfail.

Secondo test: disconnessione cavo Heartbeat

Il secondo test prevede la rimozione del cavo che collega i due nodi del cluster:

...
Apr  8 16:24:16 debian-lenny-nodo1 kernel: [17722.012482] eth1: link down
Apr  8 16:24:25 debian-lenny-nodo1 heartbeat: [14269]: info: Link debian-lenny-nodo2:eth1 dead.
Apr  8 16:24:25 debian-lenny-nodo1 ipfail: [14297]: info: Link Status update: Link debian-lenny-nodo2/eth1 now has status dead
Apr  8 16:24:25 debian-lenny-nodo1 ipfail: [14297]: debug: Found ping node 192.168.1.50!
Apr  8 16:24:26 debian-lenny-nodo1 ipfail: [14297]: info: Asking other side for ping node count.
Apr  8 16:24:26 debian-lenny-nodo1 ipfail: [14297]: debug: Message [num_ping] sent.
Apr  8 16:24:26 debian-lenny-nodo1 ipfail: [14297]: info: Checking remote count of ping nodes.
Apr  8 16:24:27 debian-lenny-nodo1 ipfail: [14297]: debug: Got asked for num_ping.
Apr  8 16:24:27 debian-lenny-nodo1 ipfail: [14297]: debug: Found ping node 192.168.1.50!
Apr  8 16:24:28 debian-lenny-nodo1 ipfail: [14297]: info: Ping node count is balanced.
Apr  8 16:24:28 debian-lenny-nodo1 ipfail: [14297]: debug: Abort message sent.
Apr  8 16:24:28 debian-lenny-nodo1 ipfail: [14297]: info: No giveup timer to abort.
...

I messaggi riguardano l’interfaccia secondaria e, come è osservabile, la perdita di questa interfaccia non provoca alcun tipo di switch, in quanto la comunicazione tra i nodi funziona ancora attraverso l’interfaccia primaria, quindi attraverso la LAN.

Terzo test: spegnimento improvviso nodo master

Il terzo test consiste nella rimozione improvvisa dell’alimentazione relativa al nodo master:

Apr  8 16:24:16 debian-lenny-nodo2 heartbeat: [8170]: WARN: node debian-lenny-nodo1: is dead
Apr  8 16:24:16 debian-lenny-nodo2 ipfail: [8233]: info: Status update: Node debian-lenny-nodo1 now has status dead
...
...
Apr  8 16:24:16 debian-lenny-nodo2 ResourceManager[8913]: [8925]: info: Acquiring resource group: debian-lenny-nodo1 IPaddr::192.168.1.200/24/eth0 apache2
Apr  8 16:24:17 debian-lenny-nodo2 ipfail: [8233]: debug: Found ping node 192.168.1.50!
Apr  8 16:24:17 debian-lenny-nodo2 IPaddr[8937]: [8972]: INFO:  Resource is stopped
Apr  8 16:24:17 debian-lenny-nodo2 ResourceManager[8913]: [8987]: info: Running /etc/ha.d/resource.d/IPaddr 192.168.1.200/24/eth0 start
Apr  8 16:24:17 debian-lenny-nodo2 ipfail: [8233]: info: NS: We are still alive!
...
...

Lo switch avviene in maniera corretta, è possibile notare il messaggio “We are still alive!” che indica come il nodo secondario abbia rilevato che il nodo primario sia assente, acquisendone le risorse, una volta accertato il proprio grado di connettività con la rete.

Quarto test: migrazione manuale delle risorse

Heartbeat dispone di un ristretto set di comandi che consentono di interagire con le risorse. Questi comandi sono contenuti nella cartella /usr/share/heartbeat/, ed il comando che consente di gestire le risorse dichiarate è hb_takeover, la cui sintassi d’impiego è la seguente:

# /usr/share/heartbeat/hb_standby all|foreign|local|failback

I parametri passabili al comando comprendono la possibilità da parte di un nodo di acquisire tutte le risorse (all), le risorse del nodo secondario (foreign), le risorse di proprietà (local), le risorse precedentemente migrate (failback).
Nel caso che si vuole simulare il nodo secondario lancerà il seguente comando:

# /usr/share/heartbeat/hb_standby foreign

Ed il comportamento del cluster, osservabile dal nodo primario, sarà il seguente:

Apr  8 16:28:36 debian-lenny-nodo1 heartbeat: [14269]: info: debian-lenny-nodo1 wants to go standby [local]
Apr  8 16:28:36 debian-lenny-nodo1 heartbeat: [14269]: info: standby: debian-lenny-nodo2 can take our local resources
Apr  8 16:28:36 debian-lenny-nodo1 heartbeat: [14859]: info: give up local HA resources (standby).
Apr  8 16:28:36 debian-lenny-nodo1 ResourceManager[14872]: [14884]: info: Releasing resource group: debian-lenny-nodo1 IPaddr::192.168.1.200/24/eth0 apache2
Apr  8 16:28:36 debian-lenny-nodo1 ResourceManager[14872]: [14895]: info: Running /etc/init.d/apache2  stop
Apr  8 16:28:38 debian-lenny-nodo1 ResourceManager[14872]: [14929]: info: Running /etc/ha.d/resource.d/IPaddr 192.168.1.200/24/eth0 stop
Apr  8 16:28:38 debian-lenny-nodo1 IPaddr[14956]: [14968]: INFO: ifconfig eth0:0 down
Apr  8 16:28:38 debian-lenny-nodo1 IPaddr[14930]: [14972]: INFO:  Success

Le risorse sono state correttamente spostate su debian-lenny-nodo2.

Quinto test: standby manuale di un nodo

Il quinto test della serie prevederà la messa in standby del nodo attivo, al fine di verificare il corretto spostamento delle risorse. Il controllo di questa funzionalità da parte del cluster è possibile mediante lo stesso comando precedentemente illustrato, lanciato senza argomenti (che equivale a lanciarlo parametro “all”) sul secondo nodo:

# /usr/share/heartbeat/hb_standby

Il comportamento è il seguente:

Apr  8 16:29:48 debian-lenny-nodo1 heartbeat: [14269]: info: debian-lenny-nodo2 wants to go standby [all]
Apr  8 16:29:49 debian-lenny-nodo1 ipfail: [14297]: debug: Other side is unstable.
Apr  8 16:29:51 debian-lenny-nodo1 heartbeat: [14269]: info: standby: acquire [all] resources from debian-lenny-nodo2
Apr  8 16:29:51 debian-lenny-nodo1 heartbeat: [14974]: info: acquire all HA resources (standby).
Apr  8 16:29:51 debian-lenny-nodo1 ResourceManager[14987]: [14999]: info: Acquiring resource group: debian-lenny-nodo1 IPaddr::192.168.1.200/24/eth0 apache2
Apr  8 16:29:52 debian-lenny-nodo1 IPaddr[15011]: [15046]: INFO:  Resource is stopped
Apr  8 16:29:52 debian-lenny-nodo1 ResourceManager[14987]: [15061]: info: Running /etc/ha.d/resource.d/IPaddr 192.168.1.200/24/eth0 start
Apr  8 16:29:53 debian-lenny-nodo1 IPaddr[15088]: [15121]: INFO: Using calculated netmask for 192.168.1.200: 255.255.255.0
Apr  8 16:29:53 debian-lenny-nodo1 IPaddr[15088]: [15143]: INFO: eval ifconfig eth0:0 192.168.1.200 netmask 255.255.255.0 broadcast 192.168.1.255
Apr  8 16:29:53 debian-lenny-nodo1 IPaddr[15062]: [15162]: INFO:  Success
Apr  8 16:29:53 debian-lenny-nodo1 ResourceManager[14987]: [15183]: info: Running /etc/init.d/apache2  start

Tutte le risorse vengono acquisite dal nodo debian-lenny-nodo2.

Sesto test: interruzione manuale di un servizio

L’ultimo test della serie comprende lo stop manuale di uno dei servizi erogati. Ad esempio apache:

# /etc/init.d/apache2 stop

è facile verificare come nessuna azione venga svolta da Heartbeat, il servizio infatti rimane spento, e l’unica via per fare in modo che il cluster lo riavvii è quella di mandare in standby manualmente il nodo.

Gli ultimi tre test mostrano come in realtà il controllo manuale del cluster sia unicamente la simulazione della messa in standby di un nodo o lo stop di un servizio attivo. Lo standby non avviene in maniera totale, il nodo non viene escluso dal cluster, semplicemente rilascia le proprie risorse e lo stesso vale per i servizi.
Quanto descritto rappresenta una grossa differenza nei confronti dell’utilizzo del CRM Pacemaker, ed il concetto sarà ancora più chiaro nei paragrafi successivi.

Configurazione di Heartbeat in modalità CRM con Pacemaker

L’esecuzione di Heartbeat in modalità CRM prevede che nel sistema sia installato il pacchetto Pacemaker. Questo pacchetto è disponibile nelle maggiori distribuzioni (e nei repository indicati nel primo capitolo dell’articolo) e tra le varie librerie e file che installa uno su tutti sarà fondamentale nel proseguo dell’articolo: /usr/sbin/crm. Come verrà illustrato in seguito il comando crm consente di interagire direttamente con il cluster, il suo comportamento e la sua configurazione.
Prima di procedere è necessario predisporre nuovamente il file di configurazione /etc/ha.d/ha.cf con questo contenuto, su entrambi i nodi:

autojoin none
keepalive 1
deadtime 10
warntime 5
initdead 20
mcast eth0 239.0.0.43 694 1 0
bcast eth1
node    debian-lenny-nodo1
node    debian-lenny-nodo2
crm respawn

Le differenze con la precedente configurazione sono subito evidenti. Esiste una nuova opzione chiamata autojoin none che disabilita la funzione automatica di scoperta ed aggiunta di nodi sulla rete, inoltre sono state modificate le informazioni relative alla rete: non viene più definito un unicast per ciascuna interfaccia interessate alla comunicazione del cluster, i pacchetti viaggeranno in multicast per la rete locale ed in broadcast per la rete non condivisa (il cavo cross che collega le due macchine).
Infine, l’opzione crm respawn indica che il cluster userà il Cluster Resource Manager, Pacemaker.
Va sottolineato come siano assenti i parametri relativi al monitoraggio della connettività, che verrà gestita in maniera totale da Pacemaker.
E’ chiaro come in questa configurazione il file /etc/ha.d/haresources non ha più ragione di esistere in quanto, così come spiegato nel precedente articolo, a preoccuparsi della gestione delle risorse è il CRM stesso.
Il file relativo al protocollo di comunicazione e sicurezza /etc/ha.d/authkeys rimane invece identico.

E’ quindi possibile avviare Heartbeat per la prima volta:

# /etc/init.d/heartbeat start

Le fasi di avvio sono visibili attraverso il log, oppure utilizzando il già citato comando crm con il parametro status.
Inizialmente lo stato del cluster sarà il seguente:

# crm status
============
Last updated: Wed Jun 16 11:34:38 2010
Current DC: NONE
0 Nodes configured, unknown expected votes
0 Resources configured.
============

Dopo qualche minuto, una volta che i nodi avranno avviato le comunicazioni la situazione varierà in questa forma:

# crm status
============
Last updated: Wed Jun 16 11:35:48 2010
Stack: Heartbeat
Current DC: debian-lenny-nodo2 (e1f7faf3-7152-4c51-bfc4-b5382944a62e) - partition with quorum
Version: 1.0.8-2c98138c2f070fcb6ddeab1084154cffbf44ba75
2 Nodes configured, unknown expected votes
0 Resources configured.
============

Online: [ debian-lenny-nodo1 debian-lenny-nodo2 ]

Il cluster può dirsi così avviato. Sebbene non ci siano risorse configurate (“0 Resources configured.“) i due nodi configurati risultano “Online”, pronti cioè ad erogare risorse e debian-lenny-nodo2 ha il ruolo di DC, Designated Coordinator, il nodo “master” che guiderà cioè le operazioni.

Qualsiasi tipo di configurazione sul cluster può essere effettuata attraverso il comando crm, mediante il parametro configure seguito dalle impostazioni da modificare.
Di seguito in quattro fasi viene illustrata una configurazione che rispetti fedelmente quanto fatto per la versione senza CRM.

Prima fase: comportamento generale del cluster

# crm configure property stonith-enabled="false"

Disabilitazione dello stonith: come anticipato in apertura di articolo, lo stonith prevede la configurazione di device specifici che possano essere guidati al fine di spegnere immediatamente un nodo in situazioni in cui non si ha la certezza di quale nodo sia ancora vivo. Nel caso illustrato la configurazione dello stonith verrà pertanto disabilitato.
Una interessante documentazione su come configurare lo stonith su Heartbeat è disponibile sul sito Novell, a
questo indirizzo
.

# crm configure property no-quorum-policy="ignore"

Non considerazione dell’assenza di quorum: se la locazione comune dei dati relativi al cluster (quorum) non sarà accessibile da parte dei nodi, il cluster non dovrà prendere alcun provvedimento. Le opzioni disponibili sono ignore, stop, freeze e suicide.
Il valore stop porterà il cluster a fermare ordinatamente tutte le risorse.
Il valore freeze consentirà al cluster di continuare ad erogare le risorse in esecuzione senza però avviarne di nuove.
Il valore suicide obbligherà il cluster a spegnere immediatamente tutti i nodi con limitato accesso al quorum.

Chiaramente le due opzioni stonith-enabled e no-quorum-policy non vengono considerate nella configurazione classica. Il concetto di quorum e stonith si applica solo a cluster gestiti da CRM, in cui esiste una memoria comune.

Seconda fase: controllo della connettività

Il controllo della connettività con Pacemaker è possibile attraverso la definizione di una risorsa denominata “ping”:

# crm configure primitive ping ocf:pacemaker:ping params host_list="192.168.1.1" name="ping" op monitor interval="10s" timeout="60s" op start timeout="60s" op stop timeout="60s"

Il comando crea una risorsa (primitive) denominata ping, il cui Resource Agent (RA) è di tipo ocf, fornito da pacemaker: il path effettivo dell’eseguibile sarà quindi /usr/lib/ocf/resource.d/pacemaker/ping (si veda l’articolo precedente per l’approfondimento sulle tipologie di resource agent e loro posizionamento).
Il RA supporta diversi parametri, fra questi host_list deve contenere la lista degli host da controllare per verificare la connettività (in questo caso il gateway di rete) e name dovrà corrispondere al nome interno della risorsa (si veda la quarta fase).
Infine le indicazioni che seguono le voci “op” (abbreviazione di operations) consentono di definire le politiche di monitoring della risorsa: come deve essere controllata (ad intervalli di 10 secondi e con 60 secondi di timeout) ed in quanto tempo si deve avviare e fermare (entro i 60 secondi di timeout).

La definizione della risorsa ping non è però sufficiente per fornire ad ogni nodo uno strumento per il controllo della connettività, poiché, definita nel modo indicato, la risorsa ping verrà eseguita su un unico nodo. Proprio per ovviare a questo problema e fare in modo che la stessa risorsa possa girare su più nodi è possibile clonarla:

# crm configure clone ping_clone ping meta globally-unique="false"

Il comando indica al cluster di creare la risorsa ping_clone che girerà su tutti i nodi, indistintamente (meta globally-unique=”false”).

Terza fase: definizione delle risorse

Per riprodurre il test e confrontarlo con il precedente rimangono da definire le due risorse scelte ip e apache. La risorsa ip verrà dichiarata come segue:

# crm configure primitive cluster-ip ocf:heartbeat:IPaddr2 params ip="192.168.1.200" nic="eth0" op monitor interval="10s" timeout="20s" op start timeout="20s" op stop timeout="20s"

il nome della risorsa è cluster-ip ed il resource agent utilizzato sarà di tipo OCF, con fornitore heartbeat.
I parametri comprendono l’indirizzo ip che verrà erogato ed il nic (la scheda di rete) a cui verrà associato.
Per quanto riguarda le politiche di monitoring vale quanto detto poco sopra per la risorsa ping.

Il servizio apache2 verrà dichiarato in maniera similare:

crm configure primitive cluster-apache2 ocf:heartbeat:apache params configfile="/etc/apache2/apache2.conf" httpd="/usr/sbin/apache2" port="80" op monitor interval="10s" timeout="60s" op start timeout="40s" op stop timeout="60s"

E’ da notare che il Resource Agent utilizzato non è, come per la configurazione di Heartbeat senza CRM, lo script di avvio del demone presente in /etc/init.d, ma un vero e proprio resource agent di tipo OCF. I parametri necessari al funzionamento sono il file di configurazione (configfile), l’eseguibile del demone (httpd) e la porta su cui apache sarà in ascolto (port).
Anche in questo caso per le opzioni di monitoring vale quanto espresso in precedenza.

Per completare la configurazione delle risorse verrà definito un gruppo, denominato cluster, a cui verranno associate le risorse definite:

# crm configure group cluster cluster-ip cluster-apache2

Il gruppo cluster potrà essere utilizzato nella configurazione come un unica risorsa, le cui operazioni di avvio e stop rispetteranno l’ordine indicato nella definizione: in fase di start del gruppo cluster verrà avviato prima cluster-ip e poi cluster-apache2, in fase di stop verrà prima stoppato cluster-apache2 e poi cluster-ip.

Quarta fase: associazione delle risorse al nodo attivo

La configurazione del cluster, definiti i parametri di monitoraggio della connessione ed il gruppo delle risorse, potrebbe sembrare a questo punto completa:

# crm status
============
Last updated: Wed Jun 16 15:36:43 2010
Stack: Heartbeat
Current DC: debian-lenny-nodo2 (e1f7faf3-7152-4c51-bfc4-b5382944a62e) - partition with quorum
Version: 1.0.8-2c98138c2f070fcb6ddeab1084154cffbf44ba75
2 Nodes configured, unknown expected votes
2 Resources configured.
============

Online: [ debian-lenny-nodo1 debian-lenny-nodo2 ]

 Clone Set: ping_clone
     Started: [ debian-lenny-nodo1 debian-lenny-nodo2 ]
 Resource Group: cluster
     cluster-ip	(ocf::heartbeat:IPaddr2):	Started debian-lenny-nodo1
     cluster-apache2	(ocf::heartbeat:apache):	Started debian-lenny-nodo1

Ma non è così. E’ vero che al momento il cluster eroga quanto stabilito, ma non è ancora stato definito il comportamento da assumere in caso di assenza di connettività. Se infatti si dovesse rimuovere il cavo di rete LAN dal nodo debian-lenny-nodo1 le risorse non verrebbero automaticamente migrate sul secondo nodo.
Questo perché il cluster non è istruito a dovere in merito al comportamento da assumere a fronte di un esito negativo delle operazioni effettuate dalla risorsa clonata ping.
Quanto descritto rappresenta un’altra grossa differenza tra le due tipologie di funzionamento: in un caso la definizione di ipfail forzava lo standby delle risorse in autonomia (e minor controllo), con Pacemaker la filosofia cambia: tutto va definito, aggiungendo certamente complessità all’architettura, ma rendendo il controllo sul cluster totale.
Per definire quindi un vincolo sull’erogazione delle risorse è necessario definire una “location”:

# crm configure location cluster_on_connected_node cluster rule -inf: not_defined ping or ping lte 0

Viene definita cioè una regola denominata cluster_on_connected_node associata alla risorsa cluster che prevede di dare il peso di meno infinito (-inf, rendere cioè incapace di erogare risorse) al nodo in cui la risorsa nominata ping non sia definita (not_defined) o il cui codice di uscita sia minore o uguale a zero (lte 0 e quindi il comando ping non ha avuto esito positivo, il ping node non risponde).

Grazie a questa regola la struttura realizzata con Heartbeat e Pacemaker risulta l’esatta replica della soluzione Heartbeat senza CRM per comportamento e configurazione.

La configurazione completa

E’ possibile ottenere il resoconto della configurazione, completo di highlight attraverso il comando crm configure show:

# crm configure show
node $id="1984521f-539f-4967-b0ff-eb23f3cf9ccf" debian-lenny-nodo1
node $id="e1f7faf3-7152-4c51-bfc4-b5382944a62e" debian-lenny-nodo2
primitive cluster-apache2 ocf:heartbeat:apache \
	params configfile="/etc/apache2/apache2.conf" httpd="/usr/sbin/apache2" port="80" \
	op monitor interval="10s" timeout="60s" \
	op start interval="0" timeout="40s" \
	op stop interval="0" timeout="60s"
primitive cluster-ip ocf:heartbeat:IPaddr2 \
	params ip="192.168.1.200" nic="eth0" \
	op monitor interval="10s" timeout="20s" \
	op start interval="0" timeout="20s" \
	op stop interval="0" timeout="20s"
primitive ping ocf:pacemaker:ping \
	params host_list="192.168.1.1" name="ping" \
	op stop interval="0" timeout="60s" \
	op start interval="0" timeout="60s" \
	op monitor interval="10s" timeout="60s"
group cluster cluster-ip cluster-apache2
clone ping_clone ping \
	meta globally-unique="false"
location cluster_on_connected_node cluster \
	rule $id="cluster_on_connected_node-rule" -inf: not_defined ping or ping lte 0
property $id="cib-bootstrap-options" \
	dc-version="1.0.8-2c98138c2f070fcb6ddeab1084154cffbf44ba75" \
	cluster-infrastructure="Heartbeat" \
	stonith-enabled="false" \
	no-quorum-policy="ignore" \
	last-lrm-refresh="1276694458"

E’ da notare che oltre ad essere un comando invocabile con specifiche opzioni, crm può essere lanciato senza argomenti, in modo da accedere alla console di amministrazione interattiva che permette di controllare il cluster su tutti i livelli. Ad esempio digitando in sequenza:

# crm
crm(live)# configure
crm(live)configure# edit

Si accederà alla configurazione riportata sopra all’interno dell’editor di testo vi, questa configurazione potrà essere modificata a piacimento e salvata attraverso il comando vi “:wq”.
Le modifiche verranno applicate digitando:

crm(live)configure# commit

L’interfaccia analizzerà quanto digitato ed applicherà alla configurazione effettiva del cluster le modifiche, ovviamente se e soltanto se queste rispettano la sintassi e la struttura del cluster.

Test di Heartbeat in modalità CRM con Pacemaker

Anche nella configurazione con Pacemaker il comportamento di Heartbeat è osservabile dal file di log di sistema /var/log/syslog. La quantità di log relativa a questa configurazione di Heartbeat è decuplicata rispetto alla configurazione classica, il che rende a volte complicato seguire quanto avviene nel cluster. Un buon approccio in caso di disservizi o comportamenti divergenti da quanto ci si aspetta è quello di cercare parole chiave come “error” o “warning” in modo da evidenziare subito potenziali problemi.

Primo test: disconnessione cavo LAN

Il comportamento di Heartbeat nei confronti della disconnessione del cavo LAN è il seguente (vengono riportate solo alcune righe del log del nodo attivo):

Jun 17 17:11:42 debian-lenny-nodo1 attrd: [2426]: info: attrd_trigger_update: Sending flush op to all hosts for: ping (0)
...
Jun 17 17:11:43 debian-lenny-nodo1 lrmd: [2424]: info: rsc:cluster-apache2:16: stop
...
Jun 17 17:11:46 debian-lenny-nodo1 lrmd: [2424]: info: rsc:cluster-ip:17: stop
...
Jun 17 17:11:49 debian-lenny-nodo1 lrmd: [2424]: info: perform_op:2873: operation monitor[11] on ocf::ping::ping:1 for client 2427, its parameters: CRM_meta_clone=[1] host_list=[192.168.1.1] 

Il nodo attivo segnala di aver perso connettività (leggendo la risposta del comando clonato ping) e procede con lo stop delle due risorse interessate (che verranno attivate sul nodo secondario, ovviamente se questo ha connettività).
Il nodo debian-lenny-nodo1 continua a tentare la connessione al nodo ping.
Da notare che debian-lenny-nodo1 non viene in alcuna maniera escluso dal cluster poiché l’interfaccia Heartbeat (il cavo che collega fra loro le due macchine) è attiva, garantendo la comunicazione dei due nodi.

Secondo test: disconnessione cavo Heartbeat

La rimozione del cavo heartbeat, così come il secondo test di Heartbeat senza CRM, non comporta alcuna variazione nello stato del cluster:

Jun 18 10:57:12 debian-lenny-nodo1 kernel: [ 3020.112982] eth1: link down
Jun 18 10:57:20 debian-lenny-nodo1 heartbeat: [11076]: info: Link debian-lenny-nodo2:eth1 dead.

Viene unicamente rilevata (sia dal kernel che da heartbeat) l’assenza di connettività sull’interfaccia eth1, ma la comunicazione del cluster è ancora garantita dal link eth0.

Terzo test: spegnimento improvviso nodo master

Ecco cosa avviene all’atto di spegnimento improvviso del nodo erogante i servizi:

Jun 18 11:00:44 debian-lenny-nodo1 heartbeat: [11076]: WARN: node debian-lenny-nodo2: is dead
Jun 18 11:00:44 debian-lenny-nodo1 heartbeat: [11076]: info: Link debian-lenny-nodo2:eth0 dead.
Jun 18 11:00:44 debian-lenny-nodo1 heartbeat: [11076]: info: Link debian-lenny-nodo2:eth1 dead.
...
Jun 18 11:00:45 debian-lenny-nodo1 crmd: [11091]: WARN: check_dead_member: Our DC node (debian-lenny-nodo2) left the cluster
...
Jun 18 11:00:48 debian-lenny-nodo1 crmd: [11091]: info: do_dc_takeover: Taking over DC status for this partition
...
Jun 18 11:00:53 debian-lenny-nodo1 pengine: [12660]: notice: unpack_config: On loss of CCM Quorum: Ignore
...
Jun 18 11:00:53 debian-lenny-nodo1 lrmd: [11088]: info: rsc:cluster-ip:13: start
...
Jun 18 11:00:53 debian-lenny-nodo1 lrmd: [11088]: info: rsc:cluster-apache2:15: start

In sequenza quanto avviene sul nodo sopravvissuto è:

  • linea 1,2,3) Rilevazione della perdita di connettività totale con l’altro nodo;
  • linea 5) Rilevazione della perdita di DC;
  • linea 7) Presa i carico da parte del nodo attuale del ruolo di DC;
  • linea 9) Come da configurazione l’assenza di quorum viene ignorata;
  • linea 11,13) Avvio dei servizi;

Il nodo debian-lenny-nodo1 ha quindi preso in carico la totalità delle risorse, in maniera automatica.

Quarto test: migrazione manuale delle risorse

La migrazione manuale delle risorse è possibile sempre attraverso l’utilizzo del comando crm:

# crm resource migrate cluster debian-lenny-nodo2

In questo caso, il gruppo di risorse cluster viene migrato dal nodo attuale al nodo debian-lenny-nodo2: è possibile migrare indistintamente un gruppo o una singola risorsa, ma se questa fa parte del gruppo, allora tutto il gruppo verrà migrato.
La migrazione della risorsa genera automaticamente un’aggiunta nella configurazione del cluster di questo tipo:

location cli-prefer-cluster cluster \
	rule $id="cli-prefer-rule-cluster" inf: #uname eq debian-lenny-nodo2

il cui scopo è chiaro: la regola infatti indica al cluster di dare priorità inf (ossia infinità) all’esecuzione della risorsa cluster sul nodo il cui comando uname equivale a debian-lenny-nodo2. Non a caso, la regola viene automaticamente battezzata “cli-prefer-cluster”. Va chiarito che sebbene il peso della regola sia infinito, questa decade in caso il nodo preferito smetta di funzionare.
E’ possibile ripristinare la migrazione attraverso il comando inverso:

# crm resource unmigrate cluster

Tale operazione ripristinerà la situazione precedente, rimuovendo la regola aggiunta all’interno della configurazione.

Quinto test: standby manuale di un nodo

Anche la messa in standby di un nodo è effettuabile attraverso il comando crm:

# crm node standby debian-lenny-nodo1

Lo stato del cluster al termine di questa operazione sarà quindi il seguente:

...
Node debian-lenny-nodo1 (1984521f-539f-4967-b0ff-eb23f3cf9ccf): standby
Online: [ debian-lenny-nodo2 ]

 Clone Set: ping_clone
     Started: [ debian-lenny-nodo2 ]
     Stopped: [ ping:0 ]
 Resource Group: cluster
     cluster-ip (ocf::heartbeat:IPaddr2):       Started debian-lenny-nodo2
     cluster-apache2    (ocf::heartbeat:apache):        Started debian-lenny-nodo2

Le risorse vengono correttamente migrate sul nodo secondario ed il nodo primario viene messo in stato “standby”. Per ripristinare la situazione è sufficiente anche in questo caso forzare debian-lenny-nodo1 a tornare online:

# crm node online debian-lenny-nodo1

Sesto test: interruzione manuale di un servizio

L’ultimo test della serie prevede l’interruzione manuale di un servizio. Verrà simulato il crash del servizio apache2 tramite un comando kill, Il presupposto è che il servizio apache2 sia in esecuzione su debian-lenny-nodo1:

# killall apache2

Ecco le operazioni che il cluster esegue per porre rimedio alla situazione:

Jun 18 11:29:21 debian-lenny-nodo1 apache[24129]: [24187]: INFO: apache not running
...
Jun 18 11:29:21 debian-lenny-nodo1 crmd: [11091]: WARN: update_failcount: Updating failcount for cluster-apache2 on debian-lenny-nodo1 after failed monitor: rc=7 (update=value++, time=1276853361)
...
Jun 18 11:29:22 debian-lenny-nodo1 lrmd: [11088]: info: rsc:cluster-apache2:45: start

In sequenza quello che avviene è:

  • linea 1) Il monitor ha rilevato che il servizio non sta funzionando;
  • linea 3) Pacemaker aggiorna il conteggio dei disservizi relativi alla risorsa cluster-apache2;
  • linea 5) La risorsa viene nuovamente eseguita;

La risorsa è di nuovo attiva e funzionante.

E’ possibile monitorare in maniera costante lo stato del cluster attraverso il comando crm_mon il cui funzionamento consiste nell’esecuzione del comando crm status ad intervalli regolari. crm_mon supporta il parametro –failcount che permette di avere un sommario dei disservizi rilevati sul cluster. Nell’esempio illustrato, l’output del comando sarà il seguente:

...
Online: [ debian-lenny-nodo1 debian-lenny-nodo2 ]

 Clone Set: ping_clone
     Started: [ debian-lenny-nodo1 debian-lenny-nodo2 ]
 Resource Group: cluster
     cluster-ip (ocf::heartbeat:IPaddr2):       Started debian-lenny-nodo1
     cluster-apache2    (ocf::heartbeat:apache):        Started debian-lenny-nodo1

Migration summary:
* Node debian-lenny-nodo1: 
   ping:0: migration-threshold=1000000 fail-count=1
   cluster-apache2: migration-threshold=1000000 fail-count=1
* Node debian-lenny-nodo2:

Il Migration summary presenta la situazione relativa alle risorse intaccate dai nostri test, il cui conteggio dei disservizi è 1 (fail-count=1).
E’ possibile azzerare tale conteggio effettuando un cleanup della risorsa:

# crm resource cleanup cluster-apache2
Cleaning up cluster-apache2 on debian-lenny-nodo1
Cleaning up cluster-apache2 on debian-lenny-nodo2

Conclusioni

Giunti al termine di questo lunghissimo articolo le conclusioni da trarre sono molteplici. La prima di queste è che l’argomento Heartbeat/Pacemaker risulta tutt’altro che esaurito: esistono moltissime altre componenti del progetto che qui non sono state nemmeno accennate. Certo è che da questo confronto balza subito all’occhio come le differenze tra i due tipi di impiego siano sostanziali. La soluzione Heartbeat/Pacemaker sebbene sia evidentemente complicata offre un controllo insperato su tutte le componenti del cluster, oltre ad un monitoraggio costante di tutte le risorse configurate. L’implementazione della soluzione classica è immediata, ma come si è visto limitata.
La scelta su quale sia la scelta migliore per la propria infrastruttura è unicamente dell’utente, che come sempre nel mondo OpenSource è libero di scegliere, sperimentare e realizzare.
Nel prossimo articolo verrà presentata una soluzione Heartbeat/Pacemaker per implementare uno Storage NFS Active/Active basato su DRBD.

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.