Software-RAID nachträglich aktivieren

Es gibt Situationen, in denen man ein laufendes System nachträglich noch mit einem RAID ausrüsten will, um einen besseren Schutz vor dem Ausfall einer Festplatte zu haben. Auf dieser Seite geht es jetzt nur um Software-RAIDs, da dies (insbesondere bei Verwendung von RAID 1) für die meisten Anwendungsfälle ausreicht.

Exkurs: RAID-Controller

Früher (in den 90ern) war ein RAID-Sytem eigentlich immer mit zusätzlicher Hardware in Form eines RAID-Controllers verbunden. In dieser Erweiterungskarte (häufig SCSI) war die RAID-Funktionalität implementiert, das Betriebssystem "sah" dann nur noch eine große Festplatte. Meist besaß ein solcher RAID-Controller auch ein eigenes BIOS. Ein Vorteil dieser RAID-Controller war, dass alle Rechenoperationen durch die zusätzliche Hardware durchgeführt wurden, so dass die CPU entlastet wurde.

Heutzutage bringen immer mehr Mainboards "RAID-Fähigkeiten" mit. Tatsächlich wird aber eigentlich immer ein zusätzlicher Treiber benötigt, in dem dann die RAID-Funktionalität steckt. Daher entlasten solche Mainboards die CPU gar nicht. Weiterhin sind immer spezielle Treiber notwendig, die unter Linux entweder gar nicht verfügbar oder schlecht getestet sind, weil nicht so viele Benutzer Mainboards eines speziellen Typs verwenden. Zusätzlich kann sich noch das Problem ergeben, dass der Treiber ein eigenes Datenformat für die Festplatte mitbringt. In diesem Fall wird der Ausfall des Mainboards zu einem größeren Schlamassel, da man an die Daten nur mit einem exakt baugleichen "RAID-Chipsatz" herankommt. Ein Software-RAID unter Linux bietet da hingegen die Gewissheit, dass die Datenformate offengelegt sind und viele Rettungsdisks auch Software-RAIDs unterstützen.

Ähnliches gilt übrigens auch für "RAID-Controller", die für 50-100 Euro separat verscherbelt werden. Wirkliche Entlastung der CPU bringen diese meist nicht. Wie so oft erkennt man echte RAID-Controller daran, dass sie etwas teurer sind (ab ca. 200 Euro/Stand August 2006). Die c't hat in der Ausgabe 10/2006 auf den Seiten 186-196 einen größeren Test dazu ("Geballte Plattenpower: 12 SATA-II-RAID-Adapterkarten mit PCI, PCI-X und PCIe", Boi Feddern).

Wirklich lohnen tut sich ein eigenständiger RAID-Controller aus meiner Sicht nur für Anwender, die ein RAID 5 bei relativ hoher Serverlast aufsetzen wollen.

Allgemeine Vorbemerkungen

Es gibt im Netz schon diverse Anleitungen zu diesem Thema. Ich habe aber noch eine eigene geschrieben, weil mir an den meisten immer eine oder mehrere Dinge nicht gefallen haben. Diese Anleitung wurde mit CentOS 4 getestet, sollte aber prinzipiell mit allen modernen Linux-Distributionen funktionieren. Weiterhin ist diese Anleitung auch für Rechner nutzbar, bei denen kein physikalischer Zugriff besteht (z.B. sog. "Rootserver").

Ich möchte aber die Vorlagen für diese Anleitung nicht unter den Tisch kehren:

Eine vielleicht interessante Erweiterung wäre noch die Verwendung von LVM. Allerdings hatte dies für mich keine Priorität, da die Partitionsgröße sich sehr wahrscheinlich nie wieder ändern wird (Rootserver) und ich derzeit keinen akuten Bedarf für LVM-Snapshots habe.

Vorbereitung

Backup

Das Allerwichtigste bei diesem Prozess ist ein vollständiges und funktionsfähiges Backup. Einerseits können in dieser Anleitung durchaus Fehler enthalten sein, zum anderen kann einfach irgendetwas passieren (z.B. ein Vertipper bei mkswap) und alle Daten sind weg! Außerdem sollte man sich auch sicher sein, dass das Backup wirklich funktionsfähig ist. Es gibt hunderte Geschichten im Netz, wo dann die Beteiligten nach Eintritt des Ernstfalls feststellen mussten, dass jahrelang nur kaputte Bits gesichert wurden.

Hardware

