RAID por software con GNU/Linux

per Victor Carceler darrera modificació 2020-04-02T12:53:29+02:00

Los sistemas RAID se utilizan en muchas máquinas en producción para conseguir: tolerancia a fallos hardware, mayor rendimiento o bien conseguir un dispositivo de almacenamiento grande a partir de discos físicos menores.

Los sistemas RAID se pueden implementar mediante controladoras hardware específicas o bien mediante soporte que incluye el sistema operativo.

Introducción a RAID

Puede encontrar una introducción a la tecnología RAID e información sobre su uso en GNU/Linux en los siguientes enlaces:

  1. Entrada sobre RAID en la Wikipedia
  2. Software-RAID HOWTO

Cuando se monta un sistema RAID por software en GNU/Linux se puede utilizar cualquier dispositivo de almacenamiento (dispositivos de bloques). Así se pueden utilizar discos IDE o SCSI, particiones o bien ficheros asociados a algún dispositivo loopback. El propio dispositivo RAID que se obtiene es un dispositivo de bloques que se puede utilizar en otro RAID.

En este ejemplo se crearán diferentes ficheros que asociados a los correspondientes dispositivos loopback se utilizarán para construir un RAID. Esta aproximación es muy cómoda para probar el soporte software para RAID de GNU/Linux, pero ni que decir tiene que no debería utilizarse nunca para una situación real.

Instalando el soporte para RAID:

Deberemos instalar los paquetes para soporte RAID que incluya nuestra distribución, en el caso de Mandrake instalamos:

  • raidtools
  • mdadm

Creando los discos duros virtuales

Para no tener que utilizar discos duros físicos para demostrar el soporte RAID de GNU/Linux, vamos a construir los diferentes ficheros que nos harán (mediante dispositivos loopback) las funciones de discos duros virtuales.

[root@raca29 root]# pwd
/root
[root@raca29 root]# dd if=/dev/zero of=fichero1 bs=1M count=50
50+0 registros leídos
50+0 registros escritos
[root@raca29 root]# dd if=/dev/zero of=fichero2 bs=1M count=50
50+0 registros leídos
50+0 registros escritos
[root@raca29 root]# dd if=/dev/zero of=fichero3 bs=1M count=50
50+0 registros leídos
50+0 registros escritos
[root@raca29 root]# dd if=/dev/zero of=fichero4 bs=1M count=50
50+0 registros leídos
50+0 registros escritos
[root@raca29 root]# ll -h
total 200M
drwx------ 2 root root 139 sep 17 17:50 drakx/
-rw-r--r-- 1 root root 50M ene 30 23:01 fichero1
-rw-r--r-- 1 root root 50M ene 30 23:01 fichero2
-rw-r--r-- 1 root root 50M ene 30 23:02 fichero3
-rw-r--r-- 1 root root 50M ene 30 23:02 fichero4
drwx------ 3 root root 23 ene 29 16:52 tmp/
[root@raca29 root]#

Los asociamos con dispositivos loopback:

[root@raca29 root]# losetup /dev/loop0 fichero1
[root@raca29 root]# losetup /dev/loop1 fichero2
[root@raca29 root]# losetup /dev/loop2 fichero3
[root@raca29 root]# losetup /dev/loop3 fichero4

De ahora en adelante supondremos que nuestros discos duros son /dev/loop0 .. /dev/loop3.

Configurando el RAID

El fichero de configuración para los dispositivos RAID es /etc/raidtab y el kernel nos muestra en /proc/mdstat el estado de los dispositivos RAID. También aparece información relativa al funcionamiento del RAID en los ficheros de registro del sistema.

Configuramos un RAID en espejo con los dos primeros dispositivos de almacenamiento, dejando los otros 2 como discos de repuesto (que entran en servicio automáticamente al producirse un fallo en los primeros).

[root@localhost root]# cat /etc/raidtab
raiddev /dev/md0
raid-level 1
nr-raid-disks 2
nr-spare-disks 2
chunk-size 32
persistent-superblock 1
device /dev/loop0
raid-disk 0
device /dev/loop1
raid-disk 1
device /dev/loop2
spare-disk 0
device /dev/loop3
spare-disk 1
[root@localhost root]#

