bk99.de entertain the web since 1997

Software-RAID 2009: Mein mdadm-Spickzettel für Platten, Spares und GRUB

Zusammenfassung

Im Oktober 2009 lief mein Server odin mit einem Software-RAID 5 für die Daten und einem RAID 1 mit Hotspare für das System, verwaltet mit mdadm. Damit ich bei einem Plattentausch nicht jedes Mal suchen musste, habe ich mir die Befehle notiert: Partitionen kopieren, Platten entfernen und hinzufügen, Spares tauschen, GRUB auf alle Platten schreiben und den Zustand auto-read-only verstehen. Dieser Beitrag aus meinem alten Blog erklärt die Schritte mit den Ausgaben von damals und zeigt, was sich bis heute geändert hat.

Der Aufbau von 2009

Mein Server hieß odin und hatte drei Platten: zwei SATA-Platten als sda und sdb und eine ältere IDE-Platte als hda. Jede Platte trug zwei Partitionen. Die ersten Partitionen bildeten ein RAID 1 für das System (md2), die zweiten ein RAID 5 mit gut 200 GB für die Daten (md1). Vor den Befehlen stand ein Vorwort, das ich heute anders schreiben würde:

„RAID-5 ist nicht sinnvoll in Software abzubilden (XOR sollte im RAID in Hardware gemacht werden). Ich habe dies hier trotzdem gemacht um nicht zusätzliche Hardware (Platten/RAID5 Controller) anschaffen zu müssen.“

Platten vorbereiten, entfernen und hinzufügen

Eine neue Platte muss dieselbe Partitionierung bekommen wie die anderen. sfdisk liest die Tabelle einer Platte als Text aus und schreibt sie auf die andere:

odin:~# sfdisk -d /dev/sda | sfdisk /dev/hda

Danach kommen die Partitionen mit mdadm aus dem Verbund heraus und wieder hinein. Beim Hinzufügen beginnt sofort der Wiederaufbau, und /proc/mdstat zeigt, wie weit er ist:

odin:~# mdadm --manage --remove /dev/md1 /dev/hda2
odin:~# mdadm --manage --add /dev/md1 /dev/hda2
odin:~# cat /proc/mdstat
Personalities : [raid1] [raid6] [raid5] [raid4]
md1 : active raid5 hda2[3] sdb2[1] sda2[2]
      214836992 blocks level 5, 64k chunk, algorithm 2 [3/2] [_UU]
      [=>...................]  recovery =  7.0% (7588176/107418496) finish=30.6min speed=54199K/sec

Die Ausgabe ist kompakt, aber vollständig: [3/2] heißt, dass drei Platten vorgesehen und zwei aktiv sind, [_UU] zeigt, welche fehlt. Ein RAID 5 aus drei Platten übersteht genau einen Ausfall; während dieser halben Stunde Wiederaufbau hatte es keine Reserve.

Eine Hotspare für das System

Für das System-RAID 1 nahm ich die dritte Partition als Hotspare. Sie liegt untätig bereit und springt ein, sobald eine aktive Platte ausfällt. In /proc/mdstat ist sie am (S) zu erkennen:

odin:~# mdadm --manage --add /dev/md2 /dev/hda1
odin:~# cat /proc/mdstat
md2 : active raid1 hda1[2](S) sda1[0] sdb1[1]
      9767424 blocks [2/2] [UU]

Spannend war der Test: Ich habe sdb1 von Hand als defekt markiert. Die Spare hda1 übernahm sofort und wurde synchronisiert. Danach habe ich sdb1 entfernt und wieder hinzugefügt, und nun war sdb1 die neue Spare. Die Rollen hatten also getauscht, ohne dass das System je ohne Spiegel war.

odin:~# mdadm /dev/md2 --fail /dev/sdb1
mdadm: set /dev/sdb1 faulty in /dev/md2
odin:~# mdadm /dev/md2 --remove /dev/sdb1
mdadm: hot removed /dev/sdb1
odin:~# mdadm /dev/md2 --add /dev/sdb1
mdadm: re-added /dev/sdb1
odin:~# cat /proc/mdstat
md2 : active raid1 sdb1[2](S) sda1[0] hda1[3]
      9767424 blocks [2/1] [U_]
      [==>..................]  recovery = 13.7% (1348288/9767424) finish=4.5min speed=31144K/sec

GRUB auf jede Platte

Ein gespiegeltes System nützt nichts, wenn nur eine Platte einen Bootloader hat. Fällt genau die aus, startet der Rechner nicht mehr. Deshalb habe ich GRUB, damals noch die alte Version 0.97, nach jedem Tausch auf alle Platten geschrieben. In der GRUB-Shell findet find die Platten mit /boot, root wählt eine aus und setup schreibt den Bootloader in deren Anfang:

odin:~# grub
grub> find /boot/grub/stage1
 (hd0,0)
 (hd1,0)
 (hd2,0)
grub> root (hd0,0)
 Filesystem type is ext2fs, partition type 0xfd
