Artikel mit ‘iscsi’ getagged

Lob des Backups

Samstag, 11. Februar 2012

Während ich diesen Artikel schreibe, rauschen im anderen Fenster die Zeilen der rsync-Ausgaben über den Bildschirm. Um 07:12 Uhr bemerkte Icinga die ersten Probleme; um 7:17 Uhr eskalierte es sie auf mein Handy. Seitdem bin ich wach, und weil ich während des nun laufenden Restores ohne nichts weiter unternehmen kann und die nächsten Schritte bereits vorbereitet habe, mache ich das Beste draus: Ich blogge.

Um’s direkt vorwegzunehmen: In technischer Hinsicht bietet dieser Blogpost keinerlei Erkenntnisgewinn. Nur vielleicht eine Moral, die da lautet: Macht Backups. (Und benutzt Sonnencreme, klar.)

Vom Monitoring aus dem Schlaf geholt zu werden, ist erstmal kein großer Aufreger. Nicht selten geht es hier um Probleme vom Kaliber „der Apache braucht mal einen Restart“ oder auch „die Mailqueue ist ungewöhnlich voll“ (was auf einen Spamvorfall hindeutet). Echte Ausfälle sind selten. In diesem Fall war es ein sehr kundenspezifischer Check: Es wird durch ein PHP-Script geprüft, ob eine ganz bestimmte Spalte einer ganz bestimmten Tabelle einer MySQL-Datenbank eine bestimmte Länge hat. Die Gründe für diesen Check führen hier zu weit; es gab vor längerer Zeit einen Vorfall, der dazu Anlass gab, und wir sind eigentlich immer bestrebt, für Vorfälle, die nicht durch unser Monitoring diagnostiziert wurden, anschließend noch bessere Checks zu schreiben. Dieser hier ist ein schönes Beispiel: Der Apache lief. Der MySQL-Server lief. Apache konnte auch mit MySQL kommunizieren. Aber MySQL konnte keine Daten schreiben. Das Gros der Checks des fraglichen Systeme meldete daher fröhlich „alles in Ordnung“ – obwohl überhaupt nichts in Ordnung war. Mir war nur noch nicht bewusst, wie sehr nicht.

Das ausgeführte DESCRIBE kunden führte jedenfalls zu einem Fehler, und zwar konkret zu Can't create/write to file '/tmp/#sql_2fc2_0.MYI' (Errcode: 30). Das muss jetzt erstmal noch keine Katastrophe sein, sondern kann auf simple Probleme wie eine überschrittene Quota oder eine vollgelaufene Partition hindeuten (was wir zwar auch monitoren, aber nur in einer niedrigeren Frequenz, weil sowas typischerweise nicht „von jetzt auf gleich“ passiert). Also habe ich mich dann erstmal per SSH eingeloggt, was auch geklappt hat.

Als df -h dann lediglich Command not found lieferte, und ps ax dann auch, war ich dann sehr schnell richtig wach, und es war klar: Das Problem ist größerer Natur als nur eine vollgelaufene /tmp-Partition. Auch dmesg ließ sich nicht mehr ausführen. Da es sich bei dem System um eine Xen-Instanz handelte, war von daher ein Login auf dem Wirtssystem dran. xm console zeige neben dem Login nur noch einen ext3-Fehler: Journal has aborted. Okay, das kommt mal vor. Selten. Und es ist in der Regel kein Problem, das sich nicht mit einem fsck.ext3 lösen ließe. Also: xm shutdown, xm create -c, … und das sah alles so gar nicht gut aus, denn pygrub mochte keine grub-Konfiguration innerhalb des Blockdevices des Gasts mehr finden.

Nun sieht dieses System so aus, dass eine lokal eingebaute Festplatte im physischen Server lediglich als Boot-Medium fungiert. Die Blockdevices hingegen kommen via iSCSI von unserem Storage-Cluster: Zwei dicke Maschinen mit je einem RAID6 über 16 Platten, die über DRBD repliziert werden, und auf denen dann LVM-Volumes via ietd exportiert werden. Schnell ein Login auf dem derzeit aktiven Filer: Gibt’s Probleme? Ein Blick in die Logfiles, in dmesg, … aber alles sah gut aus. Ich habe mich schnell auf einigen anderen Xen-Gästen eingeloggt, die ebenfalls vom Storage-Cluster aus exportiert werden, aber dort war alles in Ordnung, stabiler Betrieb, auch Schreibzugriffe problemlos möglich.