Ich gehe im folgenden davon aus, dass im System zwei Festplatten vorhanden sind (hda, hdc), wobei eine davon komplett frei ist (hdc). Außerdem können insbesondere Fehler bei der grub-Konfiguration das System in einem nicht mehr startfähigen Zustand hinterlassen. Für solche Gelegenheiten ist ein Rettungsystem, wie es bei den meisten Hostern zu finden ist, sehr nützlich!

Es ist nicht notwendig, dass beide Platten gleich groß sind, da mdadm sich nur mit Partitionen und nicht mit Festplatten beschäftigt. Folglich müssen nur die gespiegelten Partitionen exakt gleich groß sein.

Vorhandene Partitionierung

Ich gehe von folgender Partitionierung aus: Sowohl '/' als auch '/var' und SWAP sind jeweils auf einer gesonderten Partition abgelegt.

Partitionierung der neuen Platte

RAID erstellen

Zunächst werden alle für Partitionen RAID-Devices mit einer fehlenden Platte auf der neuen Festplatte hdc angelegt. Für jede Partition (inkl. SWAP) ruft ihr mdadm wie folgt auf:

/sbin/mdadm --create /dev/md0 --level 1 --raid-devices=2 missing /dev/hdc1

Natürlich dürfen nicht immer md0 und hdc1 verwendet werden, sondern bei zweiten Mal md1 und hdc2 etc.

Dabei muss natürlich mdadm installiert sein. Bei CentOS/Fedora heißt das dazugehörige Paket sinnigerweise ebenfalls "mdadm".

Nachdem die RAID-Devices angelegt wurden, erzeugt man darauf das gewünschte Dateisystem, z.B. mit

/sbin/mkfs.ext3 /dev/md0 # fuer die root-Partition
/sbin/mkfs.ext3 /dev/md1 # fuer /var
/sbin/mkswap /dev/md2
usw.

Gegebenenfalls mit tune2fs die Dateisystemparameter anpassen, z.B.:

tune2fs -c 0 -i 0 /dev/md0

Exkurs: SWAP im RAID

Prinzipiell bringt es eigentlich keinen Vorteil, auch die SWAP-Partition zu spiegeln, da swap-Daten eigentlich nicht mehrfach parallel von der Platte gelesen werden (in diesem Fall kann ein RAID 1 eine Geschwindigkeitssteigerung bringen). Das entscheidende Argument für mich war die Datensicherheit: Wenn eine Platte mit der SWAP-Partition während des Betriebs ausfällt und zu dieser Zeit RAM ausgelagert war, sind diese Daten verloren. Die Folge ist ein undefinierter Systemzustand, weil im Prinzip Teile des RAMs mit einem Mal verloren sind. Daher habe ich mich entschieden, auch die SWAP-Partition zu spiegeln.

System migrieren

Systemdienste abschalten

Zwischen dem Kopieren der Daten und dem notwendigen Neustart sollten möglichst keine Daten geschrieben werden, da diese sonst verloren sind. Daher würde dazu raten, Dienste wie Mailserver, Webserver und Datenbank herunterzufahren, um versehentlichen Schaden abzuwenden.

Daten kopieren

Anschließend werden alle Daten auf die neuen RAID-Partitionen kopiert. Dazu müssen diese erst mal gemountet werden:

mount /dev/md0 /mnt/
mount /dev/md1 /mnt/var/
...

Wichtig ist, dass ihr euch beim Mounten von der Wurzel (Rootpartition) zu eventuell auf Unterverzeichnissen gemountete Partitionen wie /var vorarbeitet: Also erst / mounten, dann /var.

Jetzt müssen die Daten noch kopiert werden:

cp --no-dereference --preserve --recursive --one-file-system / /mnt
cp --no-dereference --preserve --recursive --one-file-system /var /mnt
...

fstab anpassen

Automatische Updates durch fstab-sync verhinern:

rm /etc/hal/device.d/50-fstab-sync.hal
ln -s /bin/false /etc/hal/device.d/50-fstab-sync.hal

Damit beim nächsten Mal auch gleich vom RAID gestartet wird, muss noch die Datei /etc/fstab angepasst werden. Sie könnte dann in etwa so aussehen:

/dev/md0                /                       ext3    defaults        1 1
/dev/md1                /var                    ext3    defaults        1 1
#/dev/hda2              swap                    swap    defaults        0 0
/dev/md2                swap                    swap    defaults        0 0
...

fstab-sync wieder aktivieren:

rm /etc/hal/device.d/50-fstab-sync.hal
ln -s /usr/sbin/fstab-sync /etc/hal/device.d/50-fstab-sync.hal

