Artikel mit ‘mdadm’ getagged

RAID1 mit neuen Platten vergrößern

Donnerstag, 24. Juni 2010

In einem Kundenserver, der schon ein paar Jahre auf dem Buckel hat, sollte der Speicherplatz erweitert werden – eingebaut waren zwei Festplatten mit je 160 GB; für heutige Verhältnisse in der Tat nicht mehr zeitgemäß. Möglichkeiten gibt es viele: Zusätzliche Platten einbauen (dann verbraucht die Kiste aber mehr Strom und wird lauter); eine externe Festplatte anschließen (die ist dann aber nicht redundant); die Festplatten austauschen und das System umkopieren (das dauert dann aber ewig). Schließlich haben wir uns für die schickste Möglichkeit mit minimaler Downtime entschieden: Die Festplatten nacheinander im RAID auswechseln. Downtime: Etwa zweimal fünf Minuten jeweils für den Austausch einer Platte. Plus ein bisschen Arbeitsaufwand, der aber im laufenden Betrieb erledigt werden kann.

Zum Nachmachen hier nun das Protokoll. Die Festplatten sind Platten nach S-ATA-Standard; stehen im System also als /dev/sda und /dev/sdb bereit. Sie haben jeweils drei Partionen, die per Software-RAID zusammengefasst sind:

# cat /proc/mdstat 
Personalities : [raid1] 
md1 : active raid1 sda1[0] sdb1[1]
      200704 blocks [2/2] [UU]
      
md2 : active raid1 sda3[0] sdb3[1]
      974550976 blocks [2/2] [UU]
      
md0 : active raid1 sda2[0] sdb2[1]
      2008000 blocks [2/2] [UU]
      
unused devices: 

Dabei fungiert /dev/md0 als Swap-Partition; /dev/md1 als /boot und /dev/md2 als Root-Partition. So, und jetzt geht’s los.

Erstmal wird kurz und schmerzlos eine der beiden Platten ausgebaut – in unserem Fall /dev/sdb, aber welche zuerst kommt, spielt keine Rolle. An ihrer Stelle wurde eine unpartitionierte Platte eingebaut. Der Server wurde wieder hochgefahren; alles kein Problem – dafür ist ein RAID1 ja da. Anschließend galt es, die neue Festplatte zu partitionieren. Das haben wir hier ganz traditionell mit fdisk gemacht und dabei für die ersten beiden kleinen Partitionen (Swap und /boot) die gleiche Zylinderzahl verwendet; die dritte Partition wurde dann entsprechend ausgeweitet. So sieht’s nun aus:

# fdisk -l /dev/sdb

Disk /dev/sdb: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1          25      200781   fd  Linux raid autodetect
/dev/sdb2              26         275     2008125   fd  Linux raid autodetect
/dev/sdb3             276      121601   974551095   fd  Linux raid autodetect

Wichtig ist, hier den korrekten Partitionstyp zu vergeben (in diesem Fall fd für Linux raid autodetect) sowie die erste Partition bootfähig zu machen.

Nun fehlt den drei /dev/md*-Devices ja die Redundanz; die stellen wir also erstmal wieder her, in dem wir mittels mdadm die frisch angelegten Partitionen hinzufügen:

mdadm /dev/md1 -a /dev/sdb1
mdadm /dev/md0 -a /dev/sdb2
mdadm /dev/md2 -a /dev/sdb3

Die ersten beiden synchronisieren in unter einer Minute; für /dev/md2 wurde gut eine halbe Stunde fällig. Mittels

watch cat /proc/mdstat

lässt sich die Synchronisation gut beobachten. Dieser Vorgang muss vollständig und fehlerfrei abgeschlossen sein, denn wir haben ja vor, gleich die Platte, von der synchronisiert wird, ebenfalls zu wechseln, und dafür muss die neu eingebaute natürlich komplett auf dem neuesten Stand sein!

Nun möchte man meinen, das wär’s, aber eine ganz wichtige Sache fehlt noch: Auch wenn die Daten jetzt wieder synchron sind, so fehlt noch der Bootloader – sprich, wenn jetzt die verbliebene Platte ausgewechselt würde, könnte das System nicht mehr booten. Es gilt also, GRUB auf /dev/sdb zu installieren, und das ist nicht ganz so einfach, wie es auf den ersten Blick scheint. Die RAID1-Redundanz liegt ja auf Partitionsebene – betrifft also nicht den Bootsektor selbst.

Der Haken an der Sache ist: GRUB führt eine device.map, in der die physischen Festplatten auf die GRUB-internen Bezeichnungen hd0 und hd1 gemappt werden. Kein Problem, solange es die zweite Festplatte ist, die ausfällt – fällt allerdings die erste aus, wird /dev/sdb als einzige verbleibende Platte plötzlich hd0 statt hd1 – und das schmeckt GRUB nun überhaupt nicht. Man kann nun in der device.map zwar beide Platten von Hand als hd0 definieren; das mag jedoch grub-install nicht und quittiert mit:

The drive (hd0) is defined multiple times in the device map /boot/grub/device.map

Es bleibt also letztlich nur, das Spiel von Hand zu spielen, und zwar so:

grub> device (hd0) /dev/sdb
grub> root (hd0,0)
grub> setup (hd0)
grub> quit

Mit anderen Worten: Man verkauft GRUB die zweite Platte als hd0, also als erste, denn wenn die echte erste Platte einmal ausfällt – dann ist die zweite Platte ja auch faktisch die erste. Das klappt prima, und das System ist bereit zum Austausch der verbliebenen kleinen Platte gegen das größere Modell. Hat man alles richtig gemacht, sollte der Server problemlos mit der einen neuen großen Platte booten (die nun ihrerseits auch nur eine Hälfte des RAID1 darstellt).

Nun sind die obigen Schritte für die verbliebene Platte, in unserem Fall /dev/sda, zu wiederholen: Partitionieren; mittels mdadm zum RAID1 hinzufügen; GRUB von Hand in den Bootsektor packen.

Nun haben wir einen Server mit neuen Festplatten, bei denen die Root-Partition deutlich größer ist, aber bisher haben wir davon noch nichts – es fehlen noch zwei entscheidende Schritte. Zunächst muss die Partition /dev/md2, die jetzt nur noch einen Bruchteil des physisch vorhandenen Speicherplatzes nutzt, auf die neue Größe ausgedehnt werden. Das erledigen wir mit:

mdadm --grow -z max /dev/md2

Hiermit wird für den zusätzlichen Speicherplatz ein Resync angestoßen – sprich, dieser Vorgang zieht sich eine ganze Weile, zumal wir ja hier auf Terabyte-Platten aufgerüstet haben. Im konkreten Fall mussten wir rund zwei Stunden dafür einkalkulieren.

Nun sind wir aber immer noch nicht fertig. Zwar ist das Device jetzt endlich so groß, wie wir es haben wollen, aber das Dateisystem weiß davon noch nichts – und das muss schließlich die neu hinzugekommenen Blöcke auch ansprechen können.

Erfreulicherweise gibt es seit einigen Jahren die Möglichkeit, ein ext2-/ext3-Dateisystem im laufenden Betrieb, sprich: im gemounteten Zustand zu vergrößern. Bei CentOS 4, das auf diesem Server noch läuft (kein Problem, wird ja noch bis Anfang 2012 supportet), übernimmt diesen Job noch ext2online; bei neueren Distributionen ist der Live-Resizing-Code in resize2fs aufgegangen, das bis dahin nur eine Größenanpassung von nicht aktiv verwendeten Devices realisierte. Auf geht’s:

ext2online -v /dev/md2

Der Vorgang zieht sich ein bisschen, aber man kann sehr schön beobachten, wie sich die Größe im laufenden Betrieb ändert – und sich der prozentuale Füllstand der Root-Partition entsprechend nach und nach verringert:

# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/md2              178G  123G   46G  73% /
/dev/md1              190M   15M  166M   8% /boot
none                  505M     0  505M   0% /dev/shm

… warten …

# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/md2              203G  123G   69G  65% /
/dev/md1              190M   15M  166M   8% /boot
none                  505M     0  505M   0% /dev/shm

… warten …

# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/md2              213G  123G   79G  62% /
/dev/md1              190M   15M  166M   8% /boot
none                  505M     0  505M   0% /dev/shm

Wenn dieser Vorgang abschlossen ist – war’s das. Viel Spaß mit dem neu hinzugewonnenen Speicherplatz!

Bevor man das RAID anfaßt

Freitag, 26. März 2010

Nur eine Anmerkung zu dem Bericht meines Kollegen Jonas über die Rettung eines RAID 5:

Ich war mal mit einem RAID 10 in einer ganz ähnlichen Situation, ich hatte kein aktuelles Backup der Daten auf dem RAID und ich konnte leider auch keine Images der Platten im RAID mehr ziehen, um bei einem gescheiterten Reparaturversuch nötigenfalls den Versuch rückgäng zu machen. Es ging auch nicht nur um ein paar Photos, sondern leider um ziemlich wichtige Daten. Ich war also sehr auf Vorsicht bedacht.

Wie schon gesagt war die Situation ganz ähnlich. Ich war mir sehr sicher, daß die Daten auf den Platten noch konsistent waren, aber die Superblöcke wollten partout nicht zusammengehen. Auch ich bin damals auf den Hinweis gestoßen, daß man das RAID auch quasi neu anlegen kann und so wieder zu intakten Superblöcken kommen kann. Aber da ich mir Fehler nicht leisten konnte, zögerte ich etwas mit der Umsetzung.