Im konkreten Fall ist auch der physische Server, auf dem die Xen-Instanz läuft, redundant ausgelegt: Via Heartbeat überwachen sich beide Hosts gegenseitig, und wer aktiv ist, bindet das iSCSI-Target ein und fährt die darauf enthaltene Xen-Instanz hoch. Das Setup läuft an sich prima und hat auch schon einige (geplante) Failover-Vorgänge überstanden. Ich hielt den Zeitpunkt für gegeben, einen Failover durchzuführen. Die Xen-Instanz war schnell gestoppt (tja, wenn das Linux-System erstmal nicht mehr auf sein Blockdevice schreiben kann, geht das verdammt fix …), dann ein iscsiadm --logout – und das hing. Und hing. Und hing. Was von daher merkwürdig war, weil der iSCSI-Server durchaus anpingbar war, also kein Problem mit dem Netzwerkinterface o.ä. vorliegen konnte.

In solchen Fällen ist es wichtig, eine Split-Brain-Situation zu vermeiden, sprich, es sollten nicht zwei Hosts das gleiche Blockdevice bearbeiten. Die einfachste Möglichkeit ist, den ohnehin praktisch toten Host komplett vom Strom zu trennen. Gesagt, getan – ist dank IPMI ja alles kein Problem. Dann die Übernahme des iSCSI-Targets auf den anderen Knoten, die von Heartbeat ohnehin automatisch veranlasst wurde, als der bisher aktive Host nicht mehr anpingbar war. Klappte. Mit einem kleinen Problem: Das Blockdevice beinhaltet eigentlich eine Partitionstabelle, die genau eine Partition umfasst, nämlich die Root-Partition. Wird das iSCSI-Target eingebunden, taucht es insofern als /dev/sdb auf (/dev/sda ist das eingebaute Boot-Plattensystem), und noch dazu ein /dev/sdb1 mit jener Root-Partition.

/dev/sdb war da. /dev/sdb1 fehlte. Ein fdisk -l /dev/sdb behauptete schlicht, es gebe keine Partitionstabelle. Das Blockdevice selbst hatte aber schon mal zumindest die korrekte Größe – der Zugriff via iSCSI an sich schien also zu klappen. Sicherheitshalber habe ich mir dann die Partition direkt auf dem Storage-Cluster angeschaut, um sicherzugehen, dass es wirklich kein iSCSI-Problem ist. Zum Vergleich, so sollte es aussehen (bei einem identisch eingerichteten Xen-Image):

[root@filer01 ~]# fdisk -lu /dev/mapper/vgdrbd1-vserver_working 

Disk /dev/mapper/vgdrbd1-vserver_working: 188.7 GB, 188743680000 bytes
255 heads, 63 sectors/track, 22946 cylinders, total 368640000 sectors
Units = sectors of 1 * 512 = 512 bytes

                              Device Boot      Start         End      Blocks   Id  System
/dev/mapper/vgdrbd1-vserver_working1   *           1   368627489   184313744+  83  Linux

Und so sah es faktisch aus:

[root@filer01 ~]# fdisk -lu /dev/mapper/vgdrbd2-vserver_broken 

Disk /dev/mapper/vgdrbd2-vserver_broken: 188.7 GB, 188743680000 bytes
255 heads, 63 sectors/track, 22946 cylinders, total 368640000 sectors
Units = sectors of 1 * 512 = 512 bytes

Disk /dev/mapper/vgdrbd2-vserver_broken doesn't contain a valid partition table

Okay, iSCSI selbst war als akute Fehlerquelle insofern aus dem Spiel. Es schien an der Zeit, TestDisk ins Spiel zu bringen. Dieses Tool ist Gold wert, wenn es darum geht, defekte Partitionstabellen zu fixen, unter anderem, in dem es die Platte sektorenweise nach Blöcken absucht, die z.B. wie ein ext3-Superblock aussehen – oder nach einem Backup davon, denn ext3 legt immer gleich mehrere Kopien des Superblocks verteilt über das Blockdevice an.