initiale RAM disk erzeugen

Hinweis: Mit CentOS 4.4 war dieser Schritt nicht mehr nötig, da mdadm offenbar bereits im initrd vorhanden ist.

Wenn /boot ebenfalls auf einem RAID-device liegt, muss die initial RAM disk (initrd) angepasst werden, so dass darin auch mdadm enthalten ist. Dieser Vorgang muss leider nach jedem Kernel-Update wiederholt werden. Vergisst man das, wird das System nicht mehr starten!

mkinitrd --with=raid1 raid-initrd-`uname -r`.img `uname -r`
mv raid-initrd-`uname -r`.img /mnt/boot

Ich verwende "uname -r", um die aktuelle Kernelversion dynamisch zu ermitteln.

Unter openSuSE muss man

mkinitrd -f md -d /dev/md0
cp /boot/initrd* /mnt/boot

ausführen, da der Bootvorgang sonst bei "Waiting for /dev/md0.." stehen bleibt.

Die Alternative zu einer angepassten initrd ist, /boot auf eine normale Partition zu legen. Dann muss man allerdings die Inhalte von /boot auf beiden Platten manuell spiegeln, damit das System im Notfall von beiden Platten starten kann. Die bequemste Möglichkeit ist natürlich, wenn der Distributor bereits mdadm in der von im mitgelieferten initrd bereitstellt, dann ist dieser Schritt unnötig.

grub anpassen

Die /etc/grub.conf muss angepasst werden, so dass das System beim nächsten Mal vom RAID-device startet. Die genauen Versionsnummern müssen natürlich gemäß der Ausgabe von "uname -r" angepasst werden.

title CentOS (2.6.9-22.0.1.EL RAID 1)
    root (hd1,0)
    kernel /boot/vmlinuz-2.6.9-22.0.1.EL ro root=/dev/md0
    initrd /boot/raid-initrd-2.6.9-22.0.1.EL.img

Wichtig ist hierbei "root (hd1,0)" (Start von der RAID-Partition), die korrekte Kernel-Version (hier "2.6.9-22.0.1.EL"), die Angabe der RAID-Partition ("root=/dev/md0") sowie die Angabe der korrekten initrd (Kernel-Version, Software-RAID-Support).

Vorsicht: Ein Fehler in der grub.conf kann das System in einem nicht mehr startfähigen Zustand hinterlassen, so dass ein manueller Eingriff (oder das Starten in einen Rettungsmodus) notwendig wird.

Neustart

Nachdem alle Arbeiten abgeschlossen sind, ist ein Neustart fällig. Dazu sollten alle RAID-Platten ausgehängt werden und zwar in der umgekehrten Reihenfolge, in der sie gemountet wurden:

...
umount /mnt/var
umount /mnt/
...
reboot

RAID komplettieren

System überprüfen

Wenn das System reibungslos neu gestartet ist (toi, toi, toi...), muss als erstes überprüft werden, ob wirklich alles geklappt hat.

  • Wurde wirklich vom RAID-device gestartet? "df -h" sollte anzeigen, dass "/" auf /dev/md0 liegt.
  • Wurden alle Dienste richtig gestartet? /var/log/messages & Co. sollten sorgfältig überprüft werden.
  • Sind wirklich alle Daten vorhanden? Dies ist die letzte Chance, Daten ev. zu retten! Ggf. md5summen vergleichen!

Partitionstabelle ändern

Die Partitionen auf der alten Platte (hda) müssen alle noch einen neuen Typ verpasst bekommen. Dies geschieht einfach mittels

/sbin/fdisk /dev/hda

Der Typ muss auf 0xfd ("Linux raid autodetect") gesetzt werden. Eine typische fdisk-Session könnte so aussehen:

