La necessità di differenziare…

Oggi facciamo una digressione dagli aspetti tecnici verso temi che propriamente non lo sono: parliamo di gestione del rischio tramite suddivisione in più unità.

Mi spiego con un esempio venuto con l’esperienza: avete una ditta, dovete anticipare delle fatture per cui vi serve un castelletto di 100.000,00 Euro. Il periodo è difficile, le banche prima di esporsi ci pensano 1.000 volte (belle stronze, visto che il casino l’hanno causato soprattutto loro con i mutui subprime e derivati vari), per cui è difficile che un istituto vi conceda un simile fido.

Come fare?

Come si è sempre fatto: vado in 10 banche e chiedo a ciascuna un affidamento di portafoglio di 10.000,00 Euro. E’ più difficile viaggiare per 10 banche diverse, ma grazie a 10 piccoli passi al posto di uno gigante, alla fine ho più probabilità di ottenere quello che mi serve. E non solo: se una delle banche mi crea problemi ne ho altre nove su cui contare e non su una sola che mi lascerebbe a piedi.

Lo stesso discorso si può applicare con i clienti: meglio un cliente che mi fa fatturare 100.000,00 Euro all’anno oppure 100 clienti da 1.000,00 Euro? Con un cliente solo “mi smazzo di meno”, ma quando ci sono i primi problemi (e prima o poi i problemi, anche temporanei, arrivano) si vede la differenza.

Come diceva la pubblicità: du is megl che uan!

Questo si chiama suddivisione del rischio e deve essere applicato in tutti i contesti con criticità… e non fraintendetemi, non sto dicendo di trovarvi 100 amanti per stare tranquilli se litigate con il cogniuge.

E’ per dirvi invece che la stessa filosofia deve essere applicata nell’ambito informatico per minimizzare i rischi causati da un disservizio: troppo spesso in questo blog abbiamo trattato argomenti legati al cloud, all’alta affidabilità, a più server in load balancing… ma se per caso prendono fuoco gli UPS ed il datacenter resta al buio?

Lungi da me criticare Amazon e Aruba che hanno avuto questo tipo di problemi proprio di recente, anzi, complimenti (soprattutto al secondo) per la rapidità con la quale sono tornati operativi: come si dice, la bravura non sta a non cadere mai da cavallo, ma a rialzarsi in fretta dopo una brutta caduta.

Critico però tutti coloro che concentrano tutti i servizi presso un’unica struttura, senza valutare il rischio che questa cosa può generare e, quando accade, piangono…

E, paradossalmente, per affrontare questo problema ci viene in aiuto proprio il cloud: forse non tutti sanno che i cloud di possono federare. Bella parola, ma cosa vuol dire questo? Che pressochè tutti i sistemi di cloud utilizzano le API EC2 di Amazon e quindi, per definizione, esiste un layer di compatibilità che permette di unire assieme più cloud per bilanciare il carico di lavoro (e quindi anche il rischio in caso di guasto).

Nella pratica, per il proprio web server, meglio avere un’unica grande VM su Amazon o 10 piccole VM su 10 differenti cloud in load balancing?
Ok, il vostro ISP (io) è strafigo, vi assicura continuità… ma le recenti vicissitudini indicano che nessuno è immune da problemi, per cui magari costerà di più ma è meglio avere 10 web server in load balancing piuttosto di concentrare il rischio in un’unica struttura, per quanto importante possa essere.

Quindi, nel momento in cui state per acquistare un servizio “on-the-cloud” quantomeno informatevi se il Vostro provider permette la federazione con altri cloud. Diffidate da chi non la prevede, potreste pentirvene amaramente un domani.

Creare uno stage4 in Linux

Intanto, cos’è uno stage4?

stage4 è un termine che deriva dalle prime installazioni di Gentoo Linux che mettevano a disposizione tre diverse modalità di installazione con diversi gradi rispetto a ciò che veniva fornito precompilato.

In sostanza, come già detto in questo articolo, per installare Gentoo si esegue il download di un unico file in formato tar.bz che, una volta decompresso, crea un sistema base sul quale è possibile iniziare a lavorare. Oramai si utilizza sempre lo “stage3” che, in un download di circa 150 MB, include tutti gli strumenti utili per la compilazione e il sistema di base senza il kernel.

