Artikel mit ‘backup’ 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.

Synology-Netzwerksicherung: Doppel-FAIL

Freitag, 13. November 2009

Synology baut nette kleine NAS-Boxen für Daheim oder fürs Büro. Die laufen mit Linux, haben ein Webinterface drauf, damit man nicht mit der Shell in Berührung kommen muss, und sind von daher auch bei Einsteigern sehr beliebt.

Nun gibt es hier und da Bedarf, den Datenbestand der Syno an einem externen Ort zu sichern, und wie das nun mal so ist, bietet sich da Speicherplatz im Internet an. Die Syno unterstützt praktischerweise laut Dokumentation Backups auf „rsync-kompatible Server“. Nun kenne ich zugegebenermaßen keine Serversoftware, die „rsync-kompatibel“ wäre außer eben rsync selbst, aber was soll’s, rsync ist ja prima und macht seinen Job.

Die Syno möchte allerdings, dass man rsync als Daemon betreibt, und man muss bei der Einrichtung des Backup-Profils ein Modul benennen, das man in der rsyncd.conf angelegt hat. Nun muss ich zugeben, dass ich rsync noch nie als eigenständigen Daemon habe laufen lassen, und zwar schon aus einem Grund: Die Verbindungen sind unverschlüsselt. Lediglich die Zugangsdaten werden rudimentär verschlüsselt; so rudimentär, dass selbst die man page sagt, das sei „fairly weak“. Die übertragenen Daten selbst werden überhaupt nicht verschlüsselt. Von daher taugt diese Variante maximal für lokale Netze, und für die Übertragung via Internet hat sich eingebürgert, rsync über SSH laufen zu lassen. Dabei läuft serverseitig dann gar kein rsync-Daemon, sondern es wird aus der SSH-Verbindung heraus ein Quasi-rsync-Daemon für diesen User gestartet, der dann auch nicht die /etc/rsync.conf benutzt, sondern die ~/rsync.conf – falls vorhanden. Mit dem Ende der SSH-Verbindung wird auch der Quasi-rsync-Daemon wieder beendet. Sehr aufgeräumt, und kommt ohne root-Rechte aus.

Ich hätte auf die Dokumentation achten sollen, die ganz klein in der Liste der benutzten Ports verrät, dass die verschlüsselte Netzwerksicherung nicht nur Port 22, sondern auch Port 873 – den Standardport für den unverschlüsselt laufenden rsync-Daemon – benötigt. Das erschien mir völlig unlogisch, aber es stimmt: Ohne einen rsync-Daemon geht es einfach nicht. Nun wollte ich natürlich vermeiden, dass über die unverschlüsselte Verbindung die Zugangsdaten verschickt werden, und habe mir deshalb mittels tcpdump angesehen, was die Syno da eigentlich macht. Ergebnis: Sie checkt mittels der list-Funktion von rsync, ob das ausgewählte Modul vorhanden ist. Ergo habe ich mir überlegt: Dann packe ich doch einfach die reale Konfiguration des Backup-Moduls in ~/rsync.conf, und in die /etc/rsync.conf packe ich ein Modul gleichen Namens (damit der Wizard befriedigt ist), aber mit /var/empty/rsyncd als Pfad, read-only, und vor allem: ohne irgendwelche Zugangsdaten anzufordern. Mit Erfolg: Die Dyno schaut, ob’s das Modul gibt, ist zufrieden, und macht dann alles weitere per SSH. Die Gegenprobe lässt mir einen Schauer über den Rücken laufen: Fordert man in der /etc/rsyncd.conf Zugangsdaten an, schickt die Syno sie bereitwillig rüber, über die unverschlüsselte Verbindung auf Port 873, obwohl man im Webinterface Verschlüsselung aktiviert hat. Sowas geht einfach gar nicht. Betrug am User. FAIL #1.

