Booten vom Software-RAID

Es sind zwei Platten im Server und der Server könnte ein Hardware-RAID. Aber die Jahre mit Hardware-RAIDs haben gezeigt, daß ich das eigentlich nicht will. Die Probleme sind bekannt:

  • Bei Ausfall oder Wechsel der Hardware werden die Platten nicht wieder erkannt, sind nicht (einfach) lesbar oder werden gar automatisch gelöscht, weil der andere RAID-Controller die Meta-Informationen nicht (richtig) versteht.
  • Wenn Platten getauscht oder vergrößert werden sollen, ist das System zu booten, um ins Controller-BIOS zu kommen.
  • Das Management und auch nur das Auslesen der aktuellen Statusinformation erfordert zusätzliche Software (minimal einen Treiber im Kernel).
  • Die Leistungsfähigkeit des Hauptsystems ist ungleich größer als die des embedded Controllers auf der RAID-Hardware.
  • Bugs und selbst die Aktualisierung von Firmware kann katastrophale Folgen haben.

Einige negative Erinnerungen: Ein "3ware Inc 9650SE SATA-II RAID" wird von angeschlossenen Velociraptor-Platten so überfahren, daß er unter Last abstürzt und Linux irgendwann die Nase voll hat und nicht mehr auf diese Devices schreiben will. Etwas älter war ein Controller, der sich bei der Parity Berechnung vertat: In Konsequenz hat er über mehrere Monate alle Daten geschreddert.

Typischer sind aber die kleinen Probleme der täglichen Nutzung. Der RAID-Controller versteckt die Information, welche Platte genau betroffen ist, wann welcher Fehler wobei auftrat. Ohne extra Tools bleibt einem dann nur der Reboot ins Controller-Bios.

~# cat /var/state/raidstat
/dev/cciss/c0d0: (Smart Array P400) RAID 5 Volume 0 status: OK.
  At least one spare drive has failed.  At least one spare drive remains available.

Software-RAID

Konsequenterweise gehe ich also auf Software-RAID im Kernel. Gemäß den aktuellen Empfehlungen soll es also so laufen:

  • Die Platten werden mit mdadm zu einem Raid1 zusammengezogen.
  • Der Bootlader soll von jeder Platte einzeln booten können.
  • Das Root-Filesystem muß vor dem ersten Mounten schon als Raid Device eingebunden sein.

Ein erster Versuch bestand darin, die Platten sda und sdb zu einem md0 zusammenzuschieben und dieses selbst zu partitionieren. Auslöser der Überlegung ist, daß so der Bootlader automatisch alle MBR konsistent beschreiben wird.

Dies war eine schlechte Entscheidung, weil so die Platten nur schwer in der Größe verändert werden können und vor allem die Partitionsdevices dynamische Major und Minor-Nummern erhalten. Ich mag diese Dynamik einfach nicht.

Also lieber ganz klassisch ein md-Device pro Partition. Zuerst also beide Platte einzeln gleichartig partitionieren und mit "mdadm --create" die Raids erstellen. Und schon wieder eine Entscheidung: Soll das Raid über sda1 und sdb1 den Namen md0 oder md1 bekommen? Für gleiche Nummer spricht eine leichtere Scriptfähigkeit, für einen Offset spricht die Gewohnheit.

Kann man diese Entscheidung nachträglich ändern? Im Prinzip ja, denn "mdadm --assemble" baut ein Raid auch auf ein anderes md-Device. In "/proc/mdstat" stehen dann dennoch die Angaben vom Anlegezeitpunkt. Also sorgt man hier lieber für Konsitenz.

Der Bootlader

Ich hänge an LILO. Er ist einfach, klein und verständlich. Allerdings ist das Booten von RAIDs für Lilo eine neue Eigenschaft: Lilo muß sich in den MBR der Platte schreiben und die Datein in der Boot-Partition finden.

Mit den dynamischen Devicenummern von Partitionen eines Raid-Devices kommt Lilo gar nicht klar. Seine RAID-Unterstüztzung beschränkt sich auf Raids von Partitionen. Der Versuch, es Lilo leicht machen zu wollen, ist damit gescheitert.

Man trägt also im in der "lilo.conf" ein, daß "root=/dev/md0" sei. Aber was gehört nach "boot"? Eigentlich müsste man die Platten "/dev/sda" und "/dev/sdb" angeben. Tyischerweise wird genau das auch empfohlen. Elegant ist anders.