Inizialmente, però, gentoo prevedeva anche lo stage1 e lo stage2:

  • lo stage1 è sostanzialmente il download di un file con solo gli strumenti per poter compliare il compilatore C

  • lo stage2 è il download di un file con tutti gli strumenti necessari per compilare il sistema di base

  • lo stage3, come già detto, è il download di un file contenete dia gli strumenti per compilare (stage2) con già il sistema di base precompilato.

Lo stage4 è quindi lo step successivo, cioè il file contenente il backup completo di una macchina linux compilata e operativa: vediamolo un po’ come il “disaster recovery” di un server Linux.

Questa operazione è abbastanza conosciuta su sistemi Gentoo Linux, però è comunqe adattabile a qualsiasi distribuzione in quanto utilizza strumenti standard. La cosa interessante è che, per creare uno stage4, non è necessario spegnere la macchina, ma è possibile farlo mentre la stessa è operativa.

Per creare lo stage4 di una macchina esistono numerosi script, tutti scaricabili a questo indirizzo.

Personalmente quello che preferisco è questo:

<strong>mkstage4.sh</strong>
#!/bin/bash

# Backup script for Gentoo Linux
#
# mkstage4.sh is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# mkstage4.sh is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# Copyright: Reto Glauser aka blinkeye
# Mailto: stage4 at blinkeye dot ch
# Homepage: http://blinkeye.ch
# Forum post: http://forums.gentoo.org/viewtopic-t-312817.html
# Date: 2009-04-02

version=v3.7
basename=`basename $0`

find=/usr/bin/find
tar=/bin/tar

# these are the commands we actually need for the backup
command_list=(cut date echo $find grep hostname mount sh split $tar umount uname which)

