Disco di Backup Avviabile con rsync (RAID freddo)
Una problematica comune riguardo ai sistemi sui quali risiedono dati senibili e/o configurazioni e servizi specifici è quella del backup, cioè poter disporre di una copia del contenuto del disco che assicuri la ridondanza in caso di guasti ai supporti di informazione. Essa si rivela di primaria importanza quando, il computer, a causa di errori dell'operatore o guasti interni, abbia perso in modo irrecuperabile dati fondamentali o configurazioni essenziali per il suo corretto funzionamento. Le procedure quì elencate vogliono essere un riassunto per descrivere come è stato affrontato questo problema a livello semi-professionale al fine di ottenere un sistema sicuro in termini di backup. Le nostre esigenze sono quelle di avere un secondo supporto di informazioni che sia completamente uguale a quello principale e sia avviabile manualmente, ma la sincronizzazione tre i due supporti non deve avvenire in tempo reale. E’ capitato che i nostri server si siano bloccati a seguito di aggiornamenti del sistema operativo scaricati dalla rete, che un operatore abbia cancellato distrattamente una directory o che abbia cambiato una configurazione e abbia provocato danni a catena. In tutti questi casi, un RAID con due dischi fissi avrebbe immediatamente duplicato i danni sui due supporti e quindi sarebbe stato inutile per far ripartire il sistema. Per le nostre esigenze si è voluto adottare un sistema in cui normalmente sia attivo un solo disco fisso. Ogni giorno, nel periodo di minor utilizzo del server, il secondo disco fisso viene automaticamente montato, sincronizzato con il disco fisso principale e poi smontato in modo da ridurne l’usura. Questa scelta ha lo svantaggio di lasciare il computer bloccato in caso di guasto al supporto principale e richiedere l’intervento di un operatore per avviare il sistema dal supporto secondario.
Questa piccola guida vorrebbe essere un utile punto di partenza per migliorare il livello di affidabilità di una piccola rete domestica o d'ufficio.
Il layout di sistema dal quale si è partiti, indipendentemente dal resto dell'hardware, presenta due dischi fissi identici, e si è operato con l'obiettivo di mantenere su uno dei due dischi la copia esatta, aggiornata giornalmente tramite l'utility rsync, di quello in funzione nel quale è presente il sistema operativo, avendo la possibilità, inoltre, di poterlo avviare in caso di rottura del primo. In particolare si illustreranno le procedure di configurazione per due sistemi:
Sebbene le tecnologie con cui si è avuto a che fare siano sostanzialmente diverse, dal punto di vista dell'utente finale ciò non comporta un cambiamento d'approccio, poiché le istruzioni seguenti, per entrambi i sistemi hanno portato a configurazioni funzionanti.
Partendo da un sistema in cui nel primo disco è già presente un sistema funzionante, si deve creare una tabella di partizioni specifica sul secondo disco fisso. Per fare ciò si possono utilizzare i tool cfdisk o fdisk come illustreremo, ricordando, e ciò vale per tutti i riferimenti seguenti, che ci si riferisce a sda per il primo disco fisso e a sdb per il secondo. E’ utile prendere visione della tabella delle partizioni del primo disco per crearne una, in questo caso identica, sul secondo. Per fare ciò
root@system:~# cfdisk /dev/sda
oppure
root@system:~# fdisk /dev/sda
Command (m for help): p
Disk /dev/sda: 400.0 GB, 400088457216 bytes
255 heads, 63 sectors/track, 48641 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x08090808
Device Boot Start End Blocks Id System
/dev/sda1 * 1 13 104391 83 Linux
/dev/sda2 14 318 2449912+ 82 Linux swap/Solaris
/dev/sda3 319 48641 388154497+ 83 Linux
Nel sistema preso in considerazione le associazioni sono le seguenti:
A questo punto si replica la struttura, in modo che sia identica sul secondo hard disk, poiché ciò evita dei disallineamenti che potrebbero portare all'impossibilità di effettuare una copia di backup per spazio insufficiente. Partendo da un disco vuoto si prosegue come riportato
root@system:~# fdisk /dev/sdb
Command (m for help): p
Disk /dev/sdb: 400.0 GB, 400088457216 bytes
255 heads, 63 sectors/track, 48641 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x000b052f
Device Boot Start End Blocks Id System
Per creare unanuova partizione usare l'opzione 'n'
Command (m for help): n
Command action
e extended
p primary partition (1-4)
indicare se la partizione è primaria o logica, in questo caso selezioniamo la prima con 'p'
p
Partition number (1-4): 1
First cylinder (1-48641, default 1):
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-48641, default 48641): +100M
si indica con +100M la dimensione della partizione creata, ossia 100MB, dopodichè si verifica il risultato con 'p'. La seguente è la partizione di boot '/boot'
Command (m for help): p
Disk /dev/sdb: 400.0 GB, 400088457216 bytes
255 heads, 63 sectors/track, 48641 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x000b052f
Device Boot Start End Blocks Id System
/dev/sdb1 1 13 104391 83 Linux
a questo punto si replica il procedimento per le ulteriori partizioni, rispettivamente di swap e di root '/'
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (14-48641, default 14):
Using default value 14
Last cylinder or +size or +sizeM or +sizeK (14-48641, default 48641): +2500M
Command (m for help): p
Disk /dev/sdb: 400.0 GB, 400088457216 bytes
255 heads, 63 sectors/track, 48641 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x000b052f
Device Boot Start End Blocks Id System
/dev/sdb1 1 13 104391 83 Linux
/dev/sdb2 14 318 2449912+ 83 Linux
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 3
First cylinder (319-48641, default 319):
Using default value 319
Last cylinder or +size or +sizeM or +sizeK (319-48641, default 48641):
Using default value 48641
Command (m for help): p
Disk /dev/sdb: 400.0 GB, 400088457216 bytes
255 heads, 63 sectors/track, 48641 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x000b052f
Device Boot Start End Blocks Id System
/dev/sdb1 1 13 104391 83 Linux
/dev/sdb2 14 318 2449912+ 83 Linux
/dev/sdb3 319 48641 388154497+ 83 Linux
Command (m for help): w
A questo punto è stata ottenuta la tabella di partizioni desiderata, quindi è necessario creare al loro interno il filesystem adatto, per esempio Ext3
root@system:~# mkfs.ext3 /dev/sdb1
[...]
root@system:~# mkfs.ext3 /dev/sdb3
[...]
root@system:~# mkswap /dev/sdb2
[...]
Il prossimo passo è quello di fare in modo che il contenuto delle singole partizioni sul primo disco sia copiato nelle rispettive partizioni del secondo. A tale scopo si utilizza rsync, un tool fondamentale per il backup dei dati, poiché permette la creazione di copie in maniera intelligente evitando di copiare di volta in volta l'intero filesystem e riportando solo i file che presentano, ad esempio, variazione dei metadati (ad esempio la data di ultimo accesso o la dimensione del file). Poiché i comandi da utilizzare sono ripetitivi, è utile la crezione di un piccolo script che li inglobi tutti. Fondamentalmente ciò che è necessario fare è:
A tal fine si riporta un possibile script minimale
root@system:~# nano -w /usr/sbin/mirroring
#!/bin/sh
/bin/mount /dev/sdb3 /mnt/sdb/sdb3
/usr/bin/rsync -a -E --exclude=/mnt/* --exclude=/etc/fstab --exclude=/etc/mtab \
--exclude=/sys/* --exclude=/tmp/* --exclude=/proc/* --exclude=/var/run/* \
--exclude=/var/lock/* --exclude=/boot/* / /mnt/sdb/sdb3
/bin/umount /dev/sdb3
/bin/mount /dev/sdb1 /mnt/sdb/sdb1
/usr/bin/rsync -a -E --delete --exclude=/boot/grub/menu.lst \
--exclude=/boot/grub.conf /boot/* /mnt/sdb/sdb1
/bin/umount /dev/sdb1
ricordarsi a questo punto di creare le directory necessarie allo script all'interno della cartella '/mnt', come '/mnt/sdb/sdb1' e '/mnt/sdb/sdb1' e di assegnare il permesso di esecuzione al file appena creato.
root@system:~# chmod +x /usr/sbin/mirroring
A questo punto è possibile effettuare le procedure sopra descritte semplicemente digitando
root@system:~# /usr/sbin/mirroring
Innanzitutto bisogna notare che le partizioni sincronizzate sono quella di boot '/boot' e quella di root '/', poiché la partizione utilizzata come swap non è adibita al contenimento di dati appartenenti alla struttura del filesystem; tuttavia gli utenti che utilizzino un metodo per l'ibernazione del sistema, ovvero della copia dell'immagine della ram e dello stato del sistema su disco, dovrebbero provvedere anche alla sincronizzazione della partizione di swap, proprio per il fatto che essa eventualmente mantiene una tale immagine.
Ora è utile soffermarsi sulle opzioni utilizzate con il comando rsync, in particolare su '--exclude=PATH'. Quest'ultima è necessaria allo scopo di escludere determinate posizioni all'interno della struttura del filesystem dall'essere copiate: ciò è utile in vista del fatto che il disco di backup, poiché si vuole che sia avviabile, possa contenere un sistema operativo, con i rispettivi dati, completamente funzionante; questo lo si può ottenere, come meglio spiega l'esempio seguente, solo non compromettendo configurazioni che riguardino strettamante il disco utilizzato e file creati ed utilizzati a run-time. Per comprendere meglio, si può pensare al caso in cui il file '/etc/fstab', il quale è responsabile di mantenere la lista delle partizioni presenti sul sistema, utilizzi un metodo “diverso dal solito” per indicare le partizioni stesse. UUID, ossia Universal Unique Identifier, è un modo, utilizzato tra gli altri nella distribuzione Ubuntu 8.04, per riferirsi alle partizioni in maniera indipendente dal nome del disco o dal punto di mount, ed è costituito da un insieme di caratteri esadecimali ricavati tramite una procedura univoca. Dunque di questo metodo si deve tener conto, poiché, il file 'fstab' presente sul secondo disco non potrà presentare gli stessi valori di quello presente sul primo, pena l'impossibilità di avviare il disco di backup nonostante la presenza di un bootloader quale GRUB (la cui procedura di installazione verrà trattata in seguito).
Per i motivi sopra spiegati è opportuno escludere, da valutarsi dipendenemente dal sistema utilizzato, i percorsi qui riportati:
Da ricordare che qualora tali cartelle non venissero create sul secondo disco, bisognerebbe provvedere manualmente, considerando il secondo disco montato in /mnt/mirror, come segue
root@system:~# cd /mnt/mirror
root@system:~# mkdir -m 1777 tmp
root@system:~# mkdir -m 1777 var/tmp
root@system:~# mkdir -m 555 proc
root@system:~# mkdir -m 755 sys
root@system:~# mkdir -m 755 mnt
root@system:~# mkdir -m 755 var/lock
root@system:~# mkdir -m 755 var/run
Per ciò che riguarda il file /etc/fstab bisogna copiarlo dal primo disco ma modificarlo in base alle partizioni presenti sul secondo disco, in modo che il sistema ne sia a conoscenza.
root@system:~# cp /etc/fstab /mnt/mirror/etc/fstab
Uno stralcio del contenuto potrebbe presentarsi così, nel caso di utilizo degli UUID
root@system:~# cat /etc/fstab
# /etc/fstab: static file system information.
#
# <file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
# /dev/sda3
UUID=eb1b27c7-36e1-40c2-8e0d-cbaf23842bee / ext3 relatime,errors=remount-ro 0 1
# /dev/sda1
UUID=baf54ec1-48c3-4506-870d-b37d9a6b2c54 /boot ext3 relatime 0 2
/dev/sda2 none swap sw 0 0
[...]
Dunque per apportare modifiche in maniera opportuna bisogna sostituire gli UUID relativi alle partizioni del primo disco con quelli delle partizioni del secondo, utilizzando l'utiliy blkid oppure il comando vol_id
root@system:~# vol_id --uuid /dev/sdb1
2e692df8-c9c8-4181-b55c-ff05379f38e5
oppure
root@system:~# blkid /dev/sdb1
/dev/sdb1: UUID="d9792df8-c9c8-4181-b55c-5f0f279f38e5" SEC_TYPE="ext2" TYPE="ext3"
Se invece in fstab sono presenti voci con la dicitura 'LABEL=', come accade nella distribuzione Red Hat Enterprise 5, ciò segnala che per indicare le singole partizioni si fà riferimento alle etichette assegnate loro al momento della creazione del filesystem.
root@system:~# cat /etc/fstab
LABEL=/ / ext3 defaults 1 1
LABEL=/boot /boot ext3 defaults 1 2
[...]
A meno di non studiare una configurazione più particolareggiata, e le casistiche a cui può essere applicata, è opportuno non utilizzare i LABEL nei file di configurazione, a favore dell'utilizzo del nome del diso assegnato da udev (ossia /dev/sda o /dev/hda etc) oppure gli stessi UUID desritti precedentemente. Per conoscere le associazoni tra LABEL e dispositivi, si può utilizzare il comando
root@system:~# dumpe2fs -h /dev/sda1
così, alla prima delle tante voci che compare come output del comando, è mostrata quella del LABEL relativo alla partizione sda1. Qualora se ne volesse far uso, per assegnare e sovrascrivere un LABEL ad una partizione si può digitare il seguente comando
root@system:~# e2label /dev/sdb1 NUOVO_LABEL
Molto importante è sottolineare il fatto che in caso di malfunzionamento del primo disco, questo, come da ipotesi inziale, verrà scollegato manualmente dal sistema per far sì che l’avvio avvenga dal secondo disco: a questo punto il disco di backup che prima era identificato come /dev/sdb, rimanendo l'unico sul sistema, verrà riconosciuto come /dev/sda, quindi, a parte il caso (consigliato) di utilizzo di UUID univoci, nel file fstab del secondo disco ci si deve riferire alle partizioni di backup sempre con il nome /dev/sda1 – sda2 – sda3 invece che /dev/sdb1 – sdb2 – sdb3.
Una nota aggiuntiva riguarda la cartella /sys per la Red Hat Enterprise 5: essa non è stata esclusa dalla prima sincronizzazione, poiché, per il corretto avvio del secondo disco, è stato necessario replicare la struttura delle sue sottodirectory. Nelle sincronizzazioni successive anche /sys è stata inclusa come cartella da non aggiornare nella copia di backup.
A questo punto, una volta indicati i necessari cambiamenti su fstab, si riportano le istruzioni per consentire l'avvio del sistema a partire dal secondo disco, con all'interno una copia di backup valida.
Innanzitutto si suppone che venga utilizzato un boot loader per l'avvio del sistema, GRUB nello specifico, e che l'installazione sul primo disco sia funzionante essendo avvenuta in fase di prima configurazione del sistema operativo. Lo scenario preso in considerazione, si ribadisce, è il seguente:
Si vuole che in caso di malfunzionamento, o di perdita accidentale di dati, sia possibile, a sistema spento, scollegare fisicamente il primo disco lasciando il secondo collegato, consentendo comunque il successivo avvio.
Si precisa che a questo punto dovrebbe essere disponibile una copia affidabile di backup sul secondo disco, quindi si conta sulla presenza del file di configurazione di GRUB anche sul disco di backup. Il file in questione è grub.conf, a volte sostituito o link-ato dal file menu.lst, da constatare sul sistema, situato nella cartella /boot/grub. Per la modifica sono valide tutte le considerazioni fatte per il file fstab e supponendo che la partizione di boot del secondo disco sia montata su /mnt/mirror/boot, si procede come segue
root@system:~# nano -w /mnt/mirror/boot/menu.lst
[...]
Title Ubuntu 8.04.1, kernel 2.6.24-19-generic
Root (hd0,0)
kernel /vmlinuz-2.6.24-19-generic root=UUID=eb1b27c7-36e1-40c2-8e0d-cbaf23842bee ro quiet splash
initrd /initrd.img-2.6.24-19-generic
quiet
title Ubuntu 8.04.1, kernel 2.6.24-19-generic (recovery mode)
root (hd0,0)
kernel /vmlinuz-2.6.24-19-generic root=UUID=eb1b27c7-36e1-40c2-8e0d-cbaf23842bee ro single
initrd /initrd.img-2.6.24-19-generic
title Ubuntu 8.04.1, memtest86+
root (hd0,0)
kernel /memtest86+.bin
quiet
[...]
Considerando che, ad esempio, la partizione di root '/' sul secondo disco si trova su /dev/sda3 bisogna modificare le voci del file in cui si riporta lo UUID con quello corretto, sostituendolo. Nel caso siano presenti anche quì record che utilizzano LABEL, è necessario modificarli come fatto per il file fstab. Per evitare incomprensioni si precisa che l'identificativo root nella riga
root (hd0,0)
si riferisce alla partizione su cui risiede la cartella di configurazione di GRUB , nel caso /boot/grub, mentre nella riga
kernel /vmlinuz-2.6.24-19-generic root=UUID=eb1b27c7-
36e1-40c2-8e0d-cbaf23842bee [...]
si riferisce alla partizione di root del sistema, cioè quella dove risiede la radice del filesystem '/'.
L'espressione (hd0,0) indica con 'hd0' il primo disco individuato nel sistema e con '0' la prima partizione sullo stesso disco, in accordo con il fatto che al momento di un’eventuale partenza dal disco di backup, esso risulterebbe l'unico disco e quindi il primo presente. A titolo esplicativo la terza partizione del disco di backup sarebbe indicata in grub come (hd1,2).
Una volta modificato il file grub.conf, ovvero menu.lst, sul secondo disco, si provvede all'installazione del vero e proprio bootloader GRUB.
root@system:~# grub
Probing devices to guess BIOS drives. This may take a long time.
[ Minimal BASH-like line editing is supported. For the first word, TAB lists possible command completions. Anywhere else TAB lists the possible completions of a device/filename. ]
A queto punto comparirà la shell di Grub. Ipotizzando che a queto punto si sta effettuando la prima installazione e che il disco di backup sia il secondo disco del sistema, cioè /dev/sdb, si può digitare il seguente comando per indicare che la configurazione adottata nelle successive operazioni sarà quella situata nella partizione di boot del secondo disco, /dev/sdb1
grub> root(hd1,0)
[...]
è dunque ora possibile l'installazione del bootloader nel MBR (Master Boot Record) del secondo disco
grub> setup(hd1)
[...]
grub> quit
In caso di errore si verifichi che entrambi i dischi siano presenti nel file /boot/grub/device.map e anche nel file di backup, in caso contrario aggiungere quelo mancante e ripetere l'installazione di GRUB
root@system:~# cat /boot/grub/device.map
(hd0) /dev/sda
(hd1) /dev/sdb
Infine, se tutta la procedura fin qui desritta è andata a buon termine, sul secondo disco è presente una copia del primo con la configurazione adatta per un avvio corretto del sistema, a patto che il primo disco venga scollegato. Il passo finale è far si che la procedura di aggiornamento del backup avvenga giornalmente, per esempio alle 02:01AM, aggiungendo una riga al file /etc/crontab nella quale si richiama lo script utilizzato per il backup, come mostrato di seguito
root@system:~# nano -w /etc/crontab
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
01 2 * * * root /usr/sbin/mirroring >> /var/log/mirroring.log
In ultimo, qualora si verificassero problemi al login dopo l'avvio del disco di backup, assicurarsi, in caso di utilizzo del sistema SElinux, di aver aggiornato la configurazione di tutto l'albero delle directory copia (-- inserire comando--), pena l'impossibilità di accesso al sistema.
Per concludere si ricorda che tutte le procedure qui riportate sono state realmente applicate e derivano da una reale situazione in cui la necessità di avere un sistema di backup affidabile e avvibile ha portato ad uno studio, anche se non a livello professionale, dello scenario e alla successiva personale soluzione, la quale può presentare discordanze in caso di diversi sistemi, architetetture o applicativi utilizzati, ma che rimane comunque un buon punto di partenza.
Qualsiasi consiglio, correzione o aggiunta può essere inoltrato all'autore, che provvederà con piacere alla miglioria del testo.