DRBD and Highly Available NFS Server

Da Inc0Wiki.

Preambolo

L'implementazione è stata relizzata utilizzando 2 Ubuntu 8.04 virtualizzate tramite VMWare 2.0.

Scopo

In questa guida verrà spiegato come creare un server NFS ad alta disponibilità sfruttando DRBD ed heartbeat: il server sarà costituito da due server DRBD (primary + secondary) in failover con heartbeat .

Pacchetti Necessari

nfs-common - tool per montare file-system nfs
nfs-kernel-server - server nfs per rendere disponibili le risorse
drbd - software per la gestione del dispositivo a blocchi replicato via rete
heartbeat - software per l'alta affidaibilità
ntpdate - sincronizzazione dell'ora sul sistema

Un po' di teoria...

La configurazione prevede due nodi:
- vb-ubuntu4: 192.168.56.105
- vb-ubuntu5: 192.168.56.106

HA NFS.png

Quando entrambi attivi uno sarà il primario e l'altro il secondario; con drbd le scritture posso essere effettuate solo sul primario, diventa quindi evidente la necessità di dover individuare quale dei due nodi sia il primario quando entrambi attivi così da poter attivare l'ip virtuale (192.168.56.40) ed il server nfs su tale nodo e disattivarlo sul secondario; tali compiti sono affidati ad heartbeat.
E' inoltre molto importante che l'ora sui server che partecipano a drbd siano sincronizzati, per questo è buona normale installare un cron-job per la sincronizzazione dell'ora.

Configurazione

DRBD

DRBD richiede la creazione di due partizioni su entrambi i server: una di dimensione lievemente superiore a 128MB all'interno della quale saranno salvati i metadata necessari a drbd e l'altra nella quale saranno salavati i dati veri e propri che verrà resa disponibile tramite il block device creato da drbd.
Una volta installato il demone assicuriamoci che parta al boot in quanto tale demone si occupa della replicazione dei dati sui nodi: è quindi necessario che sia sempre in esecuzione.

Partizionamento

Creaiamo le due partizioni ma non creiamo alcun file-system.
NOTA: In questo caso, su entrambi i server è stato agganciato un disco secondario (/dev/sdb) sul quale sono state create due partizioni logiche (sdb5 e sdb6).
Generiamo il file di configurazione di drbd:

/etc/drbd.conf

common {
         syncer {
                 rate 100M;
         }
}

# Nome della Risorsa
resource ApacheDocRoot {
  protocol C;

  startup {
         wfc-timeout 10;
         degr-wfc-timeout  20;
  }
  disk {
         on-io-error detach;
  }
  # vb-ubuntu4 è l'hostname di uno dei nodi ('uname -n')
  # address: ip associato all'host (vb-ubuntu4)
  on vb-ubuntu4 {
    device      /dev/drbd0;
    disk        /dev/sdb6;
    address     192.168.56.105:7791;
    meta-disk   /dev/sdb5[0];
  }
  # vb-ubuntu5 è l'hostname di uno dei nodi ('uname -n')
  # address: ip associato all'host (vb-ubuntu5)
  on vb-ubuntu5 {
    device      /dev/drbd0;
    disk        /dev/sdb6;
    address     192.168.56.106:7791;
    meta-disk   /dev/sdb5[0];
  }
}

Inizializzazione

Possiamo procedere a questo punto all'inizializzazione delle risorse configurate in drbd.conf: questa operazione va eseguita solo alla prima inizilizzazione.
Prendendo come esempio la risorsa ApacheDocRoot, il metodo più veloce per renderla disponibile è:

# drbdadm up ApacheDocRoot

che svolge le seguenti operazioni:
crea i meta-data

# drbdadm create-md ApacheDocRoot

associa la risorsa al block device:

# drbdadm attach ApacheDocRoot

imposta i parametri di sincronizzazione tra le risorse

# drbdadm syncer ApacheDocRoot

collega le risorse tra di loro

# drbdadm connect ApacheDocRoot

Fatto ciò, le risorse saranno marcate come secondary: lo si può verificare digitando

# drbdadmin state ApacheDocRoot
Secondary/Secondary

E' necessario scegliere quale si vuole diventi primary ovvero quella che sarà possibile montare e sulla quale sarà possibile eseguire le scritture; fattò ciò bastera digitare:

# drbdadm -- --overwrite-data-of-peer primary ApacheDocRoot

e verificare l'avanzamento della sincronizzazione in /proc/drbd:

# cat /proc/drbd 
version: 8.0.11 (api:86/proto:86)
GIT-hash: b3fe2bdfd3b9f7c2f923186883eb9e2a0d3a5b1b build by phil@mescal, 2008-02-12 11:56:43
0: cs:SyncSource st:Primary/Secondary ds:UpToDate/Inconsistent C r---
    ns:67204 nr:0 dw:0 dr:75392 al:0 bm:4 lo:1 pe:4 ua:256 ap:0
	[>....................] sync'ed:  4.0% (1780340/1847444)K
	finish: 0:01:19 speed: 22,368 (22,368) K/sec
	resync: used:1/31 hits:4448 misses:5 starving:0 dirty:0 changed:5
	act_log: used:0/127 hits:0 misses:0 starving:0 dirty:0 changed:0