# verify that each command we use exists. if one can't be found use $PATH and make a suggestion if possible.
for command in ${command_list[@]}; do
        if [ ! -x "`which $command 2>&1`" ]; then
                echo -e "\nERROR: $command not found! "
                base=`basename $command`
                if [ "`which $base 2>&1 | grep "no \`basename $command\` in"`" != "" ]; then
                        echo -e "ERROR: $base is not in your \$PATH."
                fi
                exit -1
        fi
done

help="\nUsage:\n\nsh `basename $0` [[-v]|[--verbose]] [[-s]|[--split]] \n\nTo run the script NOT in verbose mode comes in handy if you want to see only the errors that occur during the backup.\n"

# Defaults to creating one tarball
tar_output="--file"

# split command
split_options="--suffix-length=1 --bytes=685m"

# options for the tar command
tarOptions=" --preserve-permissions --create --absolute-names --totals --ignore-failed-read"

# where to put the stage4
stage4Location=/mnt/backups/stage4

# name prefix
stage4prefix=`hostname`-stage4-`date +\%Y.\%m.\%d`

# patterns which should not be backed up (like iso files).
# example: default_exclude_pattern="*.iso *.divx"
# These pattern count only for files NOT listed in the $custom_include_list.
default_exclude_pattern=""

# these files/directories are always excluded. don't add trailing slashes.
# don't touch it unless you know what you are doing!
# /var/db and /var/cache/edb are intentionally added here. they are listed
# in $default_include_folders
default_exclude_list="
/dev
/lost+found
/mnt
/proc
/sys
/tmp
/usr/portage
/usr/src
/var/log
/var/tmp
/var/db
/var/cache/edb
$stage4Location
`echo $CCACHE_DIR`"

# files/devices/folders, which need to be backed up (preserve folder structure).
# don't touch it unless you know what you are doing! no recursive backup of folders.
# use $default_include_folders instead.
default_include_files="
/dev/null
/dev/console
/home
/mnt
`find /mnt -name .keep`
/proc
/sys
/tmp
/usr/portage
/usr/src
/var/log/emerge.log
/usr/src/linux-`uname -r`/.config"

# folders, which need to be backed up recursively on every backup.
# don't touch it unless you know what you are doing! the reason for this
# variable is that some users add /var to the $default_exclude_list. here
# we ensure that portage's memory is backed up in any case.
default_include_folders="
/var/db"

# IMPORTANT: A minimal backup will EXCLUDE files/folders listed here. A custom backup will
# include/exclude these files/folders depening on your answer.
custom_include_list="
/home/*
/usr/src/linux-`uname -r`"

# add files/folders here which are subfolders of a folder listed in $custom_include_list which should NOT
# be backed up. eg.
#custom_exclude_list="/home/foo/mp3 /home/foo/downloads /home/foo/.*"
custom_exclude_list=""

# Only files/folders within the $custom_include_list are checked against these patterns
# custom_exclude_pattern="*.mp3 *.iso"
custom_exclude_pattern=""

# the find_command
find_command="$find /*"

# don't backup anything which matches pattern listed in $default_exclude_pattern
for pattern in $default_exclude_pattern; do
        find_command="$find_command -not -name $pattern"
done

# assemble the find_command
function find_files()
{
        for folder in $default_exclude_list; do
                find_command="$find_command -path $folder -prune -o"
        done

        find_command="$find_command -print"

        for i in $default_include_files; do
                find_command="echo $i; $find_command"
        done

        for i in $default_include_folders; do
                if [ -d $i ]; then
                        find_command="$find $i; $find_command"
                else
                        find_command="echo $i; $find_command"
                fi
        done
}

# check the exclude/include variables for non-existing entries
function verify()
{
        for i in $1; do
                if [ ! -e "`echo "$i" | cut -d'=' -f2 | cut -d'*' -f1`" -a "$i" != "/lost+found" -a "$i" != "$stage4Location" ]; then
                        echo "ERROR: `echo "$i" | cut -d'=' -f2` not found! Check your "$2
                        exit 0
                fi
        done
}

# check input parameters
while [ $1 ]; do
        case  $1 in
        "-h" | "--help")
                echo -e $help
                exit 0;;
        "-v" | "--verbose")
                verbose=$1;;
        "-s" | "--split")
                tar_output="--split";;
        "");;
        *)
                echo -e $help
                exit 0;;
        esac
        shift
done

echo ""

# check folder/files listed in $default_exclude_list exist
verify "$default_exclude_list" "\$default_exclude_list"

# check files listed in $default_include_files exist
verify "$default_include_files" "\$default_include_files"

# check folder listed in $default_include_folders exist
verify "$default_include_folders" "\$default_include_folders"

#check folder listed in $custom_include_list exist
verify "$custom_include_list" "\$custom_include_list"

#check folder listed in $custom_exclude_list exist
verify "$custom_exclude_list" "\$custom_exclude_list"

# print out the version
 echo -e "\nBackup script $version"
 echo -e "=================="

# how do you want to backup?
echo -e "\nWhat do you want to do? (Use CONTROL-C to abort)\n
Fast (tar.gz):
 (1) Minimal backup
 (2) Interactive backup

Best (tar.bz2):
 (3) Minimal backup
 (4) Interactive backup\n"

while [ "$option" != '1' -a "$option" != '2' -a "$option" != '3' -a "$option" != '4' ]; do
        echo -en "Please enter your option: "
        read option
done

case $option in
[1,3])
        stage4Name=$stage4Location/$stage4prefix-minimal.tar;;

[2,4])
        stage4Name=$stage4Location/$stage4prefix-custom.tar

        for folder in $custom_include_list; do
                echo -en "\nDo you want to backup" `echo "$folder" | cut -d'=' -f2`"? (y/n) "
                read answer
                while [ "$answer" != 'y' -a "$answer" != 'n' ]; do
                        echo -en "Do you want to backup" `echo "$folder" | cut -d'=' -f2`"? (y/n) "
                        read answer
                done
                if [ "$answer" == 'n' ]; then
                        find_command="$find_command -path $folder -prune -o"
                else
                        custom_find="$find $folder"
                        for i in $custom_exclude_pattern; do
                                custom_find="$custom_find -name $i -o"
                        done
                        for i in $custom_exclude_list; do
                                custom_find="$custom_find -path $i -prune -o"
                        done
                        find_command="$custom_find -print; $find_command"
                fi
        done ;;
esac

# add $custom_include_list to the $default_exclude_list as we assembled
# $custom_find with $custom_include_list already.
default_exclude_list="$default_exclude_list $custom_include_list"

case $option in
[1,2])
        stage4postfix="gz"
        zip="--gzip";;

[3,4])
        stage4postfix="bz2"
        zip="--bzip2";;
esac

# mount boot
echo -e "\n* mounting boot"
mount /boot >/dev/null 2>&1

# find the files/folder to backup
find_files
find_command="($find_command)"

# create the final command
if [ "$tar_output" == "--file" ]; then
        tar_command="$find_command | $tar $zip $tarOptions $verbose --file $stage4Name.$stage4postfix --no-recursion -T -"
else
        tar_command="$find_command | $tar $zip $tarOptions $verbose --no-recursion -T - | split $split_options - "$stage4Name.$stage4postfix"_"
fi

if [ "$verbose" ]; then
        echo -e "\n* creating the stage4 in $stage4Location with the following command:\n\n"$tar_command
fi

# everything is set, are you sure to continue?
echo -ne "\nDo you want to continue? (y/n) "
read answer
while [ "$answer" != 'y' ] && [ "$answer" != 'n' ]; do
        echo -ne "Do you want to continue? (y/n) "
        read answer
done

if [ "$answer" == 'y' ]; then
        # check whether the file already exists.
        if [ "$tar_output" == "--split" ]; then
                overwrite="`ls "$stage4Name.$stage4postfix"_* 2>&1 | grep -v 'No such file'`"
        else
                overwrite="$stage4Name.$stage4postfix"
        fi

        if [ -a "`echo "$overwrite" | grep "$overwrite" -m1`" ]; then
                echo -en "\nDo you want to overwrite $overwrite? (y/n) "
                read answer
                while [ "$answer" != 'y' ] && [ "$answer" != 'n' ]; do
                        echo -en "Do you want to overwrite $overwrite? (y/n) "
                        read answer
                done
                if [ "$answer" == 'n' ]; then
                        echo -e "\n* There's nothing to do ... Exiting"
                        exit 0;
                fi
        fi

        # if necessary, create the stage4Location
        if [ ! -d "$stage4Location" ] ; then
                echo "* creating directory $stage4Location"
                mkdir -p $stage4Location
        fi

        echo -e "\n* Please wait while the stage4 is being created.\n"

        # do the backup.
        sh -c "$tar_command"

        # finished, clean up
        echo -e "\n* stage4 is done"
        echo "* umounting boot"
        umount /boot >/dev/null 2>&1

        # Integrity check
        echo -e "* Checking integrity"
        if [ "$zip" == "--gzip" ]; then
                zip="gzip"
        else
                zip="bzip2"
        fi

        if [ "$tar_output" == "--split" ]; then
                if [ "`cat "$stage4Name.$stage4postfix"_*"" | $zip --test 2>&1`" != "" ]; then
                        echo -e "* Integrity check failed. Re-run the script and check your hardware."
                        exit -1
                fi
        else
                if [ "`$zip --test  $stage4Name.$stage4postfix 2>&1`" != "" ]; then
                        echo -e "* Integrity check failed. Re-run the script and check your hardware."
                        exit -1
                fi
        fi

        # everything went smoothly
        echo -e "* Everything went smoothly. You successfully created a stage4."

else
        echo -e "\n* There's nothing to do ... Exiting"
fi

Combattiamo lo spam con sqlgrey

Uno dei principali problemi con cui un amministratore di server deve combattere è lo spam.
Purtroppo il fenomeno dello spam non è in diminuzione, anzi, e per combatterlo dobbiamo attrezzarci armandoci di infinita pazienza: difatti le regole antispam che un SysAdmin può applicare sono molteplici e scegliere quali applicare è un compromesso che non soddisferà mai la totalità degli utenti.

Un filtro molto utile che porta pochi problemi è il greylist. Questo sistema si basa su un principio ancora valido: lo spammer, per monetizzare, deve avere subito riscontro di quante mail sono arrivate a destinazione, pertanto se una consegna fallisce non sarà più ritentata. In maniera totalmente opposta funzionano i server tradizionali: se il server del destinatario ha un problema temporaneo, il mail server mittente riproverà ad inviare l’email successivamente.

Nella pratica, quando un server su cui funzona il greylisting è attivo riceve una email, viene controllata la “tripletta” formata da email mittente/indirizzo IP mittente/email destinatario per vedere se è la prima volta che accade questo evento. Se è la prima volta, l’email viene respinta con un errore temporaneo e la ricezione rimane bloccata per un tempo predefinito (solitamente 1 minuto), altrimenti, se non è la prima volta e se il minuto di blocco dal primo invio è passato, l’email viene accettata.

Se si hanno più mail server in ricezione (MX) è importantissimo che tutti siano configurati con il greylisting, altrimenti il sistema risulta inefficace. Inoltre tutti i server MX devono utilizzare un unico database per memorizzare le triplette, altrimenti si corre il rischio di continuare a respingere le mail.

Una implementazione del greylisting che soddisfa questi requisiti è sqlgrey: difatti questo sistema memorizza le triplette su un database SQL che pertanto può essere condiviso tra i server MX.

Vediamo come configurare il servizio: nella nostra installazione utilizzeremo un server MySQL centralizzato all’indirizzo mysql.dominio.local e un mirror locale del datatabase configurato come slave con la classica replica MySQL in modo da minimizzare il carico di lavoro sul master. Con questa configurazione tutte le query in scrittura andranno sul master, mentre le query in lettura (più numerose e dispendiose) saranno solo locali.

Innanzi tutto modifichiamo il file di configurazione /etc/sqlgrey/sqlgrey.conf:

<strong>/etc/sqlgrey/sqlgrey.conf</strong>
reconnect_delay = 5
max_connect_age = 24
awl_age = 32
group_domain_level = 10
db_type = mysql
db_name = sqlgrey
db_host = mysql.dominio.local
db_port = default
db_user = sqlgrey
db_pass = PasswordSQLgrey
db_cluster = on
read_hosts=localhost
db_cleanup_hostname = localhost
admin_mail = server@domino.local
greymethod = classc

Una cosa importante in questa configurazione è il fatto che abbiamo settato il greymethod a classic: è il metodo più tranquillo, in grado di generare il minor numeri di blocchi.
Difatti questo valore può essere settato a full che memorizza l’ip del mittente, classic che memorizza l’intera classe C (/24) e smart che memorizza l’intera classe C se non riesce a fare il reverse lookup. In pratica, così facendo, saremo certi che se un mittente utilizza più server per la spedizione in round robin, non corra il rischio di rimanere bloccato in un “circolo vizioso”

Quindi creiamo il database sul server MySQL:

# mysql -u root -p
mysql> create database sqlgrey ;
mysql> grant all on sqlgrey.* to sqlgrey@'%' identified by 'PasswordSQLgrey';

e la copia locale:

# mysql -u root -p
mysql> create database sqlgrey ;
mysql> grant all on sqlgrey.* to sqlgrey@'localhost' identified by 'PasswordSQLgrey';

Tralascio la configurazione della replica master/slave: in quest’articolo potete trovare le istruzioni per configurare la replica master/master.

Infine modifichiamo il file /etc/postfix/main.cf aggiungendo la seguente riga:

...
smtpd_recipient_restrictions =
....
check_policy_service inet:127.0.0.1:2501,
...

Il mio consiglio è di utilizzare il greylisting come ultimo controllo, lasciando prima quelli più performanti in modo da evitare inutili query sul database.

Aggiungiamo un metadata a MooseFS e attiviamo l’HA

Nel precedente articolo abbiamo creato uno storage di test attraverso MooseFS: trattasi di una installazione utile solo a fini di test in quanto non prevede alcun sistema di alta affidabilità.
Aggiungere l’alta affidabilità allo storage (i server chunck) è una cosa piuttosto semplice, in quanto è sufficiente installatre un nuovo server, configurare il servizio chunk e avviarlo: il chunk si collegherà al master server e agirà bilanciando il contenuto del filesystem in base alle impostazioni.
Aggiungere l’alta affidabilità al master, invece, è una cosa leggermente più complessa in quanto dobbiamo introdurre nel nostro setup un server “metadata”.
Questo server non fa altro che sincronizzare ad intervalli regolari, il metadata dal master in modo da averne una copia locale.
Avendo questa copia, in caso di guasto del server principale è sufficiente far partire il servizio master sul server metadata per essere di nuovo online.
In questo howto ci occuperemo di automatizzaare questo processo.

Iniziamo dall’installazione di linux base con i tools per la compilazione come nel precedente articolo e quindi procediamo al download e alla scompattazione del pacchetto:

wget http://pro.hit.gemius.pl/hitredir/id=0sWa0S8ft4sTAHF1bGAAEZPcP3ziyq7f9SdhoQf7oeT.c7/url=moosefs.org/tl_files/mfscode/mfs-1.6.20-2.tar.gz
tar zxvf mfs-1.6.20-2.tar.gz
cd mfs-1.6.20-2

Creiamo l’utente e installiamo FUSE come se si trattasse del nodo master:

useradd moose
emerge sys-fs/fuse

Configuriamo il processo di installazione di moose e compiliamo i sorgenti come se si trattasse di un master server:

./configure --disable-mfschunkserver --enable-mfsmount --with-default-user=moose --with-default-group=moose
make && make install

Copiamo il file di configurazione del processo master in locale:

scp master:/usr/local/etc/mfsmaster.cfg /usr/local/etc/

A questo punto il nostro server metadata è configurato nella stessa identica maniera del master.

Quello che dobbiamo fare ora è configurare il server in modo da replicare il metadata del master in locale.
Andiamo a creare il file /usr/local/etc/mfsmetalogger.cfg:

<strong>/usr/local/etc/mfsmetalogger.cfg</strong>
WORKING_USER = moose
WORKING_GROUP = moose
SYSLOG_IDENT = mfsmetalogger
LOCK_MEMORY = 0
NICE_LEVEL = -19

DATA_PATH = /usr/local/var/mfs

BACK_LOGS = 50
META_DOWNLOAD_FREQ = 24

MASTER_RECONNECTION_DELAY = 5

MASTER_HOST = master
MASTER_PORT = 9419

MASTER_TIMEOUT = 60

e avviamo il servizio metalogger:

/usr/local/sbin/mfsmetalogger

A questo punto punto server secondario terrà aggiornato il metalogger con frequenza giornaliera. Per installazioni reali, meglio usare frequenze molto più elevate.

Per chiudere il cerchio, installiamo heartbeat o coroync, configuriamo un ip condiviso e facciamo gestire l’avvio dei demoni /usr/local/sbin/mfsmaster e /usr/local/sbin/mfscgiserv dal sistema di HA. Per ulteriori informazioni su come utilizzare Pacemaker con Heartbeat, vi rimando a questo articolo del mio blog.

Installazione di test di un cluster storage con MooseFS

MooseFS è un filesystem  di rete che può essere montato attraverso il protocollo FUSE, con il quale è possibile creare uno storage ridondato e scalabile utilizzando una batteria di “commodity server” (cioè PC senza particolari caratteristiche di potenza).

Il sistema si compone di 3 elementi: il master server che fungerà da proxy e che ha la “mappa” delle posizione di tutti i dati all’interno del cluster, il metalogger server con una copia della “mappa” del server principale che può essere promosso a master in caso di necessità e una serie di “chunk server” che formetanno il vero e proprio storage.

Riguardo all’hardware, è consigliato avere due server robusti sia in termini di tolleranza ai guasti sia in termini di quantità di RAM per il master e il metalogger, mentre i chunk hanno bisogno, ovviamente, solo di parecchio spazio su disco.

In questo howto, installeremo un sistema semplificato formato solamente da un master e un chunk.

Partiamo da una installazione pulita della vostra distribuzione Linux preferita e installate i tools per la compilazione.

Quindi scarichiamo i sorgenti e scompattiamoli:

wget http://pro.hit.gemius.pl/hitredir/id=0sWa0S8ft4sTAHF1bGAAEZPcP3ziyq7f9SdhoQf7oeT.c7/url=moosefs.org/tl_files/mfscode/mfs-1.6.20-2.tar.gz
tar zxvf mfs-1.6.20-2.tar.gz
cd mfs-1.6.20-2

E creiamo un utente per eseguire il demone:

useradd moose

Installazione del master server
Sul master server, per comodità, installeremo anche l’opzione di mount del filesystem, per cui è necessario avere installato FUSE.
Su Gentoo è possibile installare il pacchetto con:

emerge sys-fs/fuse

Ora passiamo alla compilazione dei sorgenti. Innanzi tutto lanciamo il comando configure con le dovute opzioni:

./configure --disable-mfschunkserver --enable-mfsmount --with-default-user=moose --with-default-group=moose

Quindi passiamo alla compilazione vera e propria con:

make && make install

A questo punto il pacchetto è installato in /usr/local in modo da essere isolato dal resto del setup.

E’ necessario creare il file di configurazione /usr/local/etc/mfsmaster.cfg; io sono partito da quello di default.

<strong>/usr/local/etc/mfsmaster.cfg</strong>
WORKING_USER = moose
WORKING_GROUP = moose
SYSLOG_IDENT = mfsmaster
LOCK_MEMORY = 0
NICE_LEVEL = -19

EXPORTS_FILENAME = /usr/local/etc/mfsexports.cfg

DATA_PATH = /usr/local/var/mfs

BACK_LOGS = 50

REPLICATIONS_DELAY_INIT = 300
REPLICATIONS_DELAY_DISCONNECT = 3600

MATOML_LISTEN_HOST = *
MATOML_LISTEN_PORT = 9419

MATOCS_LISTEN_HOST = *
MATOCS_LISTEN_PORT = 9420

MATOCU_LISTEN_HOST = *
MATOCU_LISTEN_PORT = 9421

CHUNKS_LOOP_TIME = 300
CHUNKS_DEL_LIMIT = 100
CHUNKS_WRITE_REP_LIMIT = 1
CHUNKS_READ_REP_LIMIT = 5

REJECT_OLD_CLIENTS = 0

Inoltre bisogna creare il file con gli export /usr/local/etc/mfsexports.cfg. Io ho semplicemente tutto a tutti in lettura e scrittura:

/usr/local/etc/mfsexports.cfg
*           /   rw,alldirs,maproot=0
*           .   rw

Infine, trattandosi di una nuova installazione, bisogna creare il metadata:

mv /usr/local/var/mfs/metadata.mfs.empty /usr/local/var/mfs/metadata.mfs

A questo punto avviamo il servizio master e la console di stato con:

/usr/local/sbin/mfsmaster
/usr/local/sbin/mfscgiserv

Ricordiamoci di aggiungerlo all’avvio automatico, ad esempo modificando il file rc.local o /etc/conf.d/local.start a seconda della distrinuzione in uso.

Attraverso il servizio mfscgiserv si ha a disposizione una interfaccia web per controllare lo stato del proprio cluster storage. Ecco qui di seguito alcuni screenshot per stuzzicavi l’appetito.

Installazione del Chunk Server
Innanzi tutto formattiamo una partizione del nostro disco e montiamola in una directory dedicata

mke2fs -j /dev/sda4
mount /dev/sda4 /public

Ora passiamo alla compilazione di moose:

./configure --disable-mfsmaster --disable-mfsmount --with-default-user=moose --with-default-group=moose
make
make install

Assegnamo all’utente moose i privilegi di scrittura:

chown -R moose:moose /public

Creiamo il file di configurazione del demone:

<strong>/usr/local/etc/mfschunkserver.cfg</strong>
WORKING_USER = moose
WORKING_GROUP = moose
SYSLOG_IDENT = mfschunkserver
LOCK_MEMORY = 0
NICE_LEVEL = -19

DATA_PATH = /usr/local/var/mfs

MASTER_RECONNECTION_DELAY = 5

BIND_HOST = *
MASTER_HOST = master
MASTER_PORT = 9420

MASTER_TIMEOUT = 60

CSSERV_LISTEN_HOST = *
CSSERV_LISTEN_PORT = 9422

HDD_CONF_FILENAME = /usr/local/etc/mfshdd.cfg
HDD_TEST_FREQ = 10

e il file mfshdd.cfg con l’elenco dei dischi condivisi:

<strong>/usr/local/etc/mfshdd.cfg</strong>
/public

e avviamo il demone con:

/usr/local/sbin/mfschunkserver

Dato che sul master abbiamo installato anche il mfsmount, possiamo collaudare il funzionamento montando il disco con:

mfsmount /mnt/moose/ -H 192.168.0.100 -P 9421

Nel prossimo Howto aggiungeremo a questo setup un metalogger server attraverso il quale garantiremo alta affidabilità al master.