TestDisk fand nichts. Also wirklich überhaupt gar nichts. Insofern hatte ich wenig Hoffnung, dass der darauffolgende Schritt noch etwas bringen würde, nämlich die Partitionstabelle anhand eines identisch aufgesetzten VServers zu rekonstruieren. Aber bevor ich’s nicht versucht habe … erwartungsgemäß scheiterte aber der Versuch, die frisch angelegte Partition zu mounten (die ja eigentlich durchaus noch das Dateisystem hätte enthalten müssen – die Partitionstabelle zu bearbeiten, ändert ja nichts daran, dass auf dem Rest der Platte immer noch unverändert Daten liegen). Aus einem anderen Xen-Image identischer Konfiguration konnte ich noch die Positionen ableiten, die die Backup-Superblocks haben sollten, und habe sie alle durchprobiert – nichts.

An diesem Punkt war dann Schluss. Wir sind kein Datenrettungsunternehmen, und wir können auch nicht mal eben fix ein einzelnes LVM-Volume eines Clusters, auf dem noch ein paar Dutzend weiterer – voll funktionsfähiger – Volumes liegen, an ein solches schicken (wenn, dann müssten wir einen Klon des LVM-Volumes auf eine externe Platte anfertigen), und selbst wenn, würde das das Problem nicht lösen, dass das System im Moment eben nicht läuft. Insofern ist an dieser Stelle der Punkt gekommen, an dem ich mit hängenden Schultern sagen muss: Ich habe absolut keine Ahnung, was hier passiert ist. Der Storage-Cluster meldet weiterhin keinerlei Probleme. Sein RAID6 ist 100% in Ordnung (sagt der Controller). Und vor allem gab es ja keinerlei schreibenden Zugriffe auf Partitionstabelle oder Dateisystem des Images des Xen-Gasts, die irgendwie hätten fehlschlagen und etwas korrumpieren können – und Daten verschwinden eigentlich nicht „einfach so“, nicht ohne dass ein physischer Defekt vorliegen würde, was bei einem RAID-System mit vollkommen intakten Platten nun wirklich ausgesprochen unwahrscheinlich ist. Aber, wie’s aussieht, möglich.

Nun also rasseln die Dateien aus dem letzten Backup via rsync wieder zurück auf ein frisch angelegtes und mit einem Dateisystem versehenen Blockdevice. Der größte Datenblock, nämlich /home, ist schon durch, insofern kann es sich nur noch um Minuten handeln. Deshalb noch kurz ein Punkt im Hinblick auf Backups – darauf legen wir großen Wert: Insbesondere dort machen wir nichts mit proprietärer Software oder irgendwelchem Kompressions- oder diff-Gebastel. Die Gelegenheiten, bei denen uns rdiff-backup (dessen Konzept eigentlich ziemlich cool ist) im Stich gelassen hat, sei es durch absurd lange Restore-Zeiten selbst für einzelne Dateien, oder schlicht durch komplette Abbrüche mitten im Prozess, überwiegt die Zahl der Gelegenheiten, in denen es uns gerettet hat, bei weitem. Deshalb sind wir in Sachen Backup extrem konservativ: Ein extra Server mit eigenen Platten, keine komplizierten LVM-DRBD-Sonstwas-Layer dazwischen, einfach nur eine schnöde Partition angelegt, mit rsync kommen die Daten drauf. Versionierung läuft über Hardlinks. Auf diese Weise liegen zwei Versionen der gleichen Datei zwar nicht so platzsparend wie „erste Version plus Diff“ oder „letzte Version plus Reverse-Diff“ auf der Platte, aber dafür in einem Zustand, bei dem sich jeder Versionsstand mit Bordmitteln wie cp oder eben rsync schnell auf jede beliebige andere Hardware bringen lässt. Der Charme besteht eben nicht in Features, sondern manchmal schlicht im Weglassen selbiger.

So, die letzten Dateien laufen durch. In der Xen-Konfiguration ist bereits die disk-Zeile auf das neue Blockdevice angepasst. rsync fertig, umount, xm create -c. Bootet.

