Ridondiamo un controller MooseFS con uCarp

Tra tutti i filesystem cluster, il mio preferito è senza dubbio MooseFS in quanto è sicuramente il più collaudato nell’aggiunta dei nodi e quello più facile da gestire in caso di problemi.

L’unica nota dolente di questo filesystem è la necessità di avere un controller che rappresenta un Single Point of Failure; gli sviluppatori di MooseFS sono ben consci del problema ed è in roadmap la funzionalità di ridondanza del controller per le prossime versioni; nel frattempo, come consigliato sul sito ufficiale, possiamo fare riferimento ad un qualsiasi sistema di configurazione Fault Tolerance per ridondare il Controller. In questo articolo ci addentreremo più nello specifico rispetto a quanto fatto in precedenza nella configurazione dell’alta affidabilità del server master e per farlo, come consiglato dal sito ufficiale, utilizzeremo uCarp che è un sistema molto più semplice rispetto ai più conosciuti Heartbeat, Pacemaker e Corosync, ma che proprio per questo rappresenta una valida alternativa nei sistemi specializzati come i controller MooseFS. A dire il vero, una caratteristica di uCarp, è quella di poter avere un numero qualsiasi di server slave che possono diventare master e quindi aumentare l’affidabilità passiva del sistema: in questo articolo proporremo un sistema con un totale di 3 server, proprio per dimostrare questa funzionalità.

Innanzi tutto, spieghiamo in parole semplici come è strutturato MooseFS: il sistema si compone di un controller (mfsmaster) al quale si collegano una serie di server storage (chunck server) ove risiedono i “chunk”. In pratica, sullo storage condiviso di ogni nodo, è presente un albero di directory contenenti dei file di dimensioni prestabilite (i cosidetti chunck) che contengono le informazioni dei file salvati sul filesystem; vediamo i chunck come dei blocchi di disco di livello più elevato. Analogamente ai filesystem classici, anche su MooseFS esiste un indice dove è memorizzata la struttura del filesystem (in pratica di quali chunk è composto un file) e questo è il compito principale del controller: questo indice dei file è memorizzato nel “Metadata” che è mantenuto nella memoria RAM del controller.
Nel momento in cui avviene un arresto “soft” del controller, il contenuto della RAM, viene trasferito su disco nel file metadata.mfs; nel momento in cui il demone mfsmaster viene farro ripartire, questo file viene letto in RAM e, quindi, viene ricostruita la struttura del filesystem distribuito.
Il fatto di memorizzare il metadata in RAM, rende MooseFS più veloce rispetto ad altri Filesystem distribuiti… ma lo rende più sensibile ai guasti.

In aiuto ci viene un terzo demone, mfsmetadata: questo si prende la briga di collegarsi periodicamente al demone mfsmaster e salvare un “changelog” per ricostruire la struttura del filesystem in caso di arresto non soft; data la delicatezza delle informazioni contenute nel metadata, è consigliabile utilizzare il demone mfsmetadata su più server in modo da avere più punti di recupero del sistema e riuscire a far ripartire il cluster anche in caso di guasto all’hard disk del server master.

Proprio sull’utilizzo di questo demone si basa il funzionamento del sistema di fault tolerance che andremo ad implementare e, grazie alla possibilità di uCarp di far partire uno script nel momento in cui un server diventa master, implementeremo tutte le procedure necessarie per ricosturire automaticamente il file metadata.

Server master: ip 172.16.20.1
Server slave 1: ip 172.16.20.2
Server slave 2: ip 172.16.20.3

IP condiviso: 172.16.20.100

Innanzi tutto, sui server master e slave, installiamo i demoni mfsmaster e mfsmetadata come descritto in questo articolo e in questo articolo.

Ora, per andare oltre rispetto alla precedente installazione, installiamo il demone uCarp sui tre server. Ammettendo di avere un server Debian o Ubuntu, usiamo apt-get:

apt-get install ucarp

Ora è arrivato il momento di configurare uCarp per gestire l’IP condiviso e i demoni di MooseFS; per fare ciò utilizzeremo quattro semplici script in bash:

<strong>/usr/local/sbin/ucarp_startup - server master</strong>
#!/bin/bash

ucarp -i eth1 -s 172.16.20.1 -v 10 -p secret -a 172.16.160.100 -u /usr/local/sbin/vip-up -d /usr/local/sbin/vip-down -B -z

<strong>/usr/local/sbin/ucarp_startup - server slave 1</strong>
#!/bin/bash

