Aquesta és una història d’una matriu de discs que contenia una instal·lació de Zimbra amb uns 100 usuaris. És una història amb final feliç, perquè les dades s’acaben recuperant, però a la vegada és una tragicomèdia sobre les misèries de l’administració de sistemes.

El problema

Hi havia una vegada un servidor HP ProLiant ML310 G3 que tenia un disc de sistema (/dev/sda) de 80 GB i un RAID 5 de dades (/dev/md0) format per 3 discs de 160 GB (/dev/sd[bcd]1). Tot va anar bé fins que el servidor es va quedar durant un temps al passadís (!) i els discs van estar-se sis mesos a 60 graus. A més a més la persona que se’n encarregava va considerar que la millor manera de que estiguessin més fresquets era treure la tapa lateral al servidor. Això només va fer que empitjorar el problema, perquè el flux d’aire que injecten els ventiladors posteriors, tant bon punt entra a la torre surt per el lateral i no passa per la cabina de discos.

No es d’estranyar que aviat un dels tres discs de la matriu (el /dev/sdd) comencés a donar avisos SMART de que tenia problemes:

smartctl -a /dev/sdd
(...)
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Short offline Completed: read failure 60% 42169 312570497
# 2 Short offline Completed: read failure 60% 42145 312570998
# 3 Extended offline Completed: read failure 10% 42121 312570999
(...)

Es va demanar un disc de recanvi que mai va arribar. No es va insistir prou? No ho sé. La qüestió és que al cap de quatre mesos un dels altres discs va deixar de funcionar de sobte, sense cap avís. El SMART va avisar després que /dev/sdb comencés a donar I/O errors.

El kernel de seguida va treure el disc de la matriu i llavors nosaltres intentem treure’l i tornar-lo a posar a dins (què!? a vegades funciona):

mdadm --remove /dev/md0 /dev/sdb1; mdadm --add /dev/md0 /dev/sdb1
Personalities : [raid5]
md0 : active raid5 sdb1[3] sdd1[2] sdc1[1]
312576512 blocks level 5, 256k chunk, algorithm 2 [3/2] [_UU]
[>....................] recovery = 0.0% (147328/156288256) finish=353.1min speed=7366K/sec

però en aquest cas no funciona perquè el disc sdb està realment KO:

Nov 25 09:51:42 arxiver023 kernel: Invalid sdb: sense key No Sense
Nov 25 09:51:42 arxiver023 kernel: end_request: I/O error, dev sdb, sector 510663

Aquest cop demanem un disc que sí que arriba. Així doncs canviem el disc sdb per el nou i tot arreglat, no? La matriu es reconstruirà utilitzant la informació de paritat  que hi ha a sdc i sdd. Com que no tenim una controladora hot swap hem de parar el servidor, canviar el disc sdb, i tornar a engegar el sistema que per cert és un CentOS 4.9.

Però no és així perquè el disc sdd te sectors que no es poden llegir!

Dec 1 20:30:32 arxiver023 kernel: end_request: I/O error, dev sdd, sector 312570431
Dec 1 20:30:33 arxiver023 kernel: end_request: I/O error, dev sdd, sector 312570439
...

La matriu queda en una situació llastimosa en la que es nega a engegar-se. Ah! i el millor és que no hi ha copia de seguretat. FAIL!

La solució

Tal com diu la Guia de l’Autoestopista Galàctic: “Don’t Panic!”. Aquest és el check list d’emergència:

  1. Comunicar als usuaris que s’estaran una bona estona sense accés al servei
  2. Fer una copia de seguretat del que queda dels discos
  3. Engegar el que queda de la matriu i treure’n les dades que es pugui
  4. Tornar a crear la matriu amb discos bons
  5. Posar-hi les dades del punt #3 altre cop a dins
També és interessant comentar la línia de /etc/fstab que munta el filesystem afectat, perquè el sistema pugui acabar d’arrancar correctament. Així es poden activar certs serveis, com ara el sshd i treballar-hi en remot.

Backup dels discos

Amb dd fer una còpia dels discos que formen el RAID 5, perquè mai se sap què li pot passar als discos mentre intentem refer la matriu:

dd if=/dev/sdb1 of=/mnt/usb/sdb1.dd bs=4k
dd if=/dev/sdc1 of=/mnt/usb/sdc1.dd bs=4k
dd if=/dev/sdd1 of=/mnt/usb/sdd1.dd bs=4k

En el sdd dóna errors de lectura “dd reading `/dev/sdd1′: Input/output error” i el fitxer sdd1.dd és més petit. En cas de que en els passos posteriors féssim malbé algun disc podríem crear els dispositius de blocks amb els fitxers

losetup /dev/sdb1-backup /mnt/usb/sdb1.dd

Recrear la matriu

Donar un cop d’ull a les instruccions per recuperar un RAID de kernel.org que aplicades al nostre cas:

mdadm --create --assume-clean --level=5 --raid-devices=3 --chunk=256 /dev/md0 missing /dev/sdc1 /dev/sdd1
mdadm: /dev/sdc1 appears to be part of a raid array:
level=5 devices=3 ctime=Sat Dec 3 09:45:25 2011
mdadm: /dev/sdd1 appears to be part of a raid array:
level=5 devices=3 ctime=Sat Dec 3 09:45:25 2011
Continue creating array? y
mdadm: array /dev/md0 started.

Això substituirà les metadades md que hi ha als discos i assumirà que el que contenen és el que li diem nosaltres, és a dir un RAID 5 amb chunk size de 256k. És important posar el chunk size que toqui. També és important posar un dispositiu missing, ja que si els posem tots tres de seguida es posa a reconstruir la matriu i això no ho volem perquè el disc sdd te sectors defectuosos.

Si hem encertat l’estructura a /dev/md0 hauria d’haver-hi el sistema d’arxius o, com en el nostre cas, el LVM. Per muntar-ho fem:

pvscan -v
lvchange -a y /dev/vg1/data # activar el volume group
mount /dev/mapper/vg1-data /mnt/array/ -o ro
rsync -a -v /mnt/array /mnt/usb/ # salvar les dades

Amb això copiem les dades a un altre sistema d’arxius, en el nostre cas un disc USB. Si hi ha sort els sectors defectuosos no afectaran a l’estructura del ext3 ni a cap de les dades que conté. En tot cas el més probable és que algun fitxer no es pugui recuperar.

A partir d’aquí només queda tornar a crear una matriu, fer un rsync de les dades cap a dins la matriu i tornar a engegar els serveis. En el nostre cas hem hagut de prescindir del RAID 5 i fer un RAID 0 (amb LVM) perquè no tenim cap disc de recanvi.

Conclusions

Fer copia de seguretat. Si el client no ho vol: insistir. Cap RAID pot evitar la pèrdua de dades. Insisteixo: fer copia de seguretat.

Substituir de seguida qualsevol disc amb errors al SMART. Especialment si és part d’un RAID 5.

Fer un check periòdic del RAID per evitar que els sectors defectuosos passin desapercebuts. Versions més noves de mdadm ja porten un cron per fer-ho. Per exemple a Debian /etc/cron.d/mdadm executa /usr/share/mdadm/checkarray cada primer diumenge de mes.

El rendiment d’escriptura d’un RAID 5 és patètic. Un cop tret el RAID 5 el sistema és més ràpid. Ara la CPU ha d’esperar menys a que el Kernel escrigui a disc (hi ha menys iowait).

Dubto molt que amb un RAID hardware s’hagués pogut recuperar les dades. La llibertat d’un Linux Software RAID sobrepassa qualsevol consideració de rendiment.