====== RAID: uso de mdadm y recuperación de desastres ======
Este artículo es una colección de notas tomadas a lo largo de años de trabajar con RAID. Es un recordatorio de comandos, así como de procedimientos de recuperación de desastres.
===== Tareas generales =====
==== Particionar un disco en forma idéntica a otro con MBR ====
sfdisk -d /dev/hdb | sfdisk /dev/hdc
==== Particionar un disco en forma idéntica a otro con GPT ====
sgdisk /dev/sdX -R /dev/sdY
sgdisk -G /dev/sdY
El primero comando copia la tabla de particiones del disco sdX al sdY. El segundo randomiza los GUID de cada partición del disco sdY, lo cual es imprescindible ya que serán usados en el mismo equipo.
==== Obtener el número de serie de un disco (serial number) ====
Este procedimiento es sumamente importante en el caso de falla de un disco, para poder identificarlo fehacientemente y reemplazarlo. El número de serie indicado por estos comandos es el mismo impreso en la etiqueta del disco, y por lo tanto puede ser usado para hacer valer la garantía.
smartctl -i /dev/hdb
hdparm -i /dev/hdb
==== Copiar un disco completo en otro nuevo ====
Obviamente los discos deben ser idénticos. Se puede intentar hacer esto cuando hay algunos bad sectors (sectores malos o dañados) en el disco original, y se lo reemplaza por uno nuevo. Es probable que hecho esto no se pierda demasiada información en el disco final.
Ese nuevo disco puede ser luego usado para recrear el RAID como si fuera el original, ya que son idénticos (incluyendo los datos que se perdieron debido a que estaban sobre sectores dañados).
Lo mejor es utilizar el utilitario de recuperación dd_rescue (aptitude install ddrescue en Debian GNU/Linux). Es más rápido y más confiable que usar simplemente dd (descrito abajo):
dd_rescue -v /dev/sdA /dev/sdB
Donde sdA es el disco origen y sdB el destino. Es un proceso que tarda generalmente muchas horas, dependiendo del tamaño del disco y de la cantidad de bad sectors. Por ejemplo, para discos de 500GB es probable que tarde entre 4 y 6 horas, según lo mencionado.
Si no se dispone de este utilitario, se puede intentar con dd. En teoría debería funcionar, pero no es muy confiable dado que el disco origen suele estar plagado de problemas. Si se desea intentarlo, se puede usar la siguiente serie de parámetros:
dd if=/dev/sdA of=/dev/sdB bs=10240k conv=noerror,sync
Si se desea ver el progreso de copiado con dd, se debe usar el utilitario pv (aptitude install pv en Debian GNU/Linux):
dd if=/dev/sdA bs=10240k conv=noerror,sync | pv -c -b -r -t > /dev/sdB
Si hay demasiados sectores dañados, es redundante mencionar que probablemente el disco destino no sirva ya para ser agregado al RAID y sus datos se hayan perdido. De cualquier manera, si se está realizando esto es porque ya no queda más remedio (por ejemplo, en el caso de que hayan fallado dos discos en un RAID5, y se pretende tratar de recuperar el desastre). Bajo ciertas condiciones, y con un poco de ayuda del Supremo, quizá quede otra vez la unidad md en estado funcional.
=== Bibliografía ===
* http://www.cgsecurity.org/wiki/Damaged_Hard_Disk
===== RAID (mdadm) =====
==== Crear una unidad RAID5 ====
mdadm --create /dev/md5 --level=5 --raid-devices=3 /dev/sda9 /dev/sdb9 /dev/sdc9
==== Ver configuración de la unidad RAID que falla ====
mdadm --detail /dev/md3
cat /proc/mdstat
==== Agregar unidades físicas al RAID: cuando se desconectan, agregarlas con ====
mdadm --manage -a /dev/md3 /dev/hdd8
==== Desactivar una unidad RAID: ====
mdadm --misc -S /dev/md3
==== Activar una unidad RAID ====
mdadm --assemble /dev/md3
==== Cuando se rompe un disco ====
- Cambiar el disco roto por uno idéntico
- Particionarlo con sfdisk:
sfdisk -d /dev/sdX | sfdisk /dev/sdN
Donde X es un disco preexistente funcional y N es el disco nuevo
- Agregar el disco o particiones a las unidades MD:
mdadm --add /dev/md0 /dev/sdc1
==== Agregar un disco o partición a un RAID5, para incrementar el espacio disponible ====
mdadm --add /dev/md0 /dev/sde1
mdadm --grow /dev/md0 --raid-devices=4
Cuando termine de sincronizar, lo cual puede llevar varias horas dependiendo del tamaño del array, se debe extender el sistema de archivos a toda la unidad RAID:
resize_reiserfs /dev/md0
o bien:
resize2fs /dev/md0
==== Agregar un disco a una unidad RAID0 ====
* Obviamente tiene que ser otro idéntico, y el proceso tardará **mucho** tiempo
* mdadm hará un reshape a RAID4, sincronizará y finalmente volverá a RAID0
* Lo he usado para pasar de dos discos con datos a una unidad RAID0 que combina ambos:
- Se mueven primero todos los datos del primer disco al segundo
- Se convierte el primero a RAID0
- Se vuelven a mover los datos a esa nueva unidad
- Se agrega el segundo disco:
mdadm /dev/md0 --grow --raid-devices=2 --backup-file=/root/grow_md0.bak --add /dev/sdb5
- Luego se vuelve a hacer un reshape a RAID0:
mdadm /dev/md0 --grow --level=0 --raid-devices=2 --backup-file=/root/grow_md4.bak
- Finalmente, convertir la unidad a RAID0 con:
echo raid0 > /sys/block/md0/md/level
- Hecho eso, la unidad se puede utilizar. Para comprobar que esté todo bien:
mdadm -D /dev/md0
==== Renombrar una unidad MD ====
Primero se debe detener la unidad en cuestión:
mdadm --stop /dev/md127
Luego, ensamblarla con el nuevo nombre, cuidando de poner algo similar a lo que ya esté en mdadm.conf:
mdadm --assemble --update=name --name=srv01:4 /dev/md4 /dev/sda8 /dev/sdb8
Luego se debe agregar la información de esta unidad en el archivo mdadm.conf, lo que se obtiene con el comando
mdadm --examine --scan
La línea correspondiente a esta nueva unidad debe ser copiada al archivo mdadm.conf
Finalmente, se debe actualizar el archivo initrd.img:
update-initramfs -u
==== Crear el archivo de configuración mdadm.conf desde cero ====
- Agregar en /etc/mdadm/mdadm.conf lo siguiente:
# mdadm.conf
#
# Please refer to mdadm.conf(5) for information about this file.
#
# by default, scan all partitions (/proc/partitions) for MD superblocks.
# alternatively, specify devices to scan, using wildcards if desired.
DEVICE partitions
# auto-create devices with Debian standard permissions
CREATE owner=root group=disk mode=0660 auto=yes
# automatically tag new arrays as belonging to the local system
HOMEHOST
# instruct the monitoring daemon where to send mail alerts
MAILADDR root
- Luego agregar los dispositivos (que ya tienen que haber sido creados), con:
mdadm --detail --scan >> /etc/mdadm/mdadm.conf
y verificar que haya quedado todo bien. Otro método para escanear todas las particiones en búsqueda de unidades md es:
mdadm --examine --brief --scan --config=partitions
- Si se está migrando un sistema de no-RAID a RAID, es probable que haya que regenerar el initrd correspondiente al kernel que se esté usando, para que inicie el sistema:
mkinitrd -r /dev/md0 -o /boot/initrd.img-2.6.8-4-k7
===== Montar unidades RAID =====
En vez de usar para montar el dispositivo (p.ej. /dev/md0), conviene usar el UUID del sistema de archivos, de la siguiente manera:
# /etc/fstab: static file system information.
#
#
proc /proc proc defaults 0 0
# /dev/md0
UUID=80dd4e01-3bcb-40a9-858f-84f222c7fb76 / reiserfs notail 0 1
# /dev/md2
UUID=a675b65b-2468-4ce0-b9b8-a18e18ad982e /tmp reiserfs defaults 0 2
# /dev/md3
UUID=df777ce0-1adf-481b-b4cd-ee9995226671 /usr reiserfs defaults 0 2
# /dev/md4
UUID=16a357e5-9733-4eea-9294-0fadb2160883 /var reiserfs defaults 0 2
# /dev/md5
UUID=c7cba866-7042-4cad-9d35-7dfcf177a164 /home reiserfs defaults 0 2
# /dev/md1
UUID=3a5e831d-8458-470c-a80a-88f481fb5944 none swap sw 0 0
/dev/scd0 /media/cdrom0 udf,iso9660 user,noauto 0 0
El UUID puede conocerse mediante alguno de los siguientes comandos:
ls -l /dev/disk/by-uuid/
o bien:
blkid /dev/md4
Para conocer más detalles del dispositivo:
vol_id /dev/md4
===== Reconstruir desastres (1) =====
-I examined the good superblocks to make sure I knew how to recreate the array exactly (i.e. chunk size, etc).
-I zeroed all the superblocks on all the disks.
-I recreated the array with the "--assume-clean" option.
-I marked it possibly dirty with:
mdadm --assemble /dev/md0 --update=resync
-I let it try to resync. This only took about 30-60 minutes, probably because all the data was good and it was just reading from each disk and not writing.
-I mounted it & everything so far appears to be good.
-Alternately, I think I could have simply recreated it without "--assume-clean" and the initial creation sync wouldn't have destroyed the data, but that wasn't a risk I was willing to take.
===== Reconstruir desastres (2) =====
Viernes por la noche. Argentina. Se cortó la luz, volviendo una hora más tarde. Luego de encender nuevamente el servidor, por alguna razón desconocida, se colgó. Al encenderlo por segunda vez, mdadm había desconectado uno de los dispositivos (sdb1) de la unidad md RAID5 (cuatro discos de 500GB, sin spare). Por lo tanto, entré en runlevel 1 y la agregué nuevamente con mdadm --add /dev/md0 /dev/sdb1, comenzando así a sincronizar. Esto fue a las 2300 hs, por lo que me fui a dormir. Cuando volví, descubrí con desagrado que luego de terminar la sincronización, otro de los discos había fallado, pero ahora mdadm había desconectado el primero así como a este otro (sdb1 y sdd1). Como sabía que la sincronización anterior había terminado y la unidad md no había sido usada, estimé que sería posible rescatar la unidad del desastre. Por lo tanto, leí toda la documentación que pude encontrar, y luego de nada más que unas tres o cuatro horas, comencé a trabajar. El procedimiento de rescate fue el siguiente:
-Detener el array:
mdadm --stop /dev/md0
-Crear nuevamente la unidad md, teniendo la precaución de usar la opción --assume-clean que informa a mdadm que el array ya existe:
mdadm --create /dev/md0 --assume-clean --level=5 --raid-devices=4 --metadata=1.2 /dev/sdb1 /dev/sdc1 missing /dev/sde1
"missing" reemplaza a la unidad que se va a agregar más tarde (sdd1); mdadm informará que las unidades ya pertenecen a un array, y preguntará si realmente se desea continuar con la creación del array, a lo que debe responderse que sí. Este paso reescribe los metadatos y crea un nuevo UUID, dejando todo como estaba e iniciando el array con tres dispositivos. **Antes de recrear la unidad MD debe revisarse con CUIDADO que el estilo de metadata y el chunk size original son los que se va a usar para crearla. De otra manera se DESTRUYE el sistema de archivos. Por ejemplo, si la unidad preexistente tenía estilo de metadata 0.90 y se usa ahora 1.2, o si el chunk size era de 64k y ahora se usa 512k, ocurre la destrucción del sistema de archivos**.
-Detener nuevamente el array:
mdadm --stop /dev/md0
-Volver a activar el array, con la opción --update=resync para ver si levanta:
mdadm --assemble --update=resync -f /dev/md0 /dev/sdb1 /dev/sdc1 /dev/sde1
Si comienza a sincronizar, dejarlo que termine. Se puede ver si está sincronizando con:
cat /proc/mdstat
En mi caso no sincronizó, pero imagino que era lógico: el dispositivo estaba sincronizado, y si no hubiera sido así, se hubiera perdido todo con toda seguridad. Pero eso es un punto bueno de mdadm: si algo no está bien, detiene el array de manera que no se pierdan datos.
-A continuación, se debe agregar el otro disco que falló:
mdadm -a /dev/md0 /dev/sdd1
Hecho esto, el array sincronizará el nuevo dispositivo, proceso que llevará alrededor de 6 horas con estos cuatro discos de 500GB. Recomiendo encarecidamente **no utilizar la unidad, ni el equipo** (debería estar en runlevel 1), para evitar cualquier tipo de falla no esperada, y para acelerar el proceso de sincronización.
-Todo este procedimiento crea un nuevo array, que por lo tanto tendrá un nuevo UUID. El nuevo UUID puede ser visualizado con:
mdadm -D /dev/md0
-Este nuevo UUID debe ser insertado, en vez del UUID anterior en /etc/mdadm/mdadm.conf, para que el array se active en forma automática al inicio del sistema (en Debian, es un proceso realizado por el script /etc/init.d/mdadm-raid)
-El paso final es revisar que el sistema de archivos de la unidad md esté correcto (en mi caso el sistema de archivos es ReiserFS):
reiserfsck /dev/md0
-Si el chequeo del sistema de archivos es exitoso, seguramente ya no habrá inconvenientes, se podrá montar la unidad y comenzar a utilizar el sistema normalmente. Quizá sea conveniente reiniciarlo una vez más, para asegurarse que todo esté bien en el arranque, y para evitar alguna desagradable sorpresa en el futuro.
==== Notas finales ====
Los discos que fallaron deben revisarse con smartctl en búsqueda de cualquier inconveniente que indique que haya que reemplazar el o los discos. En el caso que se decida reemplazar ambos discos, **debe hacerse de a un disco por vez y esperando en cada caso que la sincronización finalice**, ya que no puede haber más de un disco fuera de servicio en una unidad RAID5.
Si bien en mi caso el rescate fue exitoso, no debe suponerse que sea algo habitual. La falla de más de un dispositivo de una misma unidad RAID5 provoca la pérdida completa de los datos, sin posibilidad de salvarlos de forma alguna. En el caso de que ocurra algo así, el array debe manejarse con el cuidado más completo, estando descansado, tranquilo y sin apuros. Es preferible perder unas horas más, que años de trabajo. Al comenzar el rescate, recomiendo elaborar un plan detallado, tratando de no olvidarse algún paso; luego de hecho esto, iniciar los trabajos. Este documento bien puede servir de base para ello.
==== Bibliografía ====
*Harry Mangalam's original post on how to resurrect an array with mdadm (one million thanks to you, Harry!!): http://maillists.uci.edu/mailman/public/uci-linux/2007-December/002225.html
*Neil Brown's blog (author of mdadm): http://neil.brown.name/blog/mdadm
*Debian mdadm FAQ: http://svn.debian.org/wsvn/pkg-mdadm/mdadm/trunk/debian/FAQ?op=file&rev=0&sc=0