Die Maschine läuft nun also wieder, zwar mit einem Stand von gestern Nacht, aber eine bessere Option gibt es nun mal nicht. Downtime: Von 07:12 Uhr bis 11:01 Uhr – fast vier Stunden, was die Verfügbarkeit im Jahresmittel auf ärgerliche 99,95% herunterkatapultiert (wobei nur etwa eine halbe Stunde auf tatsächliche administrative Arbeiten entfällt – der Rest hingegen auf den Restore der Daten; man sollte also bei einem Backup nicht unterschätzen, dass auch ein Restore eine signifikante Downtime bedeuten kann). Aber der (ziemlich branchenspezifische) Shop wird nachts kaum besucht, am Wochenende noch weniger, von daher hält sich der potentielle Schaden wohl hoffentlich in Grenzen. Dass ein solcher Vorfall nun ausgerechnet bei einem System auftritt, wo sowohl die physischen Maschinen „vorne“ redundant ausgelegt sind als auch der Storage-Cluster „hinten“, ärgert mich um so mehr, aber es ist ein gutes Beispiel dafür, dass Hochverfügbarkeit durch Failover-Cluster auch nur eine Teilmenge möglicher Störungen absichert – und derart tiefgreifende Schäden an Dateisystemen und Partitionstabelle gehören nicht dazu. Die Lehren, die ggf. aus diesem Vorfall zu ziehen sind, werden wir dann am Montag im Teammeeting besprechen.

Also Leute, macht Backups. Gute Backups. Und vor allem vollständige Backups: Seid nicht zu selektiv – kopiert lieber zuviel als zuwenig, auch wenn man im Moment leider immer noch nicht wieder „Plattenplatz kostet doch eh fast nichts“ sagen kann. Und schaut gelegentlich, dass eure Backups auch funktionieren. Ihr wisst nie, wann sie euch mal den Allerwertesten retten.

So, jetzt erstmal Kaffee.

iowait – Ein Lehrstück

Sonntag, 16. Januar 2011

Wir betreiben seit längerer Zeit einen Storagecluster, auf dessen Basis wir sowohl dedizierte als auch virtuelle Server laufen lassen. Technisch läuft das so, dass die betreffenden Server ohne lokale Festplatten über PXE booten, mit Hilfe von gPXE (früher etherboot) dann per iSCSI ihre Root-Partition vom Storagecluster beziehen und das betreffende System booten. Das läuft 1a und sorgt für eine deutlich bessere Ressourcenausnutzung verglichen mit Failover-Clustern, bei denen pro produktivem Server ein Gerät als Spare daneben steht: Nur der Storagecluster muss redundant sein – die eigentliche Serverhardware nicht, beziehungsweise: Es reicht, für eine ganze Gruppe von Servern nur wenige Ersatzgeräte bereitzuhalten, denn wenn eine Hardware physisch ausfällt, kann man das zentral auf dem Storage liegende System problemlos auf beliebiger neuer Hardware booten lassen.

Allerdings kann einem das auch ziemlich auf den Fuß fallen, und zwar, weil sich „Performance“ in Sachen Datenübertragung primär in zwei Faktoren ausdrückt: Dem Durchsatz einerseits; der Latenz andererseits. In der Theorie war uns das allen bekannt, aber das plastischste Beispiel dafür haben wir erst im Zusammenhang mit dem Storagecluster gefunden – leider erst im produktiven Betrieb, wie es nun so ist. Insofern ist es auch ein Beispiel dafür, dass auch wir im Laufe unserer Arbeit noch so einiges dazulernen, und manches davon durchaus nicht im stillen Kämmerlein, sondern weil’s gerade brennt.

Um einen kurzen Exkurs für diejenigen zu machen, die mit Latenz und Durchsatz nicht viel anfangen können:

Man stelle sich eine vierspurige Autobahn vor. Es gibt keine Geschwindigkeitsbegrenzung. Die Autobahn kann also im Prinzip auch von Raketenautos befahren werden, und da sie vier Spuren hat, können sogar vier Raketenautos gleichzeitig darauf fahren. Oder auch ein paar mehr. Nur dann, wenn’s richtig viele werden – dann gibt es Stau. Die Latenz ist gering (man kann rasen), aber die Bandbreite begrenzt (nur vier Spuren).

Umgekehrt: Eine kilometerbreite Schotterstrecke. Selbst Raketenautos können hier nur 50 km/h fahren. Aber dafür können hier hunderte Autos in diesem Tempo nebeneinanderfahren – ohne dass es Stau gibt. Es gibt hohe Latenzen (die Straße ist schlecht), aber viel Durchsatz (sehr breite Straße).