(Apropos: Im deutschsprachigen Webinterface der Syno heißt die fragliche Option „Verschlüsselung von Sicherungskopien aktivieren“. Hand aufs Herz, für mich klingt das weniger nach einer verschlüsselten Verbindung, sondern vielmehr danach, dass die Dateien verschlüsselt würden – was nebenbei eine äußerst gute Idee wäre, wenn man diese bei einem fremden Provider unterbringen will, dem man nicht seine privaten Dateien zur gefälligen Unterhaltung nach Feierabend bereitstellen will. Leider ist dem nicht so. Es geht in Wirklichkeit nämlich doch um die Verbindung, und die Daten liegen auf dem Zielserver dann für den Provider lesbar.)

Nun ist dieser Part aber gemeistert: Die /etc/rsyncd.conf verlangt einfach kein Passwort mehr, die Syno ist glücklich damit und fabriziert das Backup dann auch tatsächlich über SSH. Damit ich es nicht vergesse: In der ~/rsyncd.conf muss man beim Modul zusätzlich zum Pfad noch einstellen:

use chroot = false
read only = false

chroot funktioniert nämlich nur, wenn rsync als Standalone-Daemon als root läuft, und read only ist standardmäßig true, was für einen Backup-Speicherplatz natürlich Unsinn ist – auf den will man ja gerade etwas schreiben können. Das mit dem fehlenden chroot ist zu verschmerzen, da ja die ganz normalen Unix-Berechtigungen dafür sorgen, dass der User nicht woanders reinkommt; da die User ohnehin Shell-Zugang per SSH haben, reißen wir uns hier somit auch keine größere Sicherheitslücke auf.

Nun ist nach dem Backup natürlich noch zu testen, wie es so mit dem Zurückspielen klappt. Also mal einen Testordner angelegt, ein paar Dateien hinein, Sicherung angelegt, alles prima. Nun ein Klick auf „Wiederherstellen“. Es öffnet sich ein Fenster mit einem Wizard. Lustigerweise muss ich sämtliche Daten noch einmal eingeben, was mich schon mal ein wenig erstaunt, denn die angelegten Profile definieren ja bereits, welchen lokalen Ordner man mit welchen Zugangsdaten auf welchen Server sichern will – da wäre es doch an sich am einfachsten, bei einem Restore einfach das gewünschte Profil zu wählen, denn dann hätte die Syno ja schon alle Angaben, um die Daten zurückzukopieren. Nun, ist aber offensichtlich nicht so: Bei einem Restore spielen die angelegten Profile einfach keine Rolle. Stattdessen fragt mich der Wizard auch hier wiederum nach Servername oder IP-Adresse, Backupmodul, Anwendername, Passwort und …

Und jetzt der Haken: Nichts „und …“. Es gibt beim Restore keine Möglichkeit, eine verschlüsselte Verbindung zu benutzen. Nein, ich habe nichts übersehen. Da ist einfach nichts. Keine Checkbox. Man kann also zwar Backups per rsync über SSH machen – aber man bekommt sie auf diesem Weg niemals wieder. Also, von Hand auf der Shell per SSH natürlich schon, klar, aber eben nicht über das Webinterface: Restores gehen einfach nur unverschlüsselt. Und da auf dem unverschlüsselten Port 873 ja nur mein Dummy-Modul hinterlegt ist, ist da natürlich nichts zu holen, denn auf dem SSH-Port versucht die Syno es gar nicht erst. FAIL #2.

Und das alles wegen der Verschlüsselung, als wenn der Wunsch nach vertraulicher Datenübermittlung nur etwas für Geheimagenten wäre. Ich gehe davon aus, würde ich rsync als Server laufen lassen, schön mit root-Rechten, alle Module zentral in /etc/rsyncd.conf erfassen und mir einfach keinen Kopf darum machen, dass meine Zugangsdaten dann leicht zu knacken und mein gesicherter Datenbestand gleich ganz unverschlüsselt durchs Internet übertragen würde … dann, ja dann wäre bestimmt alles ganz einfach.

Aber, Synology: Wir leben nicht mehr in den Neunzigern! Hier besteht wohl noch dringender Nachholbedarf.


Impressum