RAID1 mit neuen Platten vergrößern

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!

Tags: , , , ,

Eine Antwort zu “RAID1 mit neuen Platten vergrößern”

  1. Axel Röhken sagt:

    Hallo !
    Habe die Anleitung hier genutzt, um das RIAD-1 des Root-FS auf meinem Server zu vergrößern. Danke.
    Anmerkung zu grub:
    root (hd0,0) passt nicht: Meine Root-Partition (md1) wird durch sda2 und sdb2 gebildet.
    Mit
    root (hd0,1) klappte das setup dann auch sofort. Dies sowohl beim Tausch von sda als auch sdb.

    Gruß
    Axel


Impressum