In der Dokumentation von Lilo.conf findet sich: A raid installation is initiated  by specifying a RAID1 device as the boot  device;  e.g., "boot=/dev/md0". Und tatsächlich gibt es hierfür besonderen Code im Lilo.  Man gibt an, er möge von der Partition booten und er erweitert es selbstständig auf die ganze Platte.

# lilo -v -v
[...]
do_md_install: MD_PARALLEL
  offset 00000000  /dev/sda
  offset 00000000  /dev/sdb
The boot record of  /dev/md0  has been updated.

Unglücklicherweise bootet das System danach nicht. Ein Blick in den Master Boot Record offenbar schreckliches:

# fdisk /dev/sda
Command (m for help): x
Expert command (m for help): d
Device: /dev/sda
0x000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Nichts! Aber lilo hatte doch genau dieses Sektor geschrieben, oder etwa nicht? Nein, Lilo hat zwar den Sektor benannt, aber nichts geschrieben.

In der Dokumentation steht unter "raid-extra-boot" folgendes: Starting with LILO version 22.0, the boot record is normally written to the first sector of the RAID1 partition. On PARALLEL raid sets, no other boot records are needed. The default action is auto, meaning, automatically generate auxilary boot records as needed on SKEWED raid sets. Eigentlich sollte das doch reichen?

Muß man hier etwa die Boot-Platten trotzdem einzeln aufführen? Tatsächlich steht da etwas später: Use of an explicit list of devices, forces writing of auxiliary boot records only on those devices enumerated, in addition to the boot record on the RAID1 device. Der Boot Record des RAID1 devices ist aber der Boot-Record in der Partition, nicht der MBR.

Es geht aber weiter mit: Since the version 22 RAID1 codes will never automatically write a boot record on the MBR of device 0x80, if such a boot record is desired, this is one way to have it written. Use of mbr is the other way to force writing to the MBR of device 0x80. Man kann also den MBR extra anfordern.

Mit der Option "raid-extra-boot = mbr" sieht es dann so aus.

# lilo -v -v
do_md_install: MD_PARALLEL
  offset 00000000  /dev/sda
  offset 00000000  /dev/sdb
The boot record of  /dev/md0  has been updated.
The Master boot record of  /dev/sda  has been updated.
The Master boot record of  /dev/sdb  has been updated.

Viola! Und es bootet von beiden Platten.

Mounten der Root-Partition

Bevor Linux den Init-Prozess starten kann, muß es das Root-Filesystem mounten. Dieses liegt aber auf einem RAID-Device. Der bisherige Kunstkniff, mit dem speziellen Partitionstyp "fd" dem Kernel zu sagen, er möge das RAID per Autodetect zusammebauen und davon booten, ist nun nicht mehr erwünscht.

Es bleibt also nicht viel mehr als ein frühes Dateisystem wie Initramfs zu nehmen und dort die RAIDs zusammenzubauen. Dies hat andererseits den Charme, daß die korrekten Partitionstypen erhalten bleiben und man das Root-Filesystem prüfen und reparieren kann, bevor man es benutzt. Die frühzeitige Reparatur des Root-Filesystems vermeidet einen zusätzlichen Reboot nach einem Absturz.

Wenn man einmal mit einem frühen Dateisystem anfängt, gewinnt man generell noch andere nützliche Effekte, wie Booten vom Netz und eine Fehlerkonsole auch bei schwereren Hardwareausfällen. Die dabei entstehenden schlanken modularen Kernel sind quer über alle Maschinen einsetzbar, was schnellere Updatezyklen gestattet.

Davon aber später mehr.

Avatar
Lutz Donnerhacke 09.12.2013 15:38
Da es mir gerade auf die Füße gefallen ist: Das RAID darf bei der Ausführung von Lilo nicht degraded sein.

Die Ausgangssituation war einfach: Ein Server mit einer einzelnen Platte zeigte erste Ausfallerscheinungen auf ebendieser Platte.

Eine neue Platte einzubauen war einfach, weil noch ein Slot frei war. Diese wurde auch gleich als RAID konfiguriert "mdadm --create md0 -n2 -l1 missing sdb1". Die zweite Platte sollte später kommen, weil da ja noch die defekte Platte steckt.

Allerdings lies sich lilo halt nicht dazu überreden, die Daten auch zu schreiben. Erst nachdem das RAID manuell "repariert" wurde, ging es: "mdadm --grow md0 -n1 -f"

1 Kommentare

Post a comment

Verwandter Inhalt