Und dann hatte ich eine Idee, die letztlich auch funktioniert hat: Man kann sich auf einem anderen Rechner mit Linux auf dem man LVM eingerichtet hat (in diesem Fall war das eine gerade nicht gebrauchte Workstation, auf der im LVM noch viel Platz war) einfach ein paar Logical Volumes einrichten und damit einen RAID einrichten. Natürlich ist ein RAID über Logical Volumes auf derselben Festplatte vollkommen sinnfrei und absolut inperformant, aber es eignet sich hervorragend um das Verhalten von mdadm zu testen. Ich hab mir also vier LVs angelegt, darüber einen RAID 10 erzeugt, darin ein Dateisystem angelegt und einfach ein paar Nutzdaten reinkopiert: eine größere Logdatei, eine MP3, einen Film. Dann habe ich das Dateisystem wieder ausgehängt und den RAID bewußt beschädigt — und zwar so daß derselbe Fehlerzustand hergestellt wurde wie auf dem “echten” RAID 10. Ich konnte dann die Reparatur in aller Ruhe testen, man könnte sogar sagen üben, und nach erfolgreicher Reparatur des Test-RAIDs wunderbar verifizieren, ob die Daten in dem Dateisystem noch stimmten.

Das beste daran war, daß mdadm eben wirklich nicht auf das neu angelegte RAID schreibt, solange man es in degradiertem Zustand anlegt. D.h. ich konnte mir sogar mehrere Fehlversuche leisten. (Bei einem RAID 10 nicht unwahrscheinlich, man muß ja die korrekte Anordnung der Festplatten finden.) Ob das RAID korrekt zusammengefügt war hab ich jeweils damit getestet, ob ich das Dateisytem darin im Read Only Modus mounten konnte oder nicht.

Ein weiterer Vorteil dieser LVM Testumgebung: Man kann sich mit LVM wunderbar Snapshots der LVs anlegen. Wenn man dann bei den Reparaturversuchen tatsächlich etwas beschädigen sollte (kam mir damals nicht vor, aber es hätte ja), dann kann man seine Testumgebung schnell wieder in den Ausgangszustand zurückversetzen und muß sie nicht komplett neu anlegen.

Wenn sonst nichts mehr beim kaputten RAID5 hilft

Donnerstag, 25. März 2010

Ein Kundeskunde ist stolzer Besitzer einer Synology CubeStation. Das sind kleine NAS-Server für daheim, auf Linux-Basis mit einem proprietären Webinterface, aber immer noch mit einer Shell. Je nach Modell sind unterschiedlich viele Platten verbaut; hier konkret vier. Jede Platte hat drei Partitionen, wobei die ersten beiden kleineren jeweils ein kleines RAID1 für die Root- bzw. Swap-Partition darstellen (und hier ergo dreifache Redundanz haben); die jeweils dritten – großen – Partitionen sind zu einem RAID5 ohne Spare zusammengefasst, das als /volume1 gemountet wird, was bei den Synology-Boxen offensichtlich für die eigentliche Ablage von Daten benutzt wird.

Eine der Platten ging kaputt. Kein Problem, dafür hat man ja das RAID. Beim Ausbau der defekten Platte wurde allerdings offensichtlich das Stromkabel einer der weiteren Platten gelockert. Wir wissen nicht genau, was passiert ist, aber der Zustand war der, dass die ersten beiden RAIDs problemlos zusammengesetzt werden konnten; das dritte aber nicht. /dev/sda3 und /dev/sdc3 waren da, /dev/sdb3 fehlte (weil ausgebaut), und /dev/sdd3 – die Platte mit dem Wackelkontakt am Strom – hatte zwar einen md-superblock, der aber nicht mit den anderen harmonierte. Zwar stimmte die UUID; allerdings war der Update-Timestamp nicht ganz synchron. Ein

mdadm --assemble /dev/md2 /dev/sd[acd]3

schlug von daher fehl. Nun ist das an sich kein großes Problem: Man kann mdadm einfach zwingen und die md-superblocks dann wieder neu schreiben. Also:

mdadm --assemble --force /dev/md2 /dev/sd[acd]3

Denkste. Zwar bereitet sich mdadm schon korrekt vor und informiert darüber, dass es den abweichenden update count der dritten Partition anzupassen gedenkt. Dann jedoch stirbt es mit einem Segmentation Fault.

Offensichtlich ein bekanntes Problem. Und zwar nicht spezifisch für die Syno-Box; auch der Ubuntu-Bugtracker findet:
mdadm seg faults when forced to assemble array. Das Problem scheint also spezifisch für mdadm 2.6.7 zu sein – schon bei der 2.6.7.1 soll es angeblich wieder gehen.

Nun ist auf der Syno-Box aber eben die 2.6.7 – und ein Update ist nicht in Sicht. Was also tun? Mein erster Gedanke dazu (und ich bleibe dabei, so schlecht war er nicht): IPKG installieren, und darüber dann eine hoffentlich wahlweise ältere oder neuere Version von mdadm installieren, die diesen Bug nicht hat. Und wenn’s keine gibt, bliebe immer noch die Möglichkeit, über IPKG einen Compiler zu installieren und mdadm 2.6.7.1 aus den Sourcen zu kompilieren.

Es gibt ein mdadm in IPKG. Ein 2.6 – also älter. Nur behauptet /opt/sbin/mdadm --examine (also das via IPKG installierte, im Gegensatz zum vorinstallierten /sbin/mdadm) bei allen Partitionen, dort keinen md-superblock vorzufinden. Hm, vielleicht zu alt? Also doch die Variante mit dem Compiler, und dann ein mdadm aus den Sourcen kompiliert. Noch eine neuere Version genommen. Und dann noch eine. Und noch eine ältere. Aber es half nichts: Alle Versionen fanden keinen md-superblock. Nicht mal eine aus den Sourcen kompilierte 2.6.7, obwohl das doch nun die identische Version zur offiziell installierten ist.

(Gängige Reparaturanleitungen empfehlen, die Platten aus der Syno in einen normalen PC zu bauen – wofür man erstmal entsprechend viele freie SATA-Ports bräuchte – und dann dort den Superblock von der little-endian-Byteorder der ARM-CPU der Syno auf big endian einer Intel-CPU zu ändern, damit das RAID auf einem Intel-PC wieder zusammengesetzt werden kann. Mein Bauchgefühl sagt mir, dass das Problem mit den überhaupt nicht mehr erkannten md-superblocks etwas damit zu tun haben könnte. Allerdings habe ich das mdadm ja auf der Syno kompiliert, also auch mit deren Headerfiles. Insofern müsste die Byteorder eigentlich stimmen. Hm.)

Lange Rede, kurzer Sinn: Nichts half. Bis auf das RAID-Wiki bei kernel.org, das den entscheidenden Tipp gab:

When an array is created, the data areas are not written to, *provided* the array is created in degraded mode; that is with a ‘missing’ device.

Ich denke, man kann sich das in etwa so vorstellen wie eine defekte Partitionstabelle auf einer Festplatte: Es scheint alles weg; keine Partition ist mehr lesbar. Dabei ist klar, dass die Daten an sich alle noch auf der Platte vorhanden sind – man kommt nur ohne Partitionstabelle nicht mehr dran. Man muss es also “nur” schaffen, die paar Bytes Partitionstabelle wiederherzustellen, und das Problem ist gelöst.

So auch hier: Wird bei einem mdadm --create ein Device als “missing” angegeben, wird der Datenbereich der Platten in Ruhe gelassen und nur der Superblock neu geschrieben. Das ist natürlich nur was für echte Männer. Naja, oder für Männer wie mich, die sich vorher versichert haben, dass der Kunde Images der Platten gesichert hat, falls bei den Arbeiten am RAID irgendetwas schief geht. Auf jeden Fall muss man für so ein “Reparatur-create” allerdings wissen, wie dieser Superblock auszusehen hat: Welcher RAID-Level? Wieviele Platten? Welche Platte in welchem RAID-Slot? Welche Chunk-Size? Welche Symmetrie? Das war in diesem Fall einfach: Alle drei Partitionen haben ja schließlich noch einen md-superblock, der all diese Parameter verrät. Letztlich war es also nur das hier:

mdadm --create /dev/md2 --chunks=64 --level=5 --raid-devices=4 \
  /dev/sda3 missing /dev/sdc3 /dev/sdd3

mdadm bemerkte korrekt, dass auf den Partitionen bereits etwas drauf sei, was nach einem RAID riechen würde. Okay, wissen wir ja. Nach einer entsprechenden Bestätigung wurden die Superblocks neu geschrieben. Keine Fehlermeldung. Ein

mount /dev/md2 /volume1

funktionierte anstandslos. Alle Daten vorhanden; auch nach einem Reboot erkennt die Syno-Box das RAID5 jetzt wieder von selbst und bindet es ein. Nach einer jetzt natürlich umgehend anstehenden Datensicherung wäre es von daher im Bereich des Möglichen, nun wieder die vierte, noch fehlende Platte einzubauen und einen Resync zu wagen.

Mein Kunde berichtet vom Kundeskunden, dieser sei “grad total hingerissen davon (echt jetzt)”. Schöne Sache, wobei es hier weniger um ein geschäftliches Desaster gegangen wäre, sondern “nur” etliche Gigabyte an Fotos über den Jordan hätten gehen können. Aber die sind manchmal ja noch viel wertvoller. Ich gehe davon aus, ab heute macht der Kundeskunde Backups.


Impressum