Hat man nun mit einem übers Netzwerk erreichbaren Storage zu tun, so spielen hier zwei Komponenten eine Rolle: Einerseits die Netzwerkkarte; andererseits das Plattensystem, also die Kombination aus RAID-Controller und physischen Festplatten. Dass auf der Netzwerkebene manchmal nicht nur nur die Bandbreite („Ich hab DSL Soundsovieltausend!“), sondern auch die Latenz eine Rolle spielen kann, weiß jeder, der viel online zockt und hier gerne besonders schnelle Ping-Zeiten hätte – und dann für eine FastPath-Option von seinem DSL-Provider oft mit einem kleinen Aufpreis zur Kasse gebeten wird. Ganz klar: Will ich schnell vorankommen, spielt – bei leerer Straße – keine Rolle, ob mir zwei oder hundert Spuren zur Verfügung stehen, sondern die Straße muss eben gut ausgebaut und nicht nur geschottert sein.

Netzwerkkarten sind Paradebeispiele für Geräte, die äußerst niedrige Latenzen aufweisen (die Latenzen, die man sich mit FastPath beim DSL wegkaufen muss, entstehen erst an anderer Stelle). Die Bandbreite steht auf der Packung: 100 MBit/s (Fast Ethernet) oder 1000 MBit/s (Gigabit Ethernet) sind hier gängige Größen. Gigabit Ethernet heißt: Es können 1000 MBit pro Sekunde übertragen werden, also etwa 128 MB. Eine konventionelle Serial-ATA-Festplatte überträgt demgegenüber 300 MB pro Sekunde – also mehr als doppelt soviel. Aber dafür ist eine Festplatte ein Gerät, wo sich erstmal physisch irgendwelche Teile drehen, ein Schreib-/Lesekopf sich bewegen muss … und das heißt: Es gibt Latenzen. Die Zugriffsgeschwindigkeit „normaler“ Festplatten liegt heute so um die 10ms – was zwar schnell klingt, aber bei einer Netzwerkverbindung liegt die Latenz bei weit unter 1ms, ist also um eine satte Größenordnung kleiner.

Beim Einsatz von netzwerkbasiertem Storage könnte man also zunächst meinen, dass dann hier die schlechte Zugriffsgeschwindigkeit von Festplatten die geringe Latenz der Netzwerkkarte schnell vergessen lässt, und dass die ach so schicke Bandbreite einer Festplatte keine Chance hat, weil die Daten ja zuvor erst noch durch eine Netzwerkkarte gequetscht werden müssen, die deutlich weniger Bandbreite hat. Von beidem also das Schlechteste? Nein, nicht ganz. Denn zum einen verteilt der RAID-Controller im Storage die Zugriffe auf viele Festplatten, was deren hohe Latenz entschärft. Zum zweiten muss darauf sowieso nicht gewartet werden, denn der RAID-Controller besitzt einen eingebauten batteriegepufferten Cache, und es reicht, wenn sich zu schreibende Daten dort befinden. Physisch auf Festplatten schreiben kann der RAID-Controller die Daten auch später.

Insofern: Latenzprobleme gibt’s bei diesem Aufbau eher weniger. Aber eben schmalere Bandbreite. Würde man das Setup auf lokale Festplatten umstellen, hätte man bessere – aber dann auch mehr Latenz. Gute Voraussetzungen also für ein Vom-Regen-in-die-Traufe-Problem. Und so sieht es aus:

iowait-Last-Beispiel

Der erste große Bereich bis zur senkrechten Linie 1 zeigt den Betrieb eines Servers im Storage-Cluster, also via iSCSI; die rote Kurve zeigt dabei vereinfacht gesagt, wieviel Prozent seiner Zeit der Server darauf gewartet hat, mit dem Plattensystem interagieren zu können. Hier ist deutlich erkennbar, dass diese Kurve zwar im Allgemeinen relativ niedrig ist, aber immer wieder hässliche Peaks hat – Peaks, in denen man ls -l eingibt und sich fragt: Was zur Hölle dauert hier so lange? Ein klares Zeichen für einen Engpass.

