Appunti sull'uso di mdadm per gestire il raid software
Ottenere informazioni su un raid set
Per sapere tutto cio` che il sistema puo` dirci su un raid set, si usa il comando
mdadm --detail <device raid> mdadm --detail /dev/md0
Se possediamo solo un disco estratto da un raid set, possiamo usare
mdadm -E <partizione o device che era parte del raid set> mdadm -E /dev/sdb1
Questi due comandi, che forniscono informazioni utili quando qualcosa e` collassato malamente e dobbiamo trovare il modo di rimettere assieme i cocci, sono innocui e possono essere usati in qualsiasi momento su raid set attivi o dischi attivi.
Provare a recuperare un raid set danneggiato
Questi comandi sono potenzialmente pericolosi!
Per provare a ricostruire un raid set che ha i dischi in uno stato incoerente, si puo` tentare questo:
mdadm --stop /dev/mdX mdadm --assemble /dev/mdX /dev/sdX1 /dev/sdX2 /dev/sdX3 eccetera (i componenti del raid)
Se fallisce perche` i componenti sono fuori sincro, lo si puo` forzare con "-f". Attenzione perche` questo comporta il fatto che i dischi saranno rimessi forzatamente in sincro, semplicemente "assumendo" che siano in sincro anche se non lo sono, e quindi se sono desincronizzati in modo significativo si macinera` il file system. Una cosa che si puo` tentare di fare e` VEDERE prima di forzare, quanto sono fuori sincro i componenti.
Usando mdadm -E /dev/sdXN (uno per ogni componente dell'array macinato) si imparano due cose interessanti: la prima e` il numero di "Events" che il disco ricorda: questo e` il numero sequenziale delle operazioni effettuate dal raid su quel disco, e in pratica per essere "up to date" i dischi devono avere tutti lo stesso numero di eventi. Piu` il numero e` alto piu` il disco e` "fresco", piu` e` basso piu` tempo fa e` stato espulso dall'array. Se vogliam tentare una ricostruzione dovremo tenere conto che i dischi con un numero di eventi piu` basso sarebbe meglio NON USARLI per la ricostruzione, quindi per esempio di un raid5 che ha un disco palesemente piu` "indietro" degli altri, conviene tentare una ricostruzione degradata nella quale il disco piu` vecchio non viene usato. La seconda cosa che si impara e` come era lo stato del raid quando quel disco e` andato offline per l'ultima volta. Alla voce "Array state" si vede infatti uno stato fatto di "A" per "attivo" e "." per mancante / non attivo, dove si vede come erano gli altri dischi nel momento in cui il disco che stiamo interrogando era ancora in linea.
Facendo un esempio pratico: un raid5 con 4 dischi, i quali hanno contatori di eventi che sono rispettivamente: 81404, 81400, 81400, 40 mi dice che posso tentare un recovery forzando i primi 3 ad avviare il raid in modo degradato, ma sicuramente non il quarto il quale e` fuori dal raid da tempo immemore (40 eventi contro 81.400).
Quindi potremmo tentare un:
mdadm --assemble /dev/mdX /dev/sda1 /dev/sdb2 /dev/sdc2 -f
O forse:
mdadm --assemble /dev/mdX /dev/sda1 /dev/sdb2 /dev/sdc2 missing -f
Dove abbiamo VOLUTAMENTE OMESSO il quarto componente, che e` totalmente fuori sincro!
Recuperare un raid set con il superblock danneggiato o cancellato
Un giorno ho fatto una cazzata: ho per sbaglio danneggiato il superblock di un componente di un raid5. I dati ci sono, ma il sistema non sa come leggerli. La soluzione e` quella di ricreare il raid set con le giuste configurazioni ignorando il contenuto dei superblock pre-esistenti. Fintanto che si ricrea il raid set nel modo giusto (ovvero come era prima) tutto funziona.
Esaminando il superblock di uno dei dischi che non avevo danneggiato per errore, vedo quanto segue:
root@backupsrv2:~# mdadm -E /dev/sdd2 /dev/sdd2: Magic : a92b4efc Version : 1.2 Feature Map : 0x0 Array UUID : f9a49649:4d3bab5c:b3ac2b2d:bcd2d3b1 Name : backupsrv2:1 (local to host backupsrv2) Creation Time : Mon Apr 27 11:06:34 2015 Raid Level : raid5 Raid Devices : 4 Avail Dev Size : 3896221696 (1857.86 GiB 1994.87 GB) Array Size : 5844331008 (5573.59 GiB 5984.59 GB) Used Dev Size : 3896220672 (1857.86 GiB 1994.86 GB) Data Offset : 262144 sectors Super Offset : 8 sectors State : clean Device UUID : 8dd687b1:df97a31d:9d2362f3:2571b4a6 Update Time : Tue Oct 27 07:01:43 2015 Checksum : 226e0618 - correct Events : 40 Layout : left-symmetric Chunk Size : 512K Device Role : Active device 3 Array State : AAAA ('A' == active, '.' == missing)
A questo punto quello che mi interessa e`:
- l'ordine dei device, che dal superblock si vede ma non e` detto che si veda completamente. Ogni disco che ha ancora un superblock valido mostra alla voce "Device Role" il proprio "numero" di posto.
- Il tipo di raid (Raid Level)
- Il numero di device totali (Raid Devices)
- Il layout (Layout)
- La dimensione del chunk (Chunk size)
- La versione del superblock
Con questi dati posso forzare la ricreazione del raid set senza perdere dati, avendo cura di indicare le stesse impostazioni che c'erano prima, in questo modo:
mdadm --create /dev/md1 --chunk=512 --level=5 --raid-devices=4 /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2
Devono essere rispettati tutti i parametri elencati prima, molti sono a default ma nel dubbio e` meglio verificare e aggiungere le opzioni che indicano cosa vogliamo fare esattamente. Anche l'ordine in cui indico i componenti deve essere rispettato.
Facendo questo si genera un nuovo array come se fosse vergine, pero` con dentro i dati che c'erano prima!
Si puo` verificare ora se il file system che c'e` dentro e` coerente con un fsck -n (-n per "non fare nulla" perche` e` meglio essere sicuri che funzioni anziche` macinarlo per errore)
Ricordiamo che se tutto e` OK dobbiamo comunque rifare il file /etc/mdadm/mdadm.conf con il nuovo UUID del raid appena creato, che non e` piu` quello vecchio. (si veda piu` sotto come fare)
Creare un raid 1
Per creare un raid set (diciamo raid 1 in questo esempio) partendo da zero, occorre:
- Partizionare i dischi in modo da avere partizioni di tipo "raid autodetect" (FD)
- Creare il raid set con il comando mdadm --create. (leggetevi la man page a riguardo del superblock e dei metadati di default)
mdadm --create <md-device> --level=<raid-level> --raid-devices=<count> <device-list> mdadm --create --verbose /dev/md2 --level=1 --raid-devices=2 /dev/sde1 /dev/sdf1
- Creare il file system sul raid appena creato con mkfs (questo dovrebbe fare anche partire il rebuild)
Creare un raid 5
Per creare un raid5 di tre dischi (per esempio) partendo da zero, occorre:
- Partizionare i dischi in modo da avere partizioni di tipo "raid autodetect" (FD)
- Creare il raid set con il comando mdamd --create.
mdadm --create <md-device> --level=<raid-level> --raid-devices=<count> <device-list> mdadm --create --verbose /dev/md2 --level=5 --raid-devices=3 /dev/sde1 /dev/sdf1 /dev/sdg1
- Prendere nota dell'output e vedere quale e` il "chunk size" che mdadm ha scelto (e` possibile anche forzarlo a mano, cambiandolo cambiano le prestazioni a seconda del tipo di uso che si fara` del raid set, e` un casino prenderci)
- Applicare quando si formatta il disco una formula per ottimizzare la formattazione adattando il file system al chunk size e al numero di dischi.
Se si formatta in ext4, per esempio, la formula e`:
- stride = chunk_size / block_size
- stripe-width = stride * ((number of disks in raid5)-1)
Quindi, per un raid con chunk size di 512KB e se formattiamo con blocchi di 4k (il default di ext4) allora avremo:
- stride = 512 / 4 = 128
- stripe-width = 128*(3-1) = 128*2 = 256
La formattazione quindi si fara` con il comando:
mkfs.ext4 -v -m .1 -b 4096 -E stride=128,stripe-width=256 /dev/md2
Cambiare il nome a un raid set preesistente
Poniamo di avere un raid gia` configurato, ad esempio /dev/md3 e di volerlo rinominare in /dev/md0. Ovviamente questo presuppone che md0 non esista gia`. Questa operazione richiede uno stop del raid set, il quale deve quindi non essere in uso. Se occorre dovremo avviare da una live. Dobbiamo sapere anche quali dischi sono membri del raid set, ci servira` dopo.
- Stoppare il raid set (se e` gia` stato assemblato) con il comando
mdadm --stop /dev/md3
PER METADATA 0.90: Riassemblare il raid set imponendo un cambio di minor per il device, e salvando questo cambio nel superblock del raid set, in modo che questo sia persistente da ora in avanti. In questo caso, il nuovo nome e` md0 e il vecchio e` md3 (da qui il "-m3"). Sembra che il comando dato sia al contrario, e invece e` giusto cosi`, il vecchio nome va indicato come parametro in "-m" e il nuovo viene indicato esplicitamente come /dev/md0.
mdadm --assemble <nuovo device md> -m<vecchio minor> --update=super-minor <disco membro 1> <disco membro 2> .. <disco membro N> mdadm --assemble /dev/md0 -m3 --update=super-minor /dev/sda1 /dev/sdb1
PER METADATA 1.x: Riassemblare il raid set imponento un cambio di nome e salvandolo nel superblock. Anche in questo esempio il nuovo nome e` md0 e il vecchio e` ininfluente:
mdadm --assemble <nuovo device md> --name=<numero device md nuovo> --update=name <disco membro 1> <disco membro 2> .. <disco membro N> mdadm --assemble /dev/md0 --name=0 --update=name /dev/sda1 /dev/sdb1
Verificare se il raid set e` venuto bene con mdamd --detail /dev/md0} (o il device corrispondente al raid che avete creato), dovreste vedere il nome corretto.
verificare in generale se e` tutto ok con mdamd --examine --scan, che come output da` l'equivalente del contenuto di /etc/mdadm/mdadm.conf.
- Aggiornare il file /etc/mdadm/mdadm.conf di conseguenza
Probabilmente dovrete anche aggiornare la initramfs per importarvi le modifiche a mdadm.conf, con il comando update-initramfs -u
Cambiare UUID a un raid set preesistente
Se vogliamo impostare uno specifico UUID a un raid set (diverso da quello random assegnato alla creazione) possiamo farlo seguendo lo stesso metodo del cambio di nome del device appena descritto sopra. In questo esempio supponiamo di voler modificare lo UUID del raid /dev/md2.
- Stoppare il raid set (se e` gia` stato assemblato) con il comando
mdadm --stop /dev/md2
- Riassemblare il raid set imponendo un nuovo UUID e salvandolo nei metadati:
mdadm --assemble <device md> --update=uuid --uuid=<NUOVO UUID> <disco membro 1> <disco membro 2> .. <disco membro N> mdadm --assemble /dev/md0 --update=uuid --uuid=3a562b19:6ed0dd0c:94b52490:b189165a /dev/sda1 /dev/sdb1
Modifiche al file mdadm.conf
Supponiamo di aver fatto modifiche ai raid set presenti sulla macchina, e di voler confrontare (o modificare) il contenuto del file /etc/mdadm/mdadm.conf specialmente per quanto riguarda le righe che iniziano per "ARRAY" che contengono i dati dei raid set presenti sulla macchina. Possiamo verificare la situazione attualmente vista dal kernel (che puo` appunto essere diversa da quella indicata nel file /etc/mdadm/mdadm.conf con questo comando:
mdadm --examine --scan
L'output di questo comando puo` essere direttamente incollato nel file /etc/mdadm/mdadm.conf in quanto e` volutamente compatibile. Attenzione: dopo aver modificato mdadm.conf dovete lanciare il comando
update-initramfs -u
per copiare le modifiche dentro al ramdisk di avvio del kernel in uso, altrimenti al boot rischiate che i raid set modificati non vengano assemblati.
Probabilmente si ottiene lo stesso risultato (e anche meglio) se (vale solo per Debian) si esegue:
dpkg-reconfigure mdadm
Aggiungere o togliere dischi da un raid 1
Se vogliamo sostituire i dischi di un raid funzionante, e abbiamo spazio per connetterli, potremmo decidere di aggiungere prima i nuovi dischi, e poi togliere i vecchi. Per esempio, potremmo prendere un raid1 di 2 dischi, aggiungerne due nuovi, sincronizzare, e poi rimuovere i due vecchi. Supponiamo che la situazione sia:
- /dev/md0 composto da /dev/sda1 e /dev/sdb1
- Dischi nuovi in /dev/sdc e /dev/sdd
Per farlo, occorre:
- collegare i dischi nuovi al sistema in modo che il kernel li veda
- creare sui dischi nuovi le partizioni copiandole dai vecchi oppure rifacendole come meglio crediamo (tipo FD, ovviamente)
- aggiungere le partizioni sui dischi nuovi ai device md del raid pre-esistente
mdadm --add /dev/md0 /dev/sdc1 mdadm --add /dev/md0 /dev/sdd1
Ora il device /dev/md0 e` composto di due dischi "online" e due dischi "spare" (controllate con un cat /proc/mdstat). Possiamo quindi renderlo di 4 dischi tutti attivi con un "grow"
mdadm -G /dev/md0 -n 4
- Attendiamo che finisca la risincronizzazione del raid sui nuovi dischi. Alla fine avremo un raid con 4 dischi attivi assieme
- Modifichiamo la configurazione di GRUB, se necessario, e installiamo GRUB sui dischi nuovi
grub-install /dev/sdc grub-install /dev/sdd
spegnamo la macchina, togliamo i dischi vecchi e riavviamo. Se Grub non fa casino avremo i dischi nuovi visti come /dev/sda e /dev/sdb (in realta` non e` importante, basta che il kernel li veda e costruisca /dev/md0) e ovviamente avremo (cat /proc/mdstat per vederlo) un raid con 4 dischi di cui due attivi e due "morti". Ora, siccome vogliamo che non ci dia allarme di raid degradato ad ogni avvio, dobbiamo eliminare i dischi morti dal raid. Per farlo, basta dire al raid "tu sei composto da due dischi", e lui auto-eliminera` (logicamente) i due che non ci sono piu`.
mdadm -G /dev/md0 -n 2
Finito, abbiamo /dev/md0 con due dischi, come era all'inizio, pero` i dischi sono nuovi.
Ingrandire un file system in raid sostituendo i dischi con dischi piu` grandi
Ponendo di avere un raid (diciamo raid1, ma va bene anche con il 5) con due dischi da 500 GB e volere ingrandire il tutto a 2 TB, la cosa e` fattibile anche online (puo` essere che occorra smontare o riavviare a seconda di che fs si usa e di che controller si usa).
Prima di tutto, occorre cambiare tutti i dischi del raid (uno alla volta!) in modo da incrementare la dimensione della partizione su ogni disco. Avendo un controller che gestisce l'hot swap, è possibile fare tutto online:
Mettere un disco in fail: mdadm --fail /dev/md2 /dev/sdc1
Togliere il disco dall'array: mdadm --remove /dev/md2 /dev/sdc1
- Togliere il disco FISICO dal suo bay (togliamo sdc, vediamo di prenderci!)
- Infilare il disco fisico nuovo nel bay e vedere che device prende, supponiamo qui che sia nuovamente sdc
- Partizionare il disco nuovo non copiando le partizioni dal vecchio, ma creandole nuove e più grandi, sempre di tipo FD per il raid.
Inserire il nuovo disco nell'array: mdadm --add /dev/md2 /dev/sdc1
- Attendere che sincronizzi fino alla fine
- Ripetere la procedura dall'inizio togliendo però l'altro disco, e sostituendolo come sopra.
A questo punto, abbiamo un device md (md2 nel nostro esempio) che pur trovandosi composto di due partizioni grandi, resta piccolo. Occorre adesso ingrandire il device. Per farlo, occorre prima di tutto verificare se esiste la write intent bitmap, e nel caso toglierla (e poi ricrearla). Se non la si toglie, potrebbe corrompersi tutto quanto in quanto lo spazio ad essa dedicato potrebbe risultare insufficiente rispetto alla dimensione della nuova partizione. Quindi:
mdadm --grow /dev/md2 --bitmap none mdadm --grow /dev/md2 --size max # Attendere che finisca il lavoro di resync mdadm --grow /dev/md2 --bitmap internal
Se ha funzionato, ora un cat /proc/partitions ci dirà che /dev/md2 è più grande di prima, ed è grande quasi come le partizioni in cui è contenuto. Va notato che verrà anche avviato un rebuild che ricostruisce la parte "aggiunta" del device MD.
A questo punto, occorre ridimensionare il filesystem stesso all'interno della partizione. Se usiamo ext3, e un kernel sufficientemente moderno (2.6), possiamo resizeare anche online, senza smontare la partizione, cosi`: resize2fs /dev/md2. Questo comando ingrandisce il file system fino alla dimensione della partizione in cui si trova. Se vogliamo giocare sicuro, smontiamo il filesystem e diamo lo stesso comando su un fs smontato. Se vogliamo giocare ancora piu` sicuro, diamo un fsck prima e dopo il resize (ovviamente sempre a file system smontato). Tenete conto che il resize puo` essere molto lungo (decine di minuti) se il cambio di dimensione e` significativo.
Per riferimento, vedasi: http://www.howtoforge.com/how-to-resize-raid-partitions-shrink-and-grow-software-raid e https://raid.wiki.kernel.org/index.php/Growing
Cambiare un disco rotto
Cambiare il disco rotto. Se non si sa riconoscere il disco, usando hdparm -I /dev/sdX e` possibile leggere il numero di serie dei vari dischi, in modo da poter riconoscere senza dubbio quale sia fisicamente quello rotto.
- Sperare che GRUB booti dal disco che resta
- Copiare la tabella delle partizioni dal disco buono a quello nuovo e vuoto.
sfdisk -d /dev/discooriginale | sfdisk /dev/disconuovo
- Mettere nel raid il nuovo disco (tutte le partizioni una per una)
Esempio: per aggiungere il device fisico /dev/sdb1 al raid /dev/md0: mdadm /dev/md0 --add /dev/sdb1
Installare un raid1 con un solo disco e poi aggiungere il secondo
Se vi capita di fare una installazione in cui sapete che farete un raid1, ma adesso avete un solo disco, potete installare facendo un raid1 con un solo device, e poi, dopo aver collegato il secondo disco, includerlo nei raid.
La procedura e`:
- Installare il secondo disco
- Copiare la tabella delle partizioni dall'uno all'altro (dal pieno al vuoto, magari!)
sfdisk -d /dev/discooriginale | sfdisk /dev/disconuovo
- Per ognuno dei device raid1, aggiungere il secondo disco.
- Prima di tutto aggiungo il secondo disco come hotspare (ridicolo un hotspare con un solo disco attivo!). Facendo questo non inizia la risincronizzazione, perche` il secondo disco e` un hotspare, non e` online.
mdadm /dev/md0 -a /dev/sdc1
- Poi modifico il numero di device nel raid da 1 a 2, in questo modo l'hotspare diventa "online" ed inizia la sincronizzazione.
mdadm /dev/md0 --grow -n 2
- Prima di tutto aggiungo il secondo disco come hotspare (ridicolo un hotspare con un solo disco attivo!). Facendo questo non inizia la risincronizzazione, perche` il secondo disco e` un hotspare, non e` online.
Questa l'ho usata su Etch con il kernel 2.6.18 e ha funzionato, pero` se sminchia a morte il vostro sistema, io non voglio sapere nulla.
Eliminare totalmente i dati di md da un disco
Se occorre eliminare ogni traccia delle configurazioni di md da un disco, occorre:
Fermare il volume raid con mdadm --stop /dev/mdX
Eliminare ogni informazione relativa a md dalle partizioni dei dischi fisici che componevano il volume raid: mdadm --zero-superblock /dev/sdXN