RAID logiciel : mdadm

De wikiGite

Un article de Le wiki de 2 noisettes - noisette.ch.

Mdadm est un logiciel de gestion de RAID logiciel. Il est très complet au point que je le conseille même pour un environnement de production.

Cet article explique comment créer un RAID, assembler plusieurs disques ayant déjà fait parti d'un array, ou comment réagir en cas de panne. Pour les commandes données en exemple, nous ferons du RAID1 avec 2 disques partitionnés en 4, respectivement /boot, swap, / et /home.

Création

Configurer les disques

Une fois le logiciel mdadm installé sur l'ordinateur, il faut configurer les disques

fdisk /dev/sda
fdisk /dev/sdb

pour que les partitions qui vont accueillir du RAID soient de type Linux raid autodetect (fd). Puis on va les assembler avec mdadm pour finalement pouvoir les formater et installer le le system dessus.

La configuration des disques sera la suivante :

/dev/*1 --> /boot,  100MB
/dev/*2 --> swap, 1-2GB

/ dev/*3 --> /, 20GB

/dev/*4 --> /home, le reste (bien que mettre /var serait plus judicieux sur une gentoo.

Noyau

Compilez le noyau avec les options suivantes (et sélectionner un autre mode de RAID si souhaité)

Device Drivers  ---> 
   Multi-device support (RAID and LVM)  --->
       [*] Multiple devices driver support (RAID and LVM)
       [*]   RAID support 
       [*]     RAID-1 (mirroring) mode 

Si vous démarrez d'un live CD, il faut charger le module (raid1 par exemple) :

modprobe raid1

Créer les nodes /dev/mdX

mknod /dev/md1 b 9 1
mknod /dev/md3 b 9 3
mknod /dev/md4 b 9 4

Création des arrays

Pour les assembler avec mdadm, la commande ressemble à la suivante

mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sda1 /dev/sdb1
mdadm --create /dev/md3 --level=1 --raid-devices=2 /dev/sda3 /dev/sdb3
mdadm --create /dev/md4 --level=1 --raid-devices=2 /dev/sda4 /dev/sdb4

Une fois l'array créé, reste les formatage et le montage à l'endroit voulu.

mke2fs /dev/md1
mkreiserfs /dev/md3
mkreiserfs /dev/md4
mkswap /dev/sda2 && mkswap /dev/sdb2
swapon /dev/sda2 && swapon /dev/sdb2 
mount /dev/md3 /mnt
mkdir -p /mnt/boot && mount /dev/md1 /mnt/boot
mkdir -p /mnt/home && mount /dev/md4 /mnt/home

On peut maintenant consulter les informations sur les disques, et insérer ces informations dans /etc/mdadm.conf :

mdadm --detail --scan >> /etc/mdadm.conf

Créer un raid10

mdadm -v --create /dev/md2 --level=raid10 --raid-devices=12 /dev/sd[a-l]2


Créer un raid 50

Commencer par créer 4 baies de trois disques en RAID5 :

mdadm --create /dev/md21 -v --raid-devices=3 --level=5 /dev/sd[a-c]2
mdadm --create /dev/md22 -v --raid-devices=3 --level=5 /dev/sd[d-f]2
mdadm --create /dev/md23 -v --raid-devices=3 --level=5 /dev/sd[g-i]2
mdadm --create /dev/md24 -v --raid-devices=3 --level=5 /dev/sd[j-l]2

Pour créer un raid 0 avec ces 4 RAID5 :

mdadm --create /dev/md2 -v --raid-devices=4 --level=0 /dev/md21 /dev/md22 /dev/md23 /dev/md24

Si par la suite on veut étendre le raid : Recréer une baie de raid5 :

mdadm --create /dev/md25 -v --raid-devices=3 --level=5 /dev/sd[l-n]2

L'ajouter daans le raid0 existant :

mdadm --manage /dev/md2 --add /dev/md25

Définir le nombre de Baies pour le raid0 :

mdadm --grow /dev/md2 --raid-devices=5

(Ré)Assemblage

Une fois le RAID créé et des données dessus, on ne veut plus nécessairement le reformater et le recréer quand on l'a démonté. La solution sera donc de le réassemblé avec mdadm.

La première étape conciste à examiner une partition pour contrôler si elle fait bien partie d'un RAID (pour ceux qui on une mauvaise mémoire à très court terme) :

mdadm --examine /dev/sda1

La sortie nous dit si oui ou non la partition fait partie d'un RAID, et si oui quels autres disques en font aussi partie. Une fois en possession de ces informations, il nous reste à assembler l'ARRAY :

mdadm --assemble /dev/md1 /dev/sda1 /dev/sdb1
mdadm --assemble /dev/md3 /dev/sda3 /dev/sdb3
mdadm --assemble /dev/md4 /dev/sda4 /dev/sdb4

Reste le montage à l'endroit voulu.

Reconstruction

J'ai fait des tests de tolérence sur le RAID logiciel. J'ai commencé par enlever des disques à chaud (et j'ai pu bien constater qu'IDE était hot-déswap mais pas hot-swap), puis en utilisant l'option --fail pour simuler une panne. Les résultat étaient assez intéressants, mais le problème était de reconstruire le raid après la panne simulée.

Une fois la panne détectée (une véritable panne ou une simulée), on identifie le disque défectueux (avec dmesg ou /proc/mdstat) et on le retire de l'array :

mdadm --manage /dev/md1 --remove /dev/sdb1

Si on n'a pas de SATA pour enlever et remettre un disque à chaud, on arrête la machine et on la redémarre avec le nouveau disque. Puis on ajoute le nouveau disque à l'array :

mdadm --manage /dev/md1 --add /dev/sdb1

Suppression

Supprimer le raid existant

Passer le status des disques à fail :

mdadm --manage /dev/md2 --fail /dev/sd[a-l]2

Puis les retirer du raid :

mdadm --manage /dev/md2 --remove /dev/sd[a-l]2

Arrêter le raid :

mdadm --manage --stop /dev/md2

Commenter la ligne correspondant à md2 dans /etc/mdadm.conf

Initialiser les périphériques pour effacer toute trace et redémarrer la machine:

mdadm --zero-superblock /dev/sd[a-l]2
reboot


Monitoring

Mdadm offre une option de monitoring des arrays : --monitor. Pouvant être directement lancé sur centos avec le daemon mdmonitor : service mdmonitor start chkconfig mdmonitor on

Notifications de base

Ajouter dans /etc/mdadm.conf

MAILADDR youremail@domain.com
MAILFROM my-server-name

tester : mdadm --monitor --scan --test --oneshot

Notification à l'aide d'un script

Mdmonitor peut appeler un script externe lors d'un événement (bon ou mauvais). Pour cela rajouter dans /etc/mdadm.conf :

PROGRAM /opt/systools/handle-mdadm-events.sh

Les arguments passés au script seront les suivants :

   * $1 : une chaine de caractère qui décrit l'évènement qui s'est produit
         o 'SparesMissing' : une panne est détectée mais aucun disque de remplacement n'est présent
         o 'Fail' : un disque est détecté comme déféctueux
         o 'RebuildStarted' : un nouveau disque est ajouté à l'array et la reconstruction commence
         o 'Rebuild20' : la reconstruction est à 20%
         o 'Rebuild40' : la reconstruction est à 40%
         o 'Rebuild60' : la reconstruction est à 60%
         o 'Rebuild80' : la reconstruction est à 80%
         o 'RebuildFinished' : la reconstruction est terminée
         o 'SpareActive' : un disque de réserve est ajouté à un array 
   * $2 : le nom de la device md : /dev/mdX 

$1 et $2 étant le premier et le deuxième argument passé en paramètre.

Voici le script :

#!/bin/bash
CONFIG="/etc/mdadm.conf"
 
MAILADDR="pbrun@systea.net" # support@systea.net" #espace entre les mails
 
parse_event()
{
  echo "Hôte            : $HOSTNAME"
  if [ -z "$1" ]; then
    echo "Événement        : Test message"
  else
    echo "MD Device       : $2"
    echo "Événement           : $1"
    if [ -n "$3" ]; then
      echo "Élément en cause: $3"
    fi
  fi
 
  echo ""
  echo "/proc/mdstat dump:"
  FAIL=0
  DEGRADED=0
  while read LINE; do
    echo -n "$LINE"
    if [ -n "$(echo "$LINE" |grep 'active raid')" ]; then
      if [ -n "$(echo "$LINE" |grep '\(F\)')" ]; then
        FAIL=$(($FAIL + 1))
        echo -n " (ATTENTION: DISQUE(S) DÉFÉCTUEUX!)"
      fi
 
      if [ -n "$(echo "$LINE" |grep '\(S\)')" ]; then
        echo -n " (Hotspare(s) disponibles)"
      else
        echo -n " (NOTE: Pas de hotspare?!)"
     fi
    fi
 
    if [ -n "$(echo "$LINE" |grep 'blocks')" ]; then
      if [ -n "$(echo "$LINE" |grep '_')" ]; then
        DEGRADED=$(($DEGRADED + 1))
        echo -n " (DEGRADED!!!)"
      fi
    fi
 
    echo ""
  done < /proc/mdstat
 
  if [ $FAIL -gt 0 ]; then
    echo ""
    echo "** ATTENTION: Un ou plusieurs RAID ont un ou plusieurs disques déféctueux! **"
  fi
 
  if [ $DEGRADED -gt 0 ]; then
    echo ""
    echo "** ATTENTION: Un ou plusieurs RAID fonctionnent en mode dégradé! **"
  fi
}
 
# main line:
 
# Get MAILADDR from mdadm.conf config file, if not set already
if [ -z "$MAILADDR" ] && [ -f "$CONFIG" ]; then
  MAILADDR=`grep MAILADDR "$CONFIG" |cut -d' ' -f2`
  if [ -z "$MAILADDR" ]; then
    MAILADDR="root"
  fi
fi
 
# Call the parser and send it to the configured address
parse_event $* |mail -s"Événement RAID(MD) sur  $HOSTNAME" "$MAILADDR"
 
exit 0

Afin de ne pas recevoir deux mails pour chaque alerte il est conseillé de commenter les deux lignes :

MAILADDR youremail@domain.com
MAILFROM my-server-name - mdadm

Un script plus simple...

#!/bin/bash
MAIL=admin@domain.com
if [ $(date +\%w) -ne 0 ]
then
   STATE=$(/sbin/mdadm --query --detail /dev/md1 | grep State | grep -v Major | awk '{print $3}')
   if [ "$STATE" != "clean" -a "$STATE" != "active" ]
   then
      (/sbin/mdadm --query --detail /dev/md1
      )| mail -s "PROBLEME RAID sur $(hostname) $(date +%d/%m)" $MAIL
   fi
fi

Notes

  • Vérifier d'avoir une version > 2.5.0, car elle souffre d'un gros memory leak quand mdadm est lancé en monitoring.