Progetto

Generale

Profilo

SetupClusterHA » Cronologia » Versione 38

Versione 37 (Amministratore Truelite, 03-10-2006 11:57) → Versione 38/53 (Amministratore Truelite, 03-10-2006 15:06)

[[TracNav(TOC)]] 
 = Configurazione di un Cluster HA = 

 In questo caso per ''Cluster HA'' si intende un sistema composto da due macchine (dette nodi) in configurazione attivo/passivo, su cui viene gestita automaticamente la sincronizzazione dei dati attraverso DRDB, e lo ''switch'' automatico dei servizi in caso di crollo del nodo attivo con l'uso di ''heartbeat''. 

 == Predisposizione delle due macchine del Cluster == 

 Per un buon funzionamento del cluster è quantomeno opportuno poter disporre di una interfaccia di rete in più, dedicata alla comunicazione diretta fra i due nodi; questo è importante anche per evitare errori nella rilevazione di un crollo (che normalmente viene fatta tramite una connessione di rete, anche se è possibile usare un collegamento seriale) qualora ad andare giù fosse lo ''switch'' e non un singolo nodo. Disponendo dell'hardware necessario (interruttori controllabili da remoto) si può installare ''stonith'' per assicurarsi dello spegnimento dell'altro nodo in caso di ''switch''. 

 Negli esempi seguenti si supporrà allora che ciascuna macchina abbia almeno due interfacce di rete; la prima, {{{eth0}}}, connessa alla rete locale, la seconda, {{{eth1}}}, connessa direttamente all'altra macchina con un cavo incrociato. Sulla prima interfaccia dovremo configurare l'indirizzo pubblico di ciascuna macchina (nel nostro caso {{{10.10.0.98}}} e {{{10.10.0.99}}}) inteso come indirizzo diretto del singolo nodo del cluster, a questo si aggiungerà l'indirizzo del ''cluster'' in quanto tale (tenuto sulla macchina che fa da nodo primario, che migrerà sull'altra in caso di si ''switch'') che nel nostro caso sarà {{{10.10.0.2}}}. Sulla seconda interfaccia metteremo degli indirizzi privati (nel caso dell'esempio dell'esmepio {{{198.168.234.1}}} e {{{198.168.234.2}}}) usati per la sincronizzazione di DRBD e per il controllo di ''heartbeat''. 

 Per poter utilizzare la sincronizzazione dei dati con DRBD occorre predisporre i dischi delle due macchine riservando lo spazio opportuno. Per questo occorrono due partizioni su ciascuna macchina (in realtà si potrebbe fare tutto con una sola, ma questo comporta che gli ultimi 128Mb della partizione devono essere lasciati liberi ed il filesystem presente su di essa opportunamento ridimensionato). La prima partizione sarà quella su cui si mantengono i dati, la seconda deve essere di almeno 128Mb e serve per i metadati usati da DRBD, la partizione dei dati deve essere approssimativamente della stessa dimensione su entrambe le macchine. 


 == Configurazione di DRBD == 

 Il primo passo consiste nell'installazione dei pacchetti necessari, questi nel caso di Debian Sarge sono due: i programmi di gestione di DRBD forniti da {{{drbd0.7-utils}}}, ed i sorgenti del modulo del kernel che gestisce la replicazione dei dati forniti da {{{drbd0.7-module-source}}}. Questo modulo, {{{drbd}}}, può essere installato a mano, nel qual caso si dovrà compilare ed installare dai sorgenti in {{{/usr/src}}}, altrimenti si può utilizzare il programma {{{module-assistant}}} che si incaricherà anche di scaricare tutti gli ulteriori pacchetti necessari, di compilare il modulo per il kernel corrente e di installarlo.  

 Prima di attivare la replicazione dei dati con DRBD occorre eseguirne la configurazione; il file da modificare è {{{/etc/drbd.conf}}}, dove dovremo indicare per ciascuna macchina quali sono i dispositivi da usare e su quale indirizzo contattare l'altro nodo; i singoli nodi dovranno essere identificati con il loro ''hostname'' (viene sempre usato il risultato del comando {{{uname -n}}}), e nel nostro caso saranno {{{servint1}}} e {{{servint2}}}. 
 Il contenuto finale di {{{/etc/drbd.conf}}} dovrebbe essere allora qualcosa del tipo: 
 {{{ 
 resource r0 { 
   protocol C; 
   incon-degr-cmd "echo '!DRBD! pri on incon-degr' | wall ; sleep 60 ; halt -f"; 
   startup { 
     degr-wfc-timeout 120;      # 2 minutes. 
   } 
   disk { 
     on-io-error     detach; 
   } 
   net { 
   } 
   syncer { 
     rate 10M; 
     group 1; 
     al-extents 257; 
   } 
   on servint1 { 
     device       /dev/drbd0; 
     disk         /dev/md3; 
     address      192.168.234.1:7788; 
     meta-disk    /dev/hda7[0]; 
   } 
   on servint2 { 
     device      /dev/drbd0; 
     disk        /dev/hda5; 
     address     192.168.234.2:7788; 
     meta-disk /dev/hda7[0]; 
   } 
 } 
 }}} 
 tenendo conto che su {{{servint1}}} i dati vengono mantenuti sul dispositivo RAID {{{/dev/md3}}} ed i metadati sulla partizione {{{/dev/hda7}}}, mentre su {{{servint2}}} i dati sono su {{{/dev/hda5}}} ed i metadati su {{{/dev/hda7}}}. 

 Qualora si vogliano utilizzare più dispositivi occorrerà utilizzare altrettante voci di {{{resource}}}; per ciascuna di esse andrà indicato un diverso {{{device}}} (ad esempio {{{/dev/drbd1}}}, {{{/dev/drbd2}}}, ecc.) ed ovviamente i rispettivi dischi (o partizioni), si abbia poi cura di usare un diverso valore di {{{address}}} (ad esempio si potrà cambiare la porta con in qualcosa del tipo {{{192.168.234.2:7789}}}).  

 Inoltre se questi nuovi dispositivi fanno riferimento agli stessi dischi fisici (ad esempio a diverse partizioni su uno stesso disco) si abbia cura di cambiare il valore della direttiva {{{group}}} nella sezione {{{syncer}}}, poiché la sincronizzazione viene serializzata in ordine crescente ascente di questo valore (e se i dipositivi fanno riferimento agli stessi dischi questo è appunto il comportamento voluto).  

 Una volta completata la configurazione di {{{/etc/drbd.conf}}} su uno dei nodi si abbia cura di copiarlo sull'altro perché la configurazione deve essere identica su entrambe le macchine; dopo di che si potrà caricare il modulo {{{drbd}}} ed attivare il servizio con i comandi: 
 {{{ 
 modprobe drbd 
 drbdadm up all 
 }}} 
 ripetendo l'operazione su entrambe le macchine. Se si è messo un firewall locale sulle macchine si ricordi di dare accesso alla porta 7788 TCP, o quella che si è specificata nel file di configurazione. Più configurazione, più semplicemente si consenta l'accesso dall'interfaccia {{{eth1}}}. Se tutto è a posto si potrà verificare lo stato di funzionamento di DRBD con: 
 {{{ 
 servint1:~# cat /proc/drbd 
 version: 0.7.10 (api:77/proto:74) 
 SVN Revision: 1743 build by phil@mescal, 2005-01-31 12:22:07 
  0: cs:Connected st:Secondary/Secondary ld:Inconsistent 
     ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 
  1: cs:Unconfigured 
 }}} 
 che ci dice che le due macchine si vedono fra loro, ma anche che lo stato di DRBD è inconsistente ed che i dischi sono entrambi classificati come secondari. A questo punto si potrà definire quale dei due dischi è il primario (quello che deve essere copiato sul secondario), ed iniziare la sincronizzazione dei dispositivi con il comando: 
 {{{ 
 drbdadm -- --do-what-I-say primary all 
 }}} 
 che va dato sulla macchina (nel nostro caso {{{servint1}}}) che fa da nodo primario. Fatto questo avremo: 
 {{{ 
 servint1:~# cat /proc/drbd 
 version: 0.7.10 (api:77/proto:74) 
 SVN Revision: 1743 build by phil@mescal, 2005-01-31 12:22:07 
  0: cs:SyncSource st:Primary/Secondary ld:Consistent 
     ns:360356 nr:0 dw:0 dr:361240 al:0 bm:21 lo:135 pe:36 ua:221 ap:0 
         [>...................] sync'ed:    0.6% (69265/69617)M 
         finish: 1:44:47 speed: 11,252 (10,288) K/sec 
  1: cs:Unconfigured 
 }}} 
 che ci mostra l'inizio della sincronizzazione dei dati, mostrando la velocità di trasmissione degli stessi (è quella fissata dalla direttiva {{{rate}}} nella sezione {{{syncer}}}) ed una stima del tempo necessario per completarla. 

 A questo punto si tratterà solo di attendere il tempo necessario perché venga eseguita la sincronizzazione via rete (la prima volta può essere piuttosto lungo), ed una volta che questa sarà completata avremo sul nodo primario qualcosa del tipo: 
 {{{ 
 servint1:~# cat /proc/drbd 
 version: 0.7.10 (api:77/proto:74) 
 SVN Revision: 1743 build by phil@mescal, 2005-01-31 12:22:07 
  0: cs:Connected st:Primary/Secondary ld:Consistent 
     ns:71288320 nr:0 dw:0 dr:71288320 al:0 bm:4352 lo:0 pe:0 ua:0 ap:0 
  1: cs:Unconfigured 
 }}} 
 mentre sul nodo secondario avremo qualcosa del tipo: 
 {{{ 
 servint2:~# cat /proc/drbd 
 version: 0.7.10 (api:77/proto:74) 
 SVN Revision: 1743 build by phil@mescal, 2005-01-31 12:22:07 
  0: cs:Connected st:Secondary/Primary ld:Consistent 
     ns:3028 nr:0 dw:0 dr:3028 al:0 bm:15 lo:0 pe:0 ua:0 ap:0 
  1: cs:Unconfigured 
 }}} 
 e come si può notare i ruoli dei dispositivi sono invertiti. 

 Adesso potremo verificare il funzionamento del sistema montando (sempre sulla macchina che fa da primario) il dispositivo {{{/dev/drbd0}}}, che conterrà quello che era presente sul dispositivo {{{/dev/md3}}}, (nel nostro caso un filesystem ext3) oppure utilizzare direttamente il dispositivo stesso per creare (qualora non fosse stato fatto in precedenza come nel nostro caso) un nuovo filesystem. 

 Una volta completata la sincronizzazione iniziale si potrà attivare o disattivare DRBD direttamente con lo script di avvio {{{/etc/init.d/drbd}}}; se per un qualche motivo la sincronizzazione si dovesse perdere, una volta bloccato il servizio si potrà ripetere la procedura precedente per risincronizzare i dispositivi, avendo ovviamente cura di impostare come primario quello che contiene i dati corretti (fare '''SEMPRE''' un backup prima di una operazione del genere!). 


 == Configurazione di heartbeat == 

 Una volta completata la configurazione di DRBD si può configurare ''heartbeat''. Il pacchetto da intallare è appunto {{{heartbeat}}}, la cui configurazione viene mantenuta in {{{/etc/ha.d}}}. Nel caso di Debian occorre anche copiare due file di configurazione, {{{ha.cf}}} e {{{haresources}}}, che di proposito non vengono installati dal pacchetto, ma di cui esiste uno scheletro in forma compressa sotto {{{/usr/src/doc/heartbeat}}}. Occorreranno cioè i comandi: 
 {{{ 
 cd /usr/share/doc/heartbeat 
 zcat ha.cf.gz > /etc/ha.d/ha.cf 
 zcat haresources.gz > /etc/ha.d/haresources 
 }}} 

 A questo punto si dovranno eseguire le impostazioni che ci servono, i file precedenti sono ampiamente commentati. Per quanto riguarda {{{ha.cf}}} occorre impostare il tempo oltre il quale, in assenza di risposta, si considera un nodo morto ({{{deadtime}}}), la modalità con cui i nodi si verificano (nel caso via rete sull'interfaccia dedicata {{{eth1}}}) ed i nomi dei due nodi (anche qui devono corrispondere a quanto restituito dal comando {{{uname -n}}}). Il contenuto di questo file (eliminati i commenti) dovrebbe essere qualcosa del tipo: 
 {{{ 
 logfacility       local0 
 keepalive 2 
 deadtime 30 
 bcast    eth1 
 auto_failback on 
 node servint1 servint2 
 }}} 

 Per quanto riguarda {{{haresources}}} occorre invece indicare quali sono le risorse che dovranno essere gestite da ''haertbeat'' in caso di ''switch''; inizieremo soltanto con il volume condiviso, l'IP pubblico del cluster, ed il montaggio del volume, pertanto avremo qualcosa del tipo: 
 {{{ 
 servint1 IPaddr::10.10.0.3/16/eth0 drbddisk::r0 Filesystem::/dev/drbd0::/home::ext3 
 }}} 

 Infine per autenticare la comunicazione fra i due demoni occorre impostare una chiave, questa deve essere immessa nel file {{{/etc/ha.d/authkeys}}}; al solito esiste uno scheletro in {{{/usr/src/doc/heartbeat}}} che si può copiare con: 
 {{{ 
 cp authkeys /etc/ha.d/ 
 chmod 600 /etc/ha.d/authkeys 
 }}} 
 e qui andrà specificata la modalità di autenticazione ed inserita la password, con qualcosa del tipo: 
 {{{ 
 auth 2 
 2 sha1 unabellapasswordbellalungaemoltocomplicata 
 }}} 

 A questo punto si potrà avviare ''heartbeat'' direttamente con lo script di avvio lanciando il comando: 
 {{{ 
 /etc/init.d/heartbeat start 
 }}} 
 e (occorre qualche secondo) verificare con {{{df}}} che è stato montato {{{/dev/drbd0}}} (nel nostro caso su {{{/home}}}), e verificare con {{{ifconfig}}} che è stato aggiunto ad {{{eth0}}} l'IP del cluster (nel nostro caso {{{10.10.0.3}}}). 


 == La configurazione dei servizi == 

 Per la configurazione di un servizio in HA è necessario che questo sia attivato su un solo nodo del cluster; questo significa che gli script di avvio non devono essere chiamati in fase di boot, ma lanciati direttamente da ''heartbeat''. Dato che l'installazione standard dei servizi di Debian li attiva su tutti i ''runlevel'' occorrerà allora disattivarli. Pertanto utilizzando DHCP, DNS, NFS, CUPS, LDAP, Apache e Samba sarà necessario eseguire una serie di comandi di rimozione con {{{update-rc.d}}}, la cosa può essere realizzata in una soluzione unica con qualcosa del tipo: 
 {{{ 
 for i in samba slapd nfs-kernel-server nfs-common dhcp3-server cupsys bind9 apache2 
 do 
   update-rc.d -f $i remove 
 done 
 }}} 
 (si tenga conto che nell'upgrade di un pacchetto l'attivazione dei servizi viene in genere ripristinata su tutti i runlevel, collegamenti potrebbero essere ripristinati, si verifichi sempre che le cose siano a posto). 

 Un secondo requisito della gestione dei servizi è che gli eventuali dati interni che essi salvano (in genere sotto {{{/var/lib}}}) siano sincronizzati con DRBD cosicché essi possano essere disponibili in caso di passaggio al nodo secondario.    Nel nostro caso i servizi attivati sono DHCP, DNS, CUPS, LDAP, Apache e Samba e occorrerà identificare le directory dei dati usate da questi servizi per ricrearle sul disco replicato da DRBD. Questo è stato fatto sul nodo principale con i seguenti comandi: 
 {{{ 
 mkdir -p /home/var/lib 
 for i in samba ldap nfs dhcp3 cups 
 do 
   mv /var/lib/$i /home/var/lib 
   ln -s /home/var/lib/$i /var/lib/$i 
 done 
 }}} 
 ed analogamente per BIND, i dati temporanei di Samba ed i dati di spool di CUPS: 
 {{{ 
 mkdir -p /home/var/cache 
 mv /var/cache/bind /home/var/cache 
 ln -s /home/var/cache/bind /var/cache/bind 
 mkdir -p /home/var/cache 
 mv /var/cache/samba /home/var/cache 
 ln -s /home/var/cache/samba /var/cache/samba 
 mkdir -p /home/var/spool 
 mv /var/spool/cups /home/var/spool 
 ln -s /home/var/spool/cups /var/spool/cups 
 }}} 
 mentre sul nodo secondario dovranno semplicemente essere cancellate le stesse directory sotto {{{/var}}} e creati al loro posto i corrispondenti link simbolici, che resteranno ''dangling'' fintanto che non verrà montato il dispositivo di DRBD (cosa fatta automaticamente da ''heartbeat'' in caso di ''switch''. 

 Infine se si vuole che le pagine web servite da Apache siano sincronizzate si dovrà spostare anche {{{/var/www}}} (in genere questo è sufficiente, se però si usano altre funzionalità di Apache, che utilizzano altre directory come {{{/var/cache/apache2}}} e {{{/var/lib/apache2}}} andranno spostate anche queste). Questo sul nodo primario si fa, come nel caso precedente, con: 
 {{{ 
 mkdir -p /home/var/www 
 mv /var/www /home/var 
 ln -s /home/var/www /var/www 
 }}} 
 mentre sul nodo secondario basterà creare la directory corrispondente. Il problema è però che in genere questo non basta, dato che sotto Apache possono girare una serie di ulteriori applicazioni web, i cui dati a loro volta verranno mantenuti altrove. In particolare qualora si usassere Subversion o Trac sulla macchina sarebbe necessario spostare sul disco condiviso le rispettive directory {{{/var/svn}}} e {{{/var/trac}}}. 

 Si tenga conto poi che essendo i servizi attivi sul cluster, essi verranno acceduti con l'indirizzo generico di quest'ultimo, per cui occorrerà configurarli in maniera identica su entrambi i nodi, e fare in modo che, dove richiesto, per il nome a dominio compaia sempre quello del cluster e non del singolo nodo e lo stesso per l'indirizzo IP. 

 Infine si tenga conto che il sistema di rotazione dei log (''logrotate'') in certi casi esegue il riavvio del servizio, anche se questo non è attivo (trattasi di un problema degli script di configurazione, ma ad esempio questo è quanto avviene con CUPS su Debian Sarge). Il che comporta che occorre assicurarsi che nessuno dei file di {{{/etc/logrotate.d/}}} esegua un riavvio senza prima controllare se il servizio è attivo, questo significa ad esempio modificare le righe seguenti: 
 {{{ 
 postrotate 
        [ -f /var/run/cups/cupsd.pid ] || invoke-rc.d --quiet cupsys restart > /dev/null && sleep 10 
 endscript 
 }}} 
 in {{{/etc/logrotate.d/cupsys}}}. 

 Per la configurazione di LDAP si rammenti di usare gli stessi certificati (e CA) su entrambe le macchine, si abbia anche cura di creare i certificati in modo che il nome corrisponda a quello del servizio dato sul cluster, altrimenti non si riuscirà ad accedervi con SSL. Sarà comunque utile inserire nei ''subjectAltName'' anche i valori degli indirizzi IP del cluster e dei singoli nodi. 

 Per il DHCP si abbia cura di usare lo stesso {{{dhcpd.conf}}} su entrambe le macchine, e si controlli anche che {{{/etc/default/dhcp3-server}}} sia identico e che faccia partire il demone specificando l'utilizzo dell'interfaccia corretta (che nel nostro caso è {{{eth0}}}) con qualcosa del tipo: 
 {{{ 
 INTERFACES="eth0" 
 }}} 
 si abbia cura inoltre di verificare l'esistenza di {{{/var/lib/dhcp3/dhcpd.leases}}}. 

 Per quanto riguarda Samba si abbia cura di impostare manualmente il nome del server in modo che corrisponda a quello del cluster, infatti il default è quello di usare il nome della macchina, che nel nostro caso è quello del singolo nodo. Inoltre si deve indicare a Samba di usare l'indirizzo di rete del cluster; pertanto si dovranno aggiungere alla sezione ''global'' di {{{smb.conf}}} le seguenti righe: 
 {{{ 
    netbios name = SERVINT 
    interfaces = 10.10.0.2 
    bind interfaces only = yes 
 }}}  

 Una volta finite le configurazioni di tutti i servizi occorrerà modificare {{{haresources}}} cosicché essi possano essere gestiti da ''heartbeat'' in caso di ''switch''. Questo si fa aggiungendo in coda alla riga mostrata in precedenza i nomi degli script di avvio, pertanto avremo qualcosa del tipo: 
 {{{ 
 servint1 IPaddr::10.10.0.3/16/eth0 drbddisk::r0 Filesystem::/dev/drbd0::/home::ext3 slapd samba bind9 dhcp3-server cupsys  
 }}}