$ t  (Typ ändern)
$ 1  (# der Partition)
$ fd (Typ: Linux RAID autodetect)
$ t  (...)
$ 2  (...)
$ fd (...)
$ w  (Partitionstabelle schreiben)

Alte Partitionen zum RAID hinzufügen

Jetzt werden die alten Partitionen zum RAID-Array hinzugefügt. Für jede RAID-Partition den folgenden Befehl ausführen (und wieder md0 und hda1 entspr. anpassen!):

/sbin/mdadm --add /dev/md0 /dev/hda1

Dadurch wird automatisch ein resync ausgelöst. Der Fortschritt kann über

cat /proc/mdstat

beobachtet werden. Der resync ist abgeschlossen, wenn hinter jeder RAID-Partition "[UU]" zu sehen ist.

grub anpassen

Nachdem das System jetzt von der Raid-Partition bootet, kann jetzt die /etc/grub.conf wieder zu hd0 geändert werden.

title CentOS (2.6.9-22.0.1.EL RAID 1)
    root (hd0,0)
    kernel /boot/vmlinuz-2.6.9-22.0.1.EL ro root=/dev/md0
    initrd /boot/raid-initrd-2.6.9-22.0.1.EL.img

Außerdem muss grub noch im boot record der zweiten Platte verankert werden. Dies geschieht mittels dem Kommando "/sbin/grub":

$ find /boot/grub/stage1
... (Es sollte "hd(0,0)" und "hd(1,0)" als Ausgabe kommen.)
$ device (hd0) /dev/hda
$ root (hd0,0)
$ setup (hd0)
... (grub-Erfolgsmeldung)
$ device (hd0) /dev/hdc
$ root (hd0,0)
$ setup (hd0)
... (grub-Erfolgsmeldung)
$ quit

Nach jedem Kernel-Update

Hinweis: Mit CentOS 4.4 war dieser Schritt nicht mehr nötig, da mdadm offenbar bereits im initrd vorhanden ist, entsprechend ist keine Handarbeit mehr nötig!

  • initrd aktualisieren
  • grub.conf anpassen (oder die alte initrd mit der zuvor generierten überschreiben)

Zum Schluss

Nachdem das RAID-System jetzt eingerichtet ist, sollte man sich mit den Optionen von mdadm vertraut machen. Insbesondere die Benachrichtigung bei einer ausgefallenen Platte sollte getestet werden - denn was nutzt einem das beste RAID, wenn eine Platte ausfällt, man dies aber erst merkt, wenn einige Monate später auch die zweite Platte über den Jordan geht?

Außerdem sollte man jetzt noch - wenn möglich - Fehlerfälle testen, d.h. Booten nur mit einer der beiden Platten oder das Verhalten des RAIDs, wenn eine Platte plötzlich verschwindet.

Nicht vergessen werden sollte auch der Eintrag der neuen Platte in die /etc/smartd.conf, damit auch der Status der Platte durch den smartd immer überwacht wird.

Raid-Recovery: RAID nach Plattenausfall wieder vervollständigen

Irgendwann wird (mindestens) eine Platte ausfallen. Bei mir sah das im logwatch-Report dann so aus:

Apr 26 04:05:16 hda: dma_intr: status=0x51 { DriveReady SeekComplete Error }
Apr 26 04:05:16 hda: dma_intr: error=0x40 { UncorrectableError }, LBAsect=20252932, sector=20252924
Apr 26 04:05:16 end_request: I/O error, dev hda, sector 20252924
Apr 26 04:05:17 raid1: Disk failure on hda2, disabling device.
Apr 26 04:05:17 raid1: hda2: rescheduling sector 3866624
Apr 26 04:05:17 raid1: hdc2: redirecting sector 3866624 to another mirror

Hier ist jetzt nicht die ganze Platte komplett gestorben (z.B. Head-Crash), sondern es war "nur" ein Sektor der Platte unlesbar. Das RAID hat den Ausfall abgefangen, aber das RAID läuft jetzt ohne Fehlertoleranz, weil hda2 deaktiviert wurde, wie man schön mit cat /proc/mdstat sieht:

...
md0 : active raid1 hdc2[1] hda2[2](F)
  8193024 blocks [2/1] [_U]
...

Im Prinzip ist jetzt ein Plattentausch angesagt. Mutige (oder Unvorsichtige) können aber auch versuchen, die Platte einfach wieder zum RAID hinzuzufügen (jede Platte hat ein paar Reserve-Sektoren, die verwendet werden können, nachdem der eigentlich defekte Sektor als unbenutzbar markiert wurde). Dazu wird zunächst die kaputte Partition entfernt und wieder hinzugefügt:

mdadm /dev/md0 -r /dev/hda2
mdadm --add /dev/md0 /dev/hda2

Tipps zum Fehlerfinden

Natürlich lief bei mir nicht alles glatt nach der initialen Einrichtung.

Stellt sicher, dass alle RAID-Partitionen wirklich auch den korrekten Partitionstyp 0xfd haben. Ansonsten wird diese Partition nicht geladen, was dazu führt, dass das System nicht mehr startet, wenn diese Partition beim Systemstart über die fstab eingebunden wird.