Comprobamos que de momento no hay ningún dispositivo RAID en uso:

[root@localhost root]# cat /proc/mdstat
Personalities :
unused devices:
[root@localhost root]#

Y construimos el RAID

[root@localhost root]# mkraid /dev/md0
handling MD device /dev/md0
analyzing super-block
disk 0: /dev/loop0, 51200kB, raid superblock at 51136kB
disk 1: /dev/loop1, 51200kB, raid superblock at 51136kB
disk 2: /dev/loop2, 51200kB, raid superblock at 51136kB
disk 3: /dev/loop3, 51200kB, raid superblock at 51136kB
[root@localhost root]#

El dispositivo RAID /dev/md0 ya está disponible para su uso, se puede ver su estado al comprobar /proc/mdstat

[root@localhost root]# cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 loop3[2] loop2[3] loop1[1] loop0[0]
51136 blocks [2/2] [UU]
[===>.................] resync = 18.0% (10112/51136) finish=0.6min speed=1123K/sec
unused devices:
[root@localhost root]#

Es importante darse cuenta de como el sistema empieza automáticamente a construir el espejo con los dos primeros discos del RAID, manteniendo los otros dos como discos de repuesto. El dispositivo /dev/md0 puede utilizarse antes de que se haya construido el espejo, por ejemplo, puede formatearse y montarse mientras continúan las tareas de sincronización de los discos. Para sincronizar los discos se utilizan los tiempos muertos del subsistema en entrada/salida, de manera que el rendimiento general de la máquina no debería disminuir en exceso. De todos modos, si ocurriese un fallo en uno de los dos discos del espejo antes de que los dos estuviesen completamente sincronizados perderiamos información, así que en un entorno de producción es muy razonable esperar a que el sincronizado de los discos termine.

De modo que veamos algo como esto:

[root@localhost root]# cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 loop3[2] loop2[3] loop1[1] loop0[0]
51136 blocks [2/2] [UU]

unused devices:
[root@localhost root]#

El comando mdadm nos puede mostrar información detallada sobre el estado del RAID:

[root@localhost root]# mdadm --detail /dev/md0
/dev/md0:
Version : 00.90.01
Creation Time : Mon Jan 31 15:08:43 2005
Raid Level : raid1
Array Size : 51136 (49.94 MiB 52.36 MB)
Device Size : 51136 (49.94 MiB 52.36 MB)
Raid Devices : 2
Total Devices : 4
Preferred Minor : 0
Persistence : Superblock is persistent

Update Time : Mon Jan 31 15:09:33 2005
State : clean, no-errors
Active Devices : 2
Working Devices : 4
Failed Devices : 0
Spare Devices : 2


Number Major Minor RaidDevice State
0 7 0 0 active sync /dev/loop/0
1 7 1 1 active sync /dev/loop/1
2 7 3 -1 spare /dev/loop/3
3 7 2 -1 spare /dev/loop/2
UUID : de0d3106:6bb5adff:95e13495:02c4611d
Events : 0.2
[root@localhost root]#

En este caso vemos que los dispositivos /dev/loop0 y /dev/loop1 están en uso y sincronizados, mientras que los otros dos están funcionando como discos de repuesto.

Utilizando el RAID

Podemos utilizar el dispositivo /dev/md0 como cualquier otro dispositivo de almacenamiento, por ejemplo podemos crear un sistema de archivos en su interior y montarlo.

Creamos un sistema de archivos EXT3 (pero podriamos escoger cualquier otro.)

[root@localhost root]# mkfs.ext3 -L ESPEJO /dev/md0
mke2fs 1.34 (25-Jul-2003)
Filesystem label=ESPEJO
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
12824 inodes, 51136 blocks
2556 blocks (5.00%) reserved for the super user
First data block=1
7 block groups
8192 blocks per group, 8192 fragments per group
1832 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961

Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 20 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
[root@localhost root]#

Y ahora lo montamos:

[root@localhost root]# mount /dev/md0 /mnt/raid/
[root@localhost root]# df -h
S.ficheros Tamaño Usado Disp Uso% Montado en
/dev/ide/host0/bus0/target0/lun0/part1
8,9G 5,1G 3,9G 57% /
/dev/md/0 49M 4,1M 42M 9% /mnt/raid
[root@localhost root]#

A partir de aquí, podemos trabajar como con cualquier otro espacio de almacenamiento, con la tranquilidad de que cuando uno de los dos dispositivos (loop0 o loop1) nosotros no perderemos datos.

Simulando averias:

La razón más común para montar un RAID es conseguir cierto nivel de tolerancia a fallos. Así que vamos a ver que ocurre cuando uno de los discos del RAID sufre una avería.

En nuestro caso tenemos a /dev/loop0 y a /dev/loop1 formando un espejo. Si simulamos una avería en uno de ellos, automáticamente alguno de los discos de repuesto /dev/loop2 o /dev/loop3 se utilizará para replicar los datos del disco que sigue funcionando. Pasado un tiempo, cuando la réplica se haya acabado estaremos en una situación semejante a la inicial, en la que dos dispositivos guardan los datos del RAID, queda un dispositivo de repuesto y hay un dispositivo que está averiado.

La réplica en el disco de repuesto se realiza mientras el sistema trabaja con normalidad, no es necesario desmontar el sistema de archivos o detener la máquina. Evidentemente, mientras no se haya completado la réplica en uno de los discos de repuesto no seremos capaces de soportar la avería del único disco que contiene datos.

Podemos simular un fallo en /dev/loop0 con el siguiente comando:

[root@localhost root]# raidsetfaulty /dev/md0 /dev/loop0

Si comprobamos el fichero /proc/mdstat veremos que un dispositivo se ha marcado como defectuoso (F), y se ha iniciado un nuevo proceso de réplica:

[root@localhost root]# cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 loop3[2] loop2[3] loop1[1] loop0[4](F)
51136 blocks [2/1] [_U]
[=>...................] recovery = 8.0% (4224/51136) finish=0.5min speed=1408K/sec
unused devices:
[root@localhost root]#

El comando mdadm nos mostrará información más detallada:

[root@localhost root]# mdadm --detail /dev/md0
/dev/md0:
Version : 00.90.01
Creation Time : Mon Jan 31 15:08:43 2005
Raid Level : raid1
Array Size : 51136 (49.94 MiB 52.36 MB)
Device Size : 51136 (49.94 MiB 52.36 MB)
Raid Devices : 2
Total Devices : 4
Preferred Minor : 0
Persistence : Superblock is persistent

Update Time : Mon Jan 31 15:34:56 2005
State : clean, no-errors
Active Devices : 1
Working Devices : 3
Failed Devices : 1
Spare Devices : 2


Rebuild Status : 24% complete

Number Major Minor RaidDevice State
0 0 0 -1 removed
1 7 1 1 active sync /dev/loop/1
2 7 3 0 spare /dev/loop/3
3 7 2 -1 spare /dev/loop/2
4 7 0 -1 faulty /dev/loop/0
UUID : de0d3106:6bb5adff:95e13495:02c4611d
Events : 0.7
[root@localhost root]#

En el fichero de registro /var/log/messages podemos encontrar información sobre lo que ha ocurrido:

Jan 31 15:34:56 localhost kernel: raid1: Disk failure on loop0, disabling device.
Jan 31 15:34:56 localhost kernel: ^IOperation continuing on 1 devices
Jan 31 15:34:56 localhost kernel: RAID1 conf printout:
Jan 31 15:34:56 localhost kernel: --- wd:1 rd:2
Jan 31 15:34:56 localhost kernel: disk 0, wo:1, o:0, dev:loop0
Jan 31 15:34:56 localhost kernel: disk 1, wo:0, o:1, dev:loop1
Jan 31 15:34:56 localhost kernel: RAID1 conf printout:
Jan 31 15:34:56 localhost kernel: --- wd:1 rd:2
Jan 31 15:34:56 localhost kernel: disk 1, wo:0, o:1, dev:loop1
Jan 31 15:34:56 localhost kernel: RAID1 conf printout:
Jan 31 15:34:56 localhost kernel: --- wd:1 rd:2
Jan 31 15:34:56 localhost kernel: disk 0, wo:1, o:1, dev:loop3
Jan 31 15:34:56 localhost kernel: disk 1, wo:0, o:1, dev:loop1
Jan 31 15:34:57 localhost kernel: RAID1 conf printout:
Jan 31 15:34:57 localhost kernel: --- wd:1 rd:2
Jan 31 15:34:57 localhost kernel: disk 0, wo:1, o:1, dev:loop3
Jan 31 15:34:57 localhost kernel: disk 1, wo:0, o:1, dev:loop1
Jan 31 15:34:57 localhost kernel: md: syncing RAID array md0
Jan 31 15:34:57 localhost kernel: md: minimum _guaranteed_ reconstruction speed: 1000 KB/sec/disc.
Jan 31 15:34:57 localhost kernel: md: using maximum available idle IO bandwith
(but not more than 200000 KB/sec) for reconstruction.
Jan 31 15:34:57 localhost kernel: md: using 128k window, over a total of 51136 blocks.
Jan 31 15:35:47 localhost kernel: md: md0: sync done.
Jan 31 15:35:47 localhost kernel: RAID1 conf printout:
Jan 31 15:35:47 localhost kernel: --- wd:2 rd:2
Jan 31 15:35:47 localhost kernel: disk 0, wo:0, o:1, dev:loop3
Jan 31 15:35:47 localhost kernel: disk 1, wo:0, o:1, dev:loop1

Arreglando las cosas:

Ahora mismo tenemos dos discos formando un espejo, un disco de repuesto y un disco estropeado. El trabajo, evidentemente consiste en substituir el disco estropeado por uno nuevo (que pasará a ser un disco de repuesto).

Para ello desactivaremos el disco estropeado de la siguiente manera:

[root@localhost root]# raidhotremove /dev/md0 /dev/loop0
[root@localhost root]# cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 loop3[0] loop2[2] loop1[1]
51136 blocks [2/2] [UU]

unused devices:
[root@localhost root]#

En el mundo real cogeriamos un disco nuevo y lo instalariamos en nuestra máquina. En esta práctica con discos virtuales, borraremos por completo el contenido del disco y lo volveremos a añadir al RAID

[root@localhost root]# dd if=/dev/zero of=/dev/loop
loop loop0 loop1 loop2 loop3 loop4 loop5 loop6 loop7
[root@localhost root]# dd if=/dev/zero of=/dev/loop0
dd: escribiendo en «/dev/loop0»: No space left on device
102401+0 registros leídos
102400+0 registros escritos
[root@localhost root]# raidhotadd /dev/md0 /dev/loop0
[root@localhost root]# cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 loop0[2] loop3[0] loop2[3] loop1[1]
51136 blocks [2/2] [UU]

unused devices:
[root@localhost root]# mdadm --details /dev/md0
mdadm: unrecognized option `--details'
Usage: mdadm --help
for help
[root@localhost root]# mdadm --detail /dev/md0
/dev/md0:
Version : 00.90.01
Creation Time : Mon Jan 31 15:08:43 2005
Raid Level : raid1
Array Size : 51136 (49.94 MiB 52.36 MB)
Device Size : 51136 (49.94 MiB 52.36 MB)
Raid Devices : 2
Total Devices : 4
Preferred Minor : 0
Persistence : Superblock is persistent

Update Time : Mon Jan 31 15:45:12 2005
State : clean, no-errors
Active Devices : 2
Working Devices : 4
Failed Devices : 0
Spare Devices : 2


Number Major Minor RaidDevice State
0 7 3 0 active sync /dev/loop/3
1 7 1 1 active sync /dev/loop/1
2 7 0 -1 spare /dev/loop/0
3 7 2 -1 spare /dev/loop/2
UUID : de0d3106:6bb5adff:95e13495:02c4611d
Events : 0.10
[root@localhost root]#

Finalmente nos encontramos de nuevo en una posición cómoda y segura al utilizar un espejo de dos discos y mantener dos discos de repuesto.