Migration auf Software RAID1 mit SATA

Aus NOBAQ
Zur Navigation springenZur Suche springen

Nachdem der Festplattenspeicherplatz auf meinem Server langsam aber doch zu Neige ging habe ich mich entschlossen gleich auf SATA umzurüsten und ein RAID1 aufzusetzen. Das ist bei den heutigen Festplattenpreisen kein Problem mehr. Ich erhoffe mir dadurch einerseits erhöhte Performance (durch SATA und den neuen Platten) und andererseits erhöhte Ausfallsicherheit.

Hier beschreibe ich nun, wie ich mein altes System (PATA) auf das neue SATA-Software RAID System migriert habe. Bemerkenswert: Fast die gesamte Migration konnte ich von unterwegs mit ssh in einer screen-Session durchführen. Lediglich zum Einbau des SATA Controllers und der Platten musste ich den Server besuchen.



Das System

Auf dem Host System kommt Debian Lenny zum Einsatz. Zu beachten ist dass das RAID-Howto mit den "alten" RAID-Tools arbeitet; in Debian ist jedoch nur mehr das Tool mdadm enthalten.

Der Controller

Als SATA Controller habe ich mich für den Promise SATA300 TX2 entschieden. Der Controller wird lückenlos von Linux unterstützt, das Modul sata_promise ist im Standardkernel enthalten. Es wird soweit ich weiss TCQ/NCQ unterstützt und es wird Hot-Plugging unterstützt!

SATA Platte aus System entfernen:

echo x > /sys/bus/scsi/devices/0:0:0:0/delete

(0:0:0:0 durch das passende Device ersetzen)

Rescan eines Hosts (Platte müsste danach wieder in /dev erscheinen, ggf. unter anderem Namen):

echo "0 0 0" > /sys/class/scsi_host/host0/scan

(host0 durch den passenden Adapter ersetzen; bei SATA gibt es pro Port einen)

Ich habe auch bereits probiert eine Platte im RAID einfach rauszuziehen; das System ist problemlos weitergelaufen. Nach einem Bus-Rescan wurde die Platte wieder gefunden und problemlos wieder ins RAID eingefügt. Bei dieser Konstellation kann ich also - wie bei einem Hardware RAID - im laufenden Betrieb die Festplatten austauschen und eine Platte kann auch ohne Absturz des Systems kaputt werden.

Die Festplatten

Zum Einsatz kommen zwei idente Samsung Spinpoint F2EG mit jeweils 1GB und langsamen 5400rpm. Die "Ecoline" hat den Vorteil dass sie wirklich sehr wenig Strom verbrauchen.

Leider habe ich nicht beachtet dass die Platten normalerweise von unterschiedlichen Herstellern sein sollten falls ich einem Serienfehler zum Opfer fallen sollte.

Die Migration auf RAID

Die Migration auf das RAID habe ich mit minimaler Downtime geschafft.

Ist-Zustand

  • 30 GB Barracuda an Primary Master. Darauf ist das System und per LVM /var
  • 160 GB an Primary Slave. Darauf ist ein LVM mit den Daten (/home etc.) sowie den virtuellen OpenVZ-Servern (/vz)
  • 320 GB an Secondary Master. Backup Platte

Vorbereitungen

  1. Einbau des SATA Controllers. Downtime: Ein reboot. Der Controller wurde anstandslos erkannt.
  2. Einbau der SATA Platten (etwas später weil ich den Controller früher hatte). Die Platten wurden anstandslos als sda und sdb erkannt. Downtime: Ein reboot.

Soll-Zustand

  • Beide Platten mit 1TB gespiegelt
  • Eine Systempartition (incl. /boot) auf RAID1 (ca. 15GB)
  • Eine SWAP Partition auf RAID1 (ca. 15GB)
  • Den Rest mit LVM auf RAID1. Dort sollen dynamisch die Daten rauf (/home) sowie die OpenVZ-Server etc.

Alle Bereiche der Platte sind nun durch eine idente RAID-Partition gespiegelt. Das hat den Vorteil dass wirklich beide Platten komplett ident sind.