Die Linie 1 markiert nun den Moment, an dem wir den Server aus dem Storagecluster und auf ein baugleiches System mit lokalen Platten umgebaut haben. Kurz vorher zeigen zwei Peaks der roten Linie die zwei vorab durchgeführten Datensynchronisationen an; eine grobe am Abend und dann noch eine für die letzten Änderungen mitten in der Nacht.

Der Abschnitt zwischen 1 und 2 zeigt nun deutlich: Das war nicht nur vom Regen in die Traufe; das war vom Regen sogar bis in den Brunnen, ganz tief unten. Soll heißen: Obwohl die lokalen Festplatten eine wesentlich höhere Bandbreite haben, zieht ihre schlechtere Latenz das System noch viel massiver in den Keller. Auf der Haben-Seite steht, dass es im Grunde keine schlimmen Peaks mehr gibt. Umgekehrt muss zähneknirschend festgestellt werden, dass die Festplattenlast nun eigentlich einen einzigen durchgehenden Peak darstellt.

Wir haben während dieser Zeit bereits einen Replikationspartner aufgesetzt, der via DRBD den gesamten Datenbestand auf ein baugleiches System übertragen und aktuell gehalten hat – diesmal aber nicht auf ein RAID1, sondern auf ein RAID0. (Wem das nichts sagt: Beim RAID1 werden die Daten einer Festplatte 1:1 auf eine zweite gespielt. Beim RAID0 hingegen werden Schreibzugriffe auf beide Festplatten verteilt – finden also grob gesagt doppelt so schnell statt.)

Die Linie 2 zeigt nun den Zeitpunkt, an dem wir auf das andere Gerät – das mit dem RAID0 – umgeschaltet haben. Unmittelbar danach haben wir auf dem vorherigen Gerät das RAID1 ebenfalls durch ein RAID0 ersetzt und die Daten zurücksynchronisiert, was der Grund dafür ist, wieso die rote Kurve hier erstmal nicht signifikant runtergeht.

Aber dann: 6 Uhr morgens; Linie 3. Die Rück-Synchronisation ist abgeschlossen – und das System atmet förmlich auf. Es ist gut erkennbar, wie sämtliche Kurven den gesamten Freitag über keinerlei Peaks zeigen. Vor allem, wenn man das mit Montag, Dienstag und Mittwoch – also ebenfalls Werktagen – vergleicht, ist das ein massiver Fortschritt. Die Maschine ist nun effektiv rund um die Uhr zu 90% untätig, so wie es sein soll, um für plötzliche Lastspitzen, wenn mal wieder ein Kunde Fernsehwerbung schaltet, anständig gerüstet zu sein.

Gut erkennbar ist nebenbei der Peak, der mit 4 eingekringelt ist. Der lässt sich nicht vermeiden: So sieht das aus, wenn die tägliche Datensicherung einmal alle Daten auf dem Festplattensystem anschauen muss, um festzustellen, ob sie in die inkrementelle Sicherung neu übertragen werden müssen. Aber selbst dieser Peak ist, verglichen mit den Peaks an anderen Tagen zur gleichen Uhrzeit, fast schon zu vernachlässigen.

Wenn Switche zu smart sind

Donnerstag, 23. Dezember 2010

Die letzten zwei Tage waren schlimm. Der eigentliche Plan war, den beiden Knoten unseres größten Storage-Clusters (2 x 16 Festplatten im DRBD-Verbund) angesichts gestiegenen Datendurchsatzes zwei zusätzliche GBit-Netzwerkschnittstellen zu verpassen, um die Bandbreite für iSCSI zu erhöhen.

Der Einbau der zusätzlichen Netzwerkkarten verlief auch prima und von Kunden unbemerkt – da bei einem manuellen Failover des aktiven Knotens im Storagecluster die angeschlossenen Systeme maximal 5-10 Sekunden kurz bei Plattenzugriffen hängen, fällt nicht mal mitten am Tag ein solcher Failover auf.