ucarp -i eth1 -s 172.16.20.2 -v 10 -p secret -a 172.16.160.100 -u /usr/local/sbin/vip-up -d /usr/local/sbin/vip-down -B -z

<strong>/usr/local/sbin/ucarp_startup - server slave 2</strong>
#!/bin/bash

ucarp -i eth1 -s 172.16.20.3 -v 10 -p secret -a 172.16.160.100 -u /usr/local/sbin/vip-up -d /usr/local/sbin/vip-down -B -z

Attraverso questo script, (una sola riga) avviamo sui server il demone uCarp. I parametri che impostiamo sono:

  • -i eth1: è la scheda di rete fisica dove “appoggiare” il demone uCarp

  • -s 172.16.20.1,2 e 3: sono gli indirizzi IP reali della scheda di rete

  • -v 10: è un numero di riferimento dell’interfaccia virtuale creata da uCarp; va bene un qualsiasi numero da 1 a 255, basta che sia identico sui due server

  • -p secret: è una password comune sui server

  • -a 172.16.20.100: è l’indirizzo IP “condiviso” tra i server

  • -u /usr/local/sbin/vip-up: è lo script che sarà eseguito quando il server diventerà master (vedi oltre)

  • -d /usr/local/sbin/vip-down: è lo script che sarà eseguito quando il server diventerà slave (vedi oltre)

  • -B: esegue il demone in background

  • -z: esegue lo script impostato al parametro -d quando viene chiuso il demone uCarp (per sicurezza)

    /usr/local/sbin/vip-up

    !/bin/bash

    exec 2> /dev/null

    ip addr add “$2”/24 dev “$1”
    /usr/local/sbin/metadata_recover &
    exit 0

Questo script viene eseguito quando il demone uCarp reputa di eleggere a master il server e viene lanciato con due parametri: l’interfaccia di rete ($1) e l’indirizzo IP condiviso ($2).
Lo script aggiunge quindi l’indirizzo ip condiviso (172.16.20.100) alla scheda di rete (eth1) e lancia un secondo script in background (/usr/local/sbin/metadata_recover) che vedremo successivamente.

<b>/usr/local/sbin/vip-down</b>
#! /bin/sh
exec 2> /dev/null

ip addr del "$2"/24 dev "$1"

Lo script qui sopra è analogo al precedente ma serve a declassare un server in slave; pertanto viene lanciato il comando per cancellare l’indirizzo ip condiviso dalla scheda di rete.

<b>/usr/local/sbin/metadata_recover </b>
#!/bin/bash
MFS='/usr/local/var/mfs'
sleep 3

if ip a s eth1 | grep 'inet 172.16.20.100'
then
    mkdir -p $MFS/{bak,tmp}
    cp $MFS/changelog.* $MFS/metadata.* $MFS/tmp/

    kill $(pidof mfsmetalogger)
    mfsmetarestore -a

    if [ -e $MFS/metadata.mfs ]
    then
        mv -p $MFS/sessions_ml.mfs $MFS/sessions.mfs
        mfsmaster
        mfscgiserv
        mfsmetalogger
    else
        kill $(pidof ucarp)
    fi
    tar cvaf $MFS/bak/metabak.$(date +%s).tlz $MFS/tmp/*
    rm -rf $MFS/tmp
fi

Questo è lo script che fa il grosso del lavoro e viene lanciato da vip-up quando un server diventa master.
Innanzi tutto setto la directory di lavoro del server (/usr/local/var/mfs) e attendo 3 secondi in modo da essere certo che l’IP condiviso sia settato sull’interfaccia di rete. Se è così procedo con lo script che sposta eventuali vecchi file changelog. e metadata. in una directory temporanea. ferma il demone del metalogger (non essendoci un master funzionante è meglio che questo demone sia temporaneamente fermato) e lancia lo script mfsmetarestore in grado di estrapolare i dati dai file changelog_ml. e creare un nuovo file metadata.mfs.
Se lo script riesce nel suo intento, viene ripristinato il file sessions.mfs contenete le sessioni dei client collegati al server e vengono avviati i demoni di mfsmaster, mfsmetalogger e mfscgiserv (l’interfaccia web di controllo): fino a questo momento, i server che montano il filesystem non ricevono risposta dal server; da questo momento in poi il sistema riprenderà a funzionare regolarmente.
Nel caso in cui lo script mfsmetarestore non dovesse riuscire a ricostrire il file metadata.mfs, lo script ferma il demone uCarp e quindi concede la possibilità ad un ulteriore server slave, se presente, di diventare master.
Ultima operazione, viene creato un file di backup con il contenuto dei vecchi file metadata.
e changelog.*… non si sa mai.