Systemroot
Ursprünglich habe ich nicht gewusst dass Linux auch problemlos von einem Software RAID booten kann. Mit RAID autodetect kann sich aber der Systemroot problemlos auf einem RAID (md-Device) befinden. Debian liefert dazu die komplette Unterstützung mit: Das Paket mdadm fragt bereits, ob man von einem md-Device booten möchte und baut daraufhin eine neue initrd mit der benötigten Unterstützung.
Bootpartition
Ursprünglich wollte ich dann zwei separate Bootpartitionen haben, auf jeder Platte eine, und diese manuell synchronisieren. Aber das ist gar nicht notwendig. Lesend ist eine RAID Partition gleich ansprechbar wie das darunterliegende Dateisystem, da es sich nur durch den RAID-Superblock am Ende der Partition unterscheidet. Es kann also auch /boot problemlos in ein LVM aufgenommen werden; grub kann dann problemlos von der Partition lesen


SWAP auf RAID1?
Auch SWAP wollte ich ursprünglich separat auf jede Platte legen (mit gleicher Priorität). Aber das ist gar keine gute Idee, da beim Ausfall einer Platte das System abstürzen würde. Meine Experimente mit dem "Platten einfach herausziehen" hätte das System sofort mit einem Absturz quittiert. Swap auf RAID1 ist zwar ein bisschen langsamer, aber da Swap ohnehin um 10er-Potenzen langsamer ist als der RAM Zugriff ist diese minimale Differenz vernachlässigbar, da ist mir die Systemstabilität dann doch wichtiger. Und auch das Argument mit dem Speicherplatz zählt bei zwei 1TB Platten nicht mehr wirklich.

Die Migration

Software Installation

Im ersten Schritt wurde die passende Software installiert. Das ist mit Debian ja sehr einfach:

aptitude install mdadm

Auf die Frage "Für das Wurzelverzeichnis benötigte MD Verbünde" habe ich "all" gewählt. Das ist wichtig weil sich mein System nun auf einem RAID1 befinden wird. Die letzten Fragen habe ich ebenfalls standard gewählt (monatliche Konsistenzprüfung sowie Monitoring-Daemon).

Partitionierung

Im zweiten Schritt habe ich auf sda mit fdisk die gewünschten Partitionen erstellt:

# 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
Disk identifier: 0xa6c0462d

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1        1887    15157296   fd  Linux raid autodetect
/dev/sdb3            1888        2435     4401810   fd  Linux raid autodetect
/dev/sdb4            2436      121601   957200895   fd  Linux raid autodetect

Wichtig ist dass die Partionen auf ID 0xFD stehen - Linux Software RAID autodetect, damit die LVMs automatisch beim Systemstart gefunden und eingerichtet werden.

Das "verkorkste" Layout hier ist keine Absicht - ich habe im Nachhinein noch die Partitionstabelle geändert.

Um die gleiche Partitionstabelle nun auf die zweite Platte zu übertragen habe ich

dd if=/dev/sda of=/dev/sdb bs=512 count=1

verwendet. Wichtig ist danach ein

fdisk /dev/sdb

auszuführen und die Partitionstabelle mit "w" zu speichern, damit der Kernel die neue Partitionstabelle auch übernimmt.

Erstellung der RAID Devices

Die drei RAIDs wurden wie folgt erstellt:

mdadm --create /dev/md0 --verbose --level=1 --raid-devices=2 /dev/sda1 /dev/sdb1
mdadm --create /dev/md1 --verbose --level=1 --raid-devices=2 /dev/sda4 /dev/sdb4
mdadm --create /dev/md2 --verbose --level=1 --raid-devices=2 /dev/sda3 /dev/sdb3

Die Arrays sind daraufhin sofort einsatzfähig. Damit der nächste Boot auch problemlos funktioniert, wird die aktuelle Konfiguration in die mdadm.conf geschrieben:

mdadm --examine --scan >> /etc/mdadm/mdadm.conf

Ein cat /proc/mdstat sagt nun, dass das Array synchronisiert wird.

Migrieren der OpenVZ VEs

Im ersten Schritt möchte ich die virtuellen Server auf das RAID migrieren. Deshalb erstelle ich gleich das LVM auf /dev/md1:

pvcreate /dev/md1

Als nächstes darauf eine Volume Group (die soll ja unabhängig von meiner bisherigen Konstellation sein):

vgcreate raid1 /dev/md1

Dieser Befehl sagt, dass das Physical Volume auf /dev/md1 zur Volume Group "raid1" gehören soll. Schließlich wird der eigentliche Datenbereich - das Logical Volume erstellt. Für die VServer reichen vorerst 50GB, durch LVM und ext3 kann dr Bereich ja im Nachhinein problemlos erweitert werden.

lvcreate -L +50G --name vz raid1

Nun noch ein ext3 Dateisystem darauf erstellen:

mke2fs -j /dev/raid1/vz

und mounten:

mount /dev/raid1/vz /mnt

Sukzessive habe ich nun die OpenVZ Container auf das neue LV kopiert. Dazu muss zuerst die VE beendet werden, dann mit rsync die Dateien kopiert werden. Schließlich noch ein symlink aufs neue Verzeichnis und die VE wieder starten:

vzctl stop 200
rsync -v -a -A -X /var/lib/vz/private/200/ /mnt
rm -r /var/lib/vz/private/200
ln -s /mnt/200 /var/lib/vz/private/200
vzctl start 200

Diesen Vorgang habe ich für alle VEs ausgeführt; die Downtime pro VE war damit nur die Zeit die zum Kopieren des Systems benötigt wurde. Das ganze ging übrigens von unterwegs per ssh und screen-Session.

Nachdem alle VEs kopiert waren, habe ich die neue in die fstab eingetragen:

#/dev/vgdata/vserver   /var/lib/vz/private   ext3    defaults,noatime,acl 1 1
/dev/raid1/vz          /var/lib/vz/private   ext3    defaults,noatime,acl 1 1

Nun noch einmal alle VEs beenden (am besten ganz OpenVZ), die Partition ummounten und die alte LV entfernen:

/etc/init.d/openvz stop
umount /mnt
umount /var/lib/vz/private
mount /var/lib/vz/private
/etc/init.d/openvz start
lvremove /dev/vgdata/vserver

Migration von /home

Als nächstes kommt /home an die Reihe. Da /home groß ist möchte ich nicht alle VEs die /home verwenden herunterfahren. Die Maildirs liegen auf /home; so habe ich den Mailserver heruntergefahren und meinen Backup MX auf slave.nobaq.net gestartet. Auf den anderen Servern habe ich lediglich alle Dienste beendet die die Datenintegrität auf /home gefährden würden.

Nun kann also die LV erstellt werden und die Daten kopiert werden:

lvcreate -L 150G -n home raid1
mkfs -t xfs /dev/raid1/home
mount /dev/raid1/home /mnt
rsync -a -A -X /home /mnt/
umount /mnt

Die neuen Einträge in der fstab lauten nun:

#/dev/vgdata/lvhome    /home     xfs      defaults,noatime 1 2
/dev/raid1/home        /home     xfs      defaults,noatime 1 2

Nun werden alle VEs heruntergefahren die /home benutzen und das neue /home gemountet. Die alte VE kann ggf. wieder entfernt werden:

vzctl stop 200
vzctl stop 301
umount /home
mount /home
vzctl start 200
vzctl start 301
lvremove /dev/vgdata/lvhome

Noch ist ein problemloser Reboot des ganzen Systems möglich, da erst die Daten auf die neuen Platten kopiert wurden.

Migration von swap

Der nächste Schritt, der swap ist relativ einfach:

mkswap /dev/md2
swapon /dev/md2
swapoff /dev/hda3 # alte Swap-Partition

...sowie wieder die /etc/fstab ändern.

Migration des Systems

Der letzte Schritt - Das Kopieren des Root-Systems müsste normalerweise mit einer Boot-CD ausgeführt werden, damit das System in einem konsistentem Zustand kopiert wird. Da aber am Hostsystem ohnehin keine Services mehr laufen habe darauf verzichtet und direkt kopiert.

mke2fs -j /dev/md0
mount /dev/md0 /mnt
rsync -a -x / /mnt
umount /mnt

Vor dem reboot muss allerdings noch der Bootloader (grub) konfiguriert werden.

Konfiguration von grub

Wie ich bereits oben erwähnt habe, kann Linux auch einem RAID Device gestartet werden, sofern durch die Installation von mdadm bereits eine passende initrd erstellt worden ist. Im Prinzip muss also nur der root-Parameter geändert werden:

title radix (OpenVZ) [Debian lenny, sda]
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.26-2-openvz-686 root=/dev/md0 \
                     apm=off console=tty0 console=ttyS0,9600n8
        read-only
        initrd /boot/initrd.img-2.6.26-2-openvz-686

Das tolle am RAID1 ist aber nun, dass eine Platte komplett ausfallen kann und das System trotzdem vollkommen start- und lauffähig bleibt. Aus diesem Grund wird eine zweite Konfiguration im grub erstellt, die von der zweiten Platte bootet (es unterscheidet sich also nur die root-Direktive):

title radix (OpenVZ) [Debian lenny, sdb]
        root (hd1,0)
        kernel /boot/vmlinuz-2.6.26-2-openvz-686 root=/dev/md0 \
                     apm=off console=tty0 console=ttyS0,9600n8
        read-only
        initrd /boot/initrd.img-2.6.26-2-openvz-686

Ganz oben muss noch folgendes hinzugefügt werden:

default=0
fallback=1

Bei dieser Konfiguration bootet grub automatisch von der ersten Platte (erste Konfiguration) aber falls dies fehlschlägt (weil diese Platte eben ausgefallen ist) von der zweiten Konfiguration.

Natürlich muss jetzt die devices.map auch noch entsprechend geändert werden, um (hdN,M)-Einträge passend aufzulösen. Normalerweise würde ich hier einfach die /dev/sdX-Devices reinschreiben. Ich verwende aber folgende Konfiguration:

(hd0)    /dev/disk/by-id/scsi-SATA_SAMSUNG_HD103SIS1VSJ1KS300499
(hd1)    /dev/disk/by-id/scsi-SATA_SAMSUNG_HD103SIS1VSJ1KS300505

Die Platten werden also durch ihre ID referenziert. Das ist insebsondere bei diesem SATA-Hotplug Setup sehr hilfreich, denn wenn eine Platte entfernt wird die zuvor sda geheissen hat, kann die neue Platte z.B. sdd heissen, falls man eine Platte während des Betriebs austauschen will.

Schließlich wird der grub-Loader nun auf beiden Platten installiert:

grub-install /dev/disk/by-id/scsi-SATA_SAMSUNG_HD103SIS1VSJ1KS300499
grub-install /dev/disk/by-id/scsi-SATA_SAMSUNG_HD103SIS1VSJ1KS300505

Ausbau der alten Platten

Es folgt ein reboot bei dem man sich davon überzeugen kann dass das neue Setup funktioniert. Im letzten Schritt wird das System heruntergefahren und die alten PATA-Platten ausgebaut. Downtime: ca. 5 Minuten.

Test

Mit einem echten Hardware-Test habe ich gleich sowohl die Hot-Plugging Fähigkeit als auch das RAID getestet: Ich habe einfach im laufenden Betrieb eine der beiden Platten abgestöpselt!

Resultat: Sofort hat /proc/mdstat statt [UU] [_U] bei allen md-Devices gemeldet gemeldet: Das bedeutet dass die eine Platte kaputt ist und das RAID nun mit einer Platte weiterläuft. Zusätzlich wurden die Partitionen auf sda mit (F) für "failed" markiert. Das System ist absolut ohne Probleme weitergelaufen.

Zur Sicherheit habe ich noch einen Rescan des SCSI-Busses ausgeführt:

echo "0 0 0" > /sys/class/scsi_host/*/scan

/dev/sda ist nun aus dem System weg, auch die Einträge in /dev fehlen. Nun habe ich die Platte wieder reingeschoben und abermals einen Rescan ausgefürt. Die "neue" (alte) Platte wurde nun als /dev/sdd erkannt (da es die nächste freie Device-Nummer war).

Nun müssen die alten Devices entfernt werden:

# mdadm --manage /dev/md2 --remove /dev/sda3
mdadm: cannot find /dev/sda3: No such file or directory

Das ist einerseits logisch, weil das Devicefile der alten Platte ja nicht mehr existiert, auf der anderen Seite problematisch weil ich die alte Platte ja aus dem Verbund nehmen will.

Aus diesem Grund gibt es die Option "--remove failed" die kaputte Platten aus dem Verbund entfernt:

mdadm --manage /dev/md0 --remove failed
mdadm --manage /dev/md1 --remove failed
mdadm --manage /dev/md2 --remove failed

Schließlich werden die neuen (alten) Partitionen, die ja jetzt unter /dev/sdd* zu finden sind, den RAID Verbünden hinzugefügt:

mdadm --manage /dev/md0 --add /dev/hdd1
mdadm --manage /dev/md1 --add /dev/hdd4
mdadm --manage /dev/md2 --add /dev/hdd3

Fertig! In /proc/mdstat lässt sich wieder ein resync der beiden Platten erkennen.

Der Test hat mir also gezeigt: Gleich wie bei einem professionellen Hardware RAID kann eine Platte im laufenden Betrieb ausfallen ohne das System zu beeinträchtigen! Und noch besser: Im laufenden Betrieb kann die Platte ausgetauscht werden.