Bash-Archivverwaltung
Eines schönen Tages beschloss meine Abteilung, Daten, die für längere Zeit sicher gelagert werden mussten, nicht mehr auf Festplatten im Safe abzulegen. Sicher, Festplatten sind verhältnismäßig günsig, recht schnell zu beschreiben und einfach zu handhaben, gerade wenn man forensische Kopien direkt als Image darauf ablegt. Doch alleine die Verwaltung wurde mit den Jahren immer komplexer, Löschfristen mussten beachtet werden und allgemein artete das Ganze mehr und mehr in überflüssige Rennerei aus. Die Lösung: Tape-Archivierung!
Nun mag sich manch einer denken: “Sichern auf Band? Das ist doch uralte, fast schon vergessene Technologie!”
Ich würde mal sagen: Falsch gedacht! Zwar mutet das Beschreiben von Bändern archaisch an, man denkt an riesige drehende Bandspulen in zimmergroßen Computern, die man vielleicht mal in alten Science Fiction-Filmen gesehen hat, oder sie - den entsprechenden Jahrgang vorausgesetzt - sogar noch selber erleben durfte. Moderne Bandlaufwerke haben damit jedoch nur noch wenig zu tun.
Moderne LTO-Laufwerke können (Stand Ende 2024) unkomprimiert mit dem Standard LTO9 bis zu 18TB auf ein handtellergroßes Tape schreiben. Mit Komprimierung schaffen sie laut Herstellerangaben sogar bis zu knapp über 40GB, doch das dürfte je nach Art der Quelldaten stark fluktuieren. 18TB pro Band, das ist doch schon mal ordentlich und entspricht etwa dem, was moderne Festplatten auch fassen. Und auch die Schreibgeschwindigkeit von bis zu 400MB/s liegt mitten in dem Spektrum, das handelsübliche Festplatten via SATA schaffen. Der Preisunterschied ist hingegen saftig: Während ein LTO9-Tape nur knapp 100€ kostet, schlagen Festplatten mit ähnlicher Speicherdichte mit dem zwei- bis vierfachen Preis zu Buche.
Gerade beim Preis muss man allerdings die Initialkosten bedenken, und die haben es in sich: Während SATA-Anschlüsse für Festplatten heutzutage nahezu überall verbaut sind, braucht es für die Verwendung von LTO-Tapes ein spezielles Laufwerk, das mit mehreren tausend Euro nicht gerade ein Schnäppchen ist. Geräte, die die Bänder selbstständig wechseln können, liegen preislich noch einmal eine Größenordnung darüber.
Datenarchivierung auf Tape, nur wie?
Für Datenarchivierung bieten sich dennoch am ehesten Tapes an. Sie sind für das sequenzielle Schreiben von großen Datenmengen entwickelt worden, also genau das, was bei einer Archivierung passiert. Also schafften wir uns nach reichlicher Recherche einen 24fach-Bandroboter an, um uns die ständige händische Archivierung zu erleichtern.
Nun verhält sich so ein Tape etwas anders als eine Festplatte. Zuallererst: Es gibt kein Dateisystem. Okay, das ist gelogen, man kann auch auf dem Tape ein Dateisystem nutzen, über das man fast ganz normal hantieren kann. Für unseren Zweck war das allerdings absolut nicht sinnvoll, denn wir wollten ja einfach nur Daten archivieren - ein nachträgliches Ändern war nicht vorgesehen.
Geschrieben wird so ein Band entweder mit einer kommerziellen Software, die das Laufwerk direkt ansteuert, eine eigene Bandverwaltung mitbringt und meist über eine graphische Oberfläche verhältnismäßg komfortabel zu bedienen ist. Kontrapunkt: Sie ist recht starr in ihren Möglichkeiten und lässt sich nur schwer oder gar nicht an unsere Anforderungen und Datenstrukturen anpassen. Außerdem benötigt sie häufig ein bestimmtes Betriebssystem, Updates müssen regelmäßig eingespielt werden, und wenn etwas nicht funktioniert, ist es unklar, ob der Hersteller schnell eine Anpassung im Code vornehmen kann oder will. Zudem sind die Lizenzen oft mit hohen laufenden Kosten verbunden.
Option zwei war für uns: Wir versuchen es mit Linux-Bordmitteln und ein wenig Scripting. Kann ja so schwer nicht sein, mittels mt
und mtx
lassen sich Tapelaufwerk und Wechselautomatik ansteuern, mit tar
Daten schreiben und das Bisschen Logik drum herum kann ja so schlimm nicht sein… Und so begann meine mehrmonatige Odyssee in die Tiefen der Tape-Archivierung.
Wie viel Toolset darf’s denn sein?
Mein Plan war, die verwendeten Tools auf ein absolutes Minimum zu beschränken. Ich wollte keine großen Abhängigkeitsbäume, das System sollte möglichst schlank bleiben und somit leicht zu warten sein. Das Aufsetzen des verwendeten Servers sollte innerhalb weniger Minuten machbar sein und die Verwendung verschiedener Linux-Distributionen als Basissystem kein Hindernis darstellen. Auch wollte ich verhindern, dass Updates in der Umgebung das Verhalten der verwendeten Tools verändern. Die erste Idee, das Ganze in Python, Go, Rust oder anderen Sprachen zu entwickeln, war damit schnell vom Tisch.
Und eigentlich sollte das Ganze ja auch relativ straight forward sein, oder? Daten auswählen (manuell oder automatisch), Metadaten auslesen oder generieren, Datensatz wegschreiben und zur Liste der geschriebenen Datensätze hinzufügen, um sie später wiederzufinden. Alles ganz easy, das schafft man mit Bash doch spielend.
Hör auf, die Bash zu bashen!
Wer jetzt beginnt, hysterisch zu kichern: Zu recht!
Die ersten Versuche sahen zwar recht vielversprechend aus, jedoch stellte sich schnell heraus, dass simple lineare Datenstrukturen wie Logdateien nur bedingt geeignet waren, die volle Komplexität abzubilden, die wir benötigten. Datensätze, die auf mehreren Tapes übergreifend lagen, konnten damit nicht sauber abgebildet werden, ohne ein ganzes Auswertungs-Framework schreiben zu müssen, das zudem fehleranfällig sein würde. Wie konnte ich gleiczeitig die Tape-Identifizierungsmerkmale und die geschriebenen Datensätze erfassen? Und überhaupt, das Ganze sollte im Zweifel auch noch händisch auslesbar und verwertbar sein.
Als Datenstruktur musste schließlich JSON herhalten, das sich relativ komfortabel mit jq
lesen und schreiben lässt. Allerdings bedeutete die Umstellung zum einen eine steile Lernkurve für mich (ich hatte vorher nur nach Anleitung mit jq
in bekannten Datenstrukturen hantiert), zum anderen musste das bisherige Script so umfassend angepasst werden, dass ich es kurzerhand neu schrieb.
Nach einigen Wochen hatte ich alle Strukturen, Funktionen und Abläufe so sauber definiert, dass das erste Tape aus dem Tray in den Leser geladen werden konnte und einige Testdaten auch darauf landeten. Yay! Doch dann: Verflixt, wie schreibt man nun Daten auf mehrere Tapes und trackt das sauber im Hauptscript? Den Tapewechsel kann man mit einigen Hilfsfunktionen durchaus automatisieren, doch beim Tapewechsel will man ja nicht permanent daneben stehen müssen (18TB zu schreiben dauert gut einen halben Tag) und dann per Hand den erfolgten Wechsel bestätigen. tar
kann für diesen Zweck zwar ein Helper-Script aufrufen, das den Wechsel übernimmt, doch die Kommunikation zwischen den beiden Scripten ist eher einseitig. Es gab also zwei Möglichkeiten: Das Hauptscript übergab eine Liste der vorhandenen Bänder an das Hilfsscript und dieses iterierte sich durch, oder das Hilfsscript schrieb sein aktuelles Tape in eine temporäre Datei, die nach dem Schreiben des Datensatzes vom Hauptscript wieder eingelesen wurde. Ich entschied mich für die erste Variante, die nach langem Hin und Her auch funktionierte.
Zeitgleich musste natürlich auch ein Restore-Script her, das die Datensätze, die das Archivscript generierte, wieder einlesen und daraus die für spezifische Fälle benötigten Tapes herausfischte. Da jeder Datensatz zweimal geschrieben wird, um auch bei den Archiven Redundanz zu schaffen, war es notwendig, auch gemischte Tapes als Input zu akzeptieren. Also wurden die Datenstrukturen wieder angepasst und das Restore-Script so ausgestattet, dass es jeweils Tapes vom primären und vom sekundären Archivlauf untereinander austauschbar akzeptierte. Sollte eins der Bänder beschädigt sein, legte man einfach das Band der anderen Sicherung mit demselben Index ein. Problem gelöst.
Der Weg zum Release
Inzwischen ist der Quellcode der drei Scripte zusammen auf über 1300 Zeilen angewachsen. Außerdem existieren noch einige Helfer-Scripte, die beispielsweise neue Bänder laden, frische Bänder initialisieren, bestehende Bänder löschen, und so weiter. Derzeit müssen die Quelldaten noch verschlüsselt vorliegen und auf Band geschrieben werden, für die fertige Version 1.0 der Scripte fehlt also noch eine Inline-Verschlüsselung des Datenstroms beim Schreiben. Vermutlich kann man das komfortabel mit PGP/GPG lösen, das steht noch als letzter Punkt vor dem Release auf dem Plan.
Ich habe ein Monster geschaffen, und es lebt. Eine handgeschmiedete und zu 100% an unsere Anforderungen angepasste Archivlösung, die mit einem Dutzend Standard-Tools auskommt, sehr geringe Anforderungen an Hardware, das verwendete Betriebssystem und kaum Abhängigkeiten hat, zudem wartbar und bis auf die Entwicklungszeit kostenlos nutzbar ist. Zukunftssicher sollte sie auch sein, der Wechsel auf ein möglicherweise kommendes LTO10 oder anderweitige Tape-Technologien erfordert höchstens die Änderung weniger Zeilen - wenn überhaupt.
Würde ich so eine Software noch einmal selber schreiben, anstatt sie zu kaufen? Kommt drauf an, wenn Standardsoftware die wichtigsten Anforderungen erfüllen kann vermutlich nicht. Doch wenn es keine brauchbare Software am Markt gibt, die unseren speziellen Bedürfnissen gerecht wird: Auf jeden Fall!
Würde ich noch einmal Bash verwenden? Möglicherweise. Ich habe während der Entwicklung unglaublich viel über Bash gelernt. Sicher, moderne Scriptsprachen bieten viele Erleichterungen für Entwickler, erhöhen aber gleichzeitig auch den Abhängigkeitsbaum der Software. Und es braucht nur eine einzige Funktion, die irgendwann während eines neuen Releases verändert wird, und das Script läuft nicht mehr. Auf einem derart wichtigen Kernsystem wie dem Archivserver möchte ich solche Risiken nicht eingehen.