grub> setup (hd0)
grub> root (hd1,0)
grub> setup (hd1)
grub> root (hd2,0)
grub> setup (hd2)
grub> quit

Der Partitionstyp 0xfd steht für „Linux raid autodetect“. Dass GRUB 0.97 von einer RAID-1-Partition lesen konnte, lag daran, dass die damals üblichen md-Metadaten der Version 0.90 am Ende der Partition lagen: Für den Bootloader sah jede Hälfte des Spiegels aus wie ein gewöhnliches ext-Dateisystem.

Was auto-read-only bedeutet

Nach einem Neustart stand bei md1 plötzlich (auto-read-only), und mein Kommentar dazu war ein Fragezeichen: Der Zustand verhindere „in den nächsten Stunden einen rebuild“. Die Kerneldokumentation erklärt es genauer: read-auto verhält sich wie read-only, also ohne Resync und ohne geschriebene Metadaten, wechselt aber beim ersten Schreibzugriff von selbst in den normalen Zustand. Ein Array, das gerade niemand beschreibt, wartet also einfach. Wer nicht warten will, schaltet es von Hand um:

odin:~# mdadm --readwrite /dev/md1

Zum Ausprobieren: RAID 1 aus zwei Dateien

Am Ende der Notiz stand ein Experiment: ein RAID 1 aus zwei Dateien, die über Loop-Geräte wie Platten aussehen. Das ist bis heute die beste Art, mdadm gefahrlos zu üben.

dd if=/dev/zero of=/export/ftp_space1/raid1_file0 bs=10240 count=10240
dd if=/dev/zero of=/export/ftp_space2/raid1_file1 bs=10240 count=10240
losetup /dev/loop0 /export/ftp_space1/raid1_file0
losetup /dev/loop1 /export/ftp_space1/raid1_file1
mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/loop0 /dev/loop1
mkfs.ext3 /dev/md0
mount /dev/md0 /export/ftpraid0

Mit dem Blick von heute fällt ein Tippfehler auf: Die zweite Datei wird in ftp_space2 angelegt, losetup greift aber auf ftp_space1 zu. Gemeint war ein Spiegel über zwei verschiedene Freigaben, eine Idee, die auch ein Hackaday-Projekt von 2007 über ein RAID aus Netzwerkfreigaben zeigt. Heute spart losetup -f --show die Suche nach freien Loop-Geräten.

Was sich bis heute geändert hat

  • XOR in Software ist kein Problem mehr: Der Kernel misst beim Start, welche XOR-Routine auf der CPU am schnellsten ist, und nutzt dafür SIMD-Befehle. Hardware-RAID-Controller sind für kleine Server eher ein Risiko, weil man im Fehlerfall den gleichen Controller braucht. mdadm-Arrays lassen sich dagegen an jedem Linux-Rechner zusammensetzen.
  • Die Write Hole: Stürzt ein RAID 5 mitten im Schreiben ab, können Daten und Parität auseinanderlaufen. md kann das heute schließen, mit einem Journal auf einer eigenen Platte oder mit dem Partial Parity Log (--consistency-policy=ppl).
  • GRUB 2 und UEFI: Unter BIOS schreibt man den Bootloader mit grub-install auf jede Platte, unter Debian auch über dpkg-reconfigure grub-pc. Mit UEFI liegt der Bootloader auf der EFI-Systempartition, und die gehört nicht ohne Weiteres in ein md-RAID. Man legt auf jeder Platte eine eigene an und hält sie gleich.
  • GPT statt MBR: sfdisk kann GPT inzwischen auch; mit sgdisk -R kopiert man die Tabelle und vergibt danach mit sgdisk -G neue GUIDs.
  • Regelmäßig prüfen: echo check > /sys/block/md1/md/sync_action liest alle Blöcke und vergleicht die Redundanz. So fallen schleichende Lesefehler auf, bevor ein Wiederaufbau sie braucht.
  • Plattennamen: hda gibt es nicht mehr, auch IDE-Platten heißen heute sdX. Für mdadm ist das egal, es erkennt die Mitglieder an ihren Metadaten.

Zahlen im Überblick

  • Die Notiz „Raid Helper“ stand in meinem alten Plone-Blog unter /dokumente/raid-helper, zuletzt geändert am 13. Oktober 2009.
  • md kennt für RAID 5 zwei Gegenmittel gegen die Write Hole: ein Journal-Gerät und das Partial Parity Log.
  • Der Zustand read-auto wechselt beim ersten Schreibzugriff in den normalen Betrieb.
  • Über /sys/block/mdX/md/sync_action startet man mit check eine vollständige Prüfung der Redundanz.

Referenzen

Bemerkungen

  • Diesen Beitrag habe ich 2026 aus der Archivfassung vom Januar 2010 übernommen. Die Befehle und Ausgaben sind wörtlich, bei GRUB habe ich die Erfolgsmeldungen von setup gekürzt.
  • Odin, Hödur, Tyr: Meine Rechner hießen damals nach nordischen Göttern, eine Gewohnheit, die bis zur heutigen Firewall frigg geblieben ist.

Originalnotiz im Webarchiv