Volendo potete tenere sotto controllo l'operazione con

# watch cat /proc/drbd

E' ora possibile procedere con la creazione di un file-system sul block device tramite l'uso di mkfs.

NFS

Una volta installato nfs (nfs-common e nfs-kernel-server) è necessario assicurarsi che non parta all'avvio del sistema: ci penserà heartbeat ad avviarlo in base alla necessità:

# update-rc.d -f nfs-kernel-server remove
# update-rc.d -f nfs-common remove

Avendo deciso di montare il block-device creato da drbd in /mnt/NFSData, ed avendo deciso che i dati saranno contenuti nella sottocartella exports/, modifichiamo ora il file /etc/exports specificando il percorso:

/etc/exports

/mnt/NFSData/export/	 192.168.56.0/255.255.255.0(rw,no_root_squash,no_all_squash,sync)

La cartella /var/lib/nfs

A questo punto sorge però un problema: nfs salva informazioni importanti (ad esempio i lock sui file) all'interno della cartella /var/lib/nfs: cosa succederebbe se il server sul quale è attivo nfs crollasse e l'altro prendesse il suo posto e le informazioni in /var/lib/nfs fossero differenti? Per risolvere questo problema dobbiamo replicare queste informazioni tramite drbd quindi procediamo come segue: andiamo sul Primary, montiamo il block-device associato ad una risorsa:

# mount /dev/drbd0 /mnt/NFSData

spostiamo il contenuto di /var/lib/nfs in /mnt/NFSData

# mv /var/lib/nfs/ /mnt/NFSData/

creiamo in link simbolico di /mnt/NFSData/nfs in /var/lib chiamato nfs:

# ln -s /mnt/NFSData/nfs/ /var/lib/nfs

creiamo la cartella export (che sarà resa accessibile da nfs)

# mkdir /mnt/NFSData/export

smontiamo /mnt/NFSData:

# umount /mnt/NFSData

Sul nodo Secondary, cancelliamo o rinominiamo /var/lib/nfs/

# rm -fr /var/lib/nfs/

e creiamo un link simbolico in /var/lib/nfs/ alla risorsa drbd che replica le informazioni nfs:

# ln -s /mnt/NFSData/nfs/ /var/lib/nfs

Heartbeat

Procediamo ora installando heartbeat ed assicurandoci che venga avviato al boot:

# update-rc.d heartbeat defaults

ha.cf

Creiamo il file di configurazione ha.cf all'interno di /etc/ha.d/ sui server ed assicuriamoci che siano identici (cambiando i nomi delle interfacce di rete dove necessario):

/etc/ha.d/ha.cf
# log a syslog
logfacility local0

warntime 10
keepalive 1
deadtime 30
initdead 120

auto_failback off

# interfaccia e sottorete di multicast
mcast eth3 239.0.0.43 695 1 0

# nodi del cluster
node vb-ubuntu4
node vb-ubuntu5

respawn hacluster /usr/lib/heartbeat/ipfail
apiauth ipfail gid=haclient uid=hacluster

haresources

Prepariamo ora haresourcers che si trova sempre in /etc/ha.d: indipendentemente dal server sul quale si trova, il primo parametro, che nel caso attuale è vb-ubuntu4 DEVE essere uguale e deve rispecchiare l'output di uname -n eseguito sul primary. Tale file contiene:
- il nome del nodo che solitamente è considerato primary
- l'ip virtuale con netmask ed interfaccia di rete a cui è associato
- il block-device, il mount point ed il tipo di file-system che devono essere usati da heartbeat per montare la partizione da rendere disponibile via nfs
- i servizi da avviare se il nodo diventa Primary

/etc/ha.d/haresources
vb-ubuntu4 \
	IPaddr::192.168.56.40/24/eth3 \
	drbddisk::ApacheDocRoot \
	Filesystem::/dev/drbd0::/mnt/NFSData::ext3 \
	nfs-common \
	nfs-kernel-server

authkeys

Infine creiamo il file con la chiave da utilizzare tra i nodi del cluster per comunicare, tale file deve essere identico su tutti i server che partecipano al cluster:

/etc/ha.d/authkeys
auth 10
10 md5 VostraStringaSegreta

Note

split-brain detected: se riceve questo errore almeno uno dei nodi avrà le risorse in modalità StandAlone. Sarà necessario intervenire manualmente per ripristinare il normale funzionamento: è necessario scegliere un nodo dal quale scartare le modifiche e sul quale procedere alla risincronizzazione, su tale nodo digitare:

#drbdadm secondary [<resource>|all]
#drbdadm -- --discard-my-data connect [<resource>|all]

mentre sul nodo che si reputa integro

#drbdadm connect [<resource>|all]

Credits

Autore: Incubus

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