mkinitrd und Filesystem-Labels

Au Backe, das hätte deutlich schiefer gehen können.

Nicht selten betreiben wir Server mit einem Xen-Kernel als Dom0 und binden die DomU aber nicht von einer lokalen Festplatte ein, sondern via iSCSI. Das stellt sich dann so dar, dass die Dom0 eine /dev/sda hat (z.B. eine eingebaute Festplatte); das iSCSI-Target wird dann eingebunden und steht als /dev/sdb bereit. Von diesem Device werden dann aber keine Partionen direkt gemountet, sondern das Device wird in der Xen-Konfiguration der DomU als phy:-Device angesprochen. So weit, so gut – klappt auch einwandfrei.

Nun hat der anaconda-Installer von CentOS 5 die Angewohnheit, für die Root- und die /boot-Partition Labels zu vergeben. Diese kann man auf der Shell z. B. mit e2label einsehen und auch nachträglich jederzeit ändern. In der /etc/fstab wird dann die Root-Partition nicht mit /dev/sda2 referenziert, sondern mit LABEL=/, weil die Partition eben das Label namens „/“ erhalten hat. Der Gedanke dahinter ist eigentlich gar nicht mal schlecht: Ändert ein Device seine Bezeichnung, beispielsweise weil ein zusätzliches Gerät am SCSI-Bus hängt und eine sda plötzlich eine sdb ist, so kann es dennoch unverändert angesprochen werden, weil es sein Label behält. Und das funktioniert auch prima.

Bis auf eins.

Wir führten auf einer Dom0 ein Kernel-Update durch. In diesem Zuge wurde auch eine neue initrd erstellt. Hierbei stellt mkinitrd alle für den Bootvorgang nötigen Module zusammen und strickt ein minimales init-Script. Das hat auch tausend Mal prima funktioniert – bis heute. Heute war nämlich gerade ein iSCSI-Target eingebunden – was an sich auch kein Problem ist, denn mkinitrd interessiert sich, was Treiber für Blockdevices angeht, eigentlich nur für die Devices, die in der /etc/fstab als zum Booten nötig referenziert werden. Nun nennt die /etc/fstab aber LABEL=/ als Root-Device, und damit nimmt das Unheil seinen Lauf. Zunächst einen Blick auf die Konfiguration:

# head -1 /etc/fstab 
LABEL=/ / ext3 defaults 1 1

# e2label /dev/sda2
/

# df -h | head -2
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda2              31G  1.9G   27G   7% /

Und jetzt das Problem. Es ist wie gesagt gerade ein iSCSI-Target eingebunden, das vom Kernel auf /dev/sdb gemappt wird und das nur eine Partition hat:

# ls -l /dev/disk/by-path/ip-*
lrwxrwxrwx 1 root root  9 Jul  8 22:32 /dev/disk/by-path/[...]-lun-0 -> ../../sdb
lrwxrwxrwx 1 root root 10 Jul  8 22:32 /dev/disk/by-path/[...]-lun-0-part1 -> ../../sdb1

Und eben jene Partition … hat auch das Label „/“:

# e2label /dev/sdb1
/

mkinitrd -v zeigt dann, dass es zwar versucht, das Richtige zu tun (nämlich herauszubekommen, was für eine Art Device die Root-Partition ist, damit es die dafür nötigen Treiber in die initrd einbinden kann, löst das Label aber prompt auf genau das falsche Device auf:

...
Found root device sdb1 for LABEL=/
Looking for driver for device sdb1
Found iscsi component /sys/devices/platform/host6/session5/target6:0:0/6:0:0:0
...

Damit erstellt es letztlich eine initrd mit dem falschen Root-Device – und baut dazu den gesamten iSCSI-Support mit ein, bis hin zu einem iscsistart-Aufruf, der die Zugangsdaten beinhaltet, die nötig sind, um das Target vom iSCSI-Host einbinden zu können. Ohne das -v dabei sieht man davon … nix. Vor allem sahen wir schon deshalb nichts davon, weil wir nicht mal mkinitrd selbst aufgerufen hatten – das hatte new-kernel-pkg aufgerufen, und auch das wiederum hatten wir nicht aktiv benutzt, sondern es befindet sich im %postinstall-Abschnitt des Kernel-RPMs, das wir gerade mit yum upgrade kernel-xen auf den neuesten Stand gebracht haben. Wie schon einige Male davor, immer ohne Probleme. Davor war eben zum Zeitpunkt der Kernel-Updates auch noch kein iSCSI-Target eingebunden.

Nach einem Reboot zeigte sich ein absurdes Bild. Beim Booten war deutlich erkennbar, wie sich der Server faktisch das iSCSI-Device holte und als /dev/sda vorzeigte; die lokale Festplatte war dadurch nun plötzlich /dev/sdb (in diesem Zusammenhang mag man ein zynisches „Ja und, dafür gibt’s doch die Labels!“ einwerfen. Sehr witzig, haha). Merkwürdigerweise war der Inhalt der Root-Partition definitiv der, der von der Root-Partition der lokalen Platte kam – obwohl jene laut mount das iSCSI-Device sein sollte. Kurz, das System befand sich in nicht wirklich definiertem Zustand, und darüberhinaus mussten wir uns darum sorgen, dass das fragliche iSCSI-Device, das gerade angeblich unsere Root-Partition darstellte (aber irgendwie eben auch wieder nicht) Schaden davontragen könnte, weil es nämlich parallel dazu auf einem anderen Xen-Host bereits eingebunden und aktiv in Benutzung war. Wir können uns bislang nicht erklären, wie es zu dieser merkwürdigen Differenz zwischen angeblichem und realem Mount-Zustand kommen konnte, aber auf wundersame Weise blieb das iSCSI-Target von diesem Schindluder völlig unbeeindruckt. Puh..!

Der Bugfix war letztlich trivial: Wir haben in der /etc/fstab der Dom0 alle Labels durch echte Devicenamen ersetzt und die initrd neu erstellt. Ein Reboot, und das System befand sich wieder in definiertem Zustand. Für heute: Mit einer großen Portion Glück davongekommen. Und viel über mkinitrd gelernt.