Bei der Konfiguration der zusätzlichen Netzwerkschnittstellen hörte der Spaß dann leider auf. Das eingeplante Bonding ließ sich um’s Verplatzen nicht im laufenden Betrieb aktivieren; ein Netzwerk-Restart tat sowohl DRBD als auch Heartbeat alles anderes als gut; noch ein menschlicher Fauxpas dazu … und schon hatten wir alle Hände voll zu tun damit, um den gesamten Cluster wieder zu stabilisieren. Doch darum soll es hier nicht gehen. Im Lauf des heutigen Vormittags haben wir im Team unsere Pläne und unsere Erfahrungen vom Vortag durchgesprochen und uns schließlich dazu entschieden, anstelle von Bonding die zusätzliche Ports über einen zusätzlichen Switch laufen zu lassen und einige der besonders iSCSI-intensiven Knoten dann dorthin zu verlagern. Und damit fingen die Unwägbarkeiten dann erstmal so richtig an.

Alle angeschlossenen Hosts haben keine lokalen Festplatten. Sie booten via PXE direkt aus dem Cluster und bekommen via iSCSI ihre Root-Partition. Der PXE-Server befindet sich dabei mit je einer Schnittstelle an jedem Switch, kann also beide Netzbereiche bedienen.

Wir haben nicht schlecht gestaunt, als der PXE-Bootvorgang – der immer mit einem DHCP-Request beginnt – am einen Switch so problemlos läuft wie immer; versuchten wir es jedoch am anderen Switch, so dauerte es eine halbe Minute, bis per DHCP eine IP bezogen wurde. Über PXE wird dann gPXE (früher Etherboot) geladen, was dann auch iSCSI-fähig ist und das eigentliche System einbindet. Dafür macht es selbst auch noch einmal einen DHCP-Request – und der schlug (dank eines kürzeren Timeouts) schließlich ganz fehl. Der Server bootet nicht.

Nun hatten wir bereits via tcpdump herausgefunden: Die DHCPDISCOVER-Pakete kommen gar nicht erst am DHCP-Server an – erst nach besagter halber Minute. Ein Serverproblem ist von daher auszuschließen. Der DHCP-Request wird hier direkt von der Netzwerkkarte gestellt – ist also auch nichts, wo man einfach mal eben --verbose oder --debug angeben könnte. Sollte etwa … der Switch?

Problematisch ist immer, wenn man es nicht mit einem konkreten Programm oder einer konkreten Fehlermeldung zu tun hat. Wonach sollte man googlen? Switch? DHCP? Timeout? Alles Begriffe, die viel zu generisch sind, um (auch in Kombination) vernünftige Treffer zu liefern. Aber nach längerem Stöbern fanden sich in der Tat Beschreibungen wie

A little further analysis with other devices has determined that the SFE2000 simply is not passing every DHCP Discover request. It seems to work every 4th or 5th request, the others being dropped

Hat zwar nichts mit unserem Switch-Modell zu tun, aber ein Anhaltspunkt, dass ein Problem jener Art existiert. Jemand anders meldet:

dhcpcd not sending DHCPDISCOVER/-REQUEST at boot, timing out

in dessen Diskussionsverlauf schließlich ein vages

On a switched network I would be suspect of the switch just in case it is being clever somehow

zutage tritt. Und schließlich:

Checking with the comms gurus they said to check for a switch feature called „portfast“. Google finds quite a bit on it if you are not familiar with it already.

Klare Sache, „checking with the comms gurus“ werde ich ab sofort in meinen Sprachgebrauch mit aufnehmen, und „portfast“ hat sich als genau das richtige Stichwort herausgestellt – obwohl alle Beteiligten angaben, das würde nur Cisco- und HP-Switche betreffen, während wir einen 3com haben.

Fürs Protokoll: Es ist die Kommunikation aus eingeschalteten Spanning Tree Protocol und ausgeschaltetem Portfast. Nicht, dass wir das Spanning Tree Protocol benutzen würden oder wollten – es war einfach standardmäßig eingeschaltet. Und es sorgt dafür, dass beim Aktivieren des betreffenden Switchports zunächst eine Art „Lernphase“ einsetzt, bevor dann – etwa 30 Sekunden später – die ersten Pakete tatsächlich über den Port laufen können.

Aus genau diesem Grund kommen die DHCPDISCOVER-Requests auch erst so spät durch – und für gPXE sogar zu spät. Kaum dass wir Spanning Tree deaktiviert hatten, lief alles genauso fix wie am anderen Port. Durchatmen, weitermachen.

mkinitrd und Filesystem-Labels

Freitag, 09. Juli 2010

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.


Impressum