Zum Inhalt springen

Infrastruktur · · 7 Min. Lesezeit

Vom Backup zum Restore: Wie squibble Wiederherstellbarkeit betreibt

Unsere dreistufige Backup-Architektur im Betrieb: isolierte Pull-Backups, unveränderbare Offsite-Kopien, Restore-Tests und ehrliche Grenzen.

Drei Datenklassen teilen sich eine Plattform, aber nicht dieselben Regeln für Kopie, Retention und Wiederherstellung.

Im ersten Teil dieser Serie haben wir eine Backup-Architektur von ihrem Ergebnis her beschrieben: Sie muss einen brauchbaren Zustand wiederherstellen, obwohl Produktion, Zugangsdaten oder der Backup-Host selbst ausgefallen sind. Dieser Beitrag zeigt das konkrete System dahinter.

Es schützt Datenbanken, anwendungseigene Backup-Spools, versionierte Objekte, VM-Images und wachsende Medienarchive. Diese Daten landen auf derselben Plattform. Sie folgen dort bewusst nicht denselben Regeln.

Eine dedizierte VM zieht die Sicherungen aus den Quellsystemen. ZFS trennt die Datenklassen in eigene Datasets. Borg erzeugt verschlüsselte, deduplizierte Archive für operativen State. Restic überträgt diese Repositories zusätzlich in einen externen Object Store. Grosse VM-Sicherungen werden als Mirror geführt. Medienarchive wachsen nach dem Write-Once-Prinzip und erhalten SHA-256-Manifeste.

Das Ganze wird von Ansible beschrieben, von systemd geplant und über ausbleibende Heartbeats überwacht. Restore-Tests starten passende Datenbank-Container und prüfen mehr als den Exit-Code des Importwerkzeugs.

Die Backup-VM zieht, die Quellen liefern nur eng begrenzte Daten

Die VM bietet den Produktivsystemen keinen allgemeinen Backup-Endpunkt an. Sie verbindet sich selbst zu den Quellen und verwendet pro Datenquelle einen eigenen SSH-Schlüssel. Der jeweilige Public Key ist an einen Forced Command gebunden: Er darf einen bestimmten Dump erzeugen oder genau einen freigegebenen Pfad lesen. Eine freie Shell entsteht daraus nicht.

Das begrenzt zwei Richtungen des Schadens. Ein kompromittierter Applikationshost kann nicht mit seinen normalen Credentials durch die Repositories laufen. Ein kompromittierter Backup-Host erhält seinerseits keinen beliebigen administrativen Zugang zu allen Quellen.

Die Host Keys sind gepinnt. accept-new und ein automatisches ssh-keyscan würden die erste Verbindung ausgerechnet zu dem Moment machen, in dem die Identität noch nicht feststeht. Management- und Backup-Verkehr laufen über getrennte Netzpfade; auf dem Datenpfad lauscht kein Dienst.

Tier 1 schützt operativen State lokal und offsite

Tier 1 enthält die Daten, ohne die eine Anwendung nicht sinnvoll zurückkommt: MongoDB- und PostgreSQL-Dumps, kombinierte Datenbank-/Datei-Spools sowie versionierte Objekte aus Cloud Storage.

An der Quelle entsteht zuerst ein abgeschlossenes Backup-Artefakt. Für PostgreSQL kann das ein Custom-Format-Dump sein, für MongoDB ein authentifizierter Export, für eine Anwendung ein Spool mit Dump, Dateien und Prüfmetadaten. Der Object-Storage-Exporter lädt jede sichtbare Generation explizit und schreibt Inventare, Objektzahlen, Byte-Summen und SHA-256-Werte dazu.

Die Backup-VM übernimmt dieses Artefakt in ein eigenes Borg-Repository. Borg verschlüsselt mit repokey-blake2, komprimiert und dedupliziert über die Historie des jeweiligen Repositories. Jede Quelle bleibt separat, damit Checks, Retention und Fehler einer Anwendung die übrigen Repositories nicht mitziehen.

Die Repositories laufen append-only. Der tägliche Prozess darf neue Archive anlegen, aber keinen belegten Stand physisch entfernen. Der Prune-Pfad ist davon getrennt. Vor jeder Bereinigung entsteht ein ZFS-Snapshot, danach greift eine GFS-Retention mit kurzfristig dichten und langfristig ausgedünnten Recovery Points.

Ein täglicher Restic-Lauf mountet die Borg-Repositories und schreibt sie als eine verschlüsselte Snapshot-Menge in Backblaze B2. Der reguläre Cloud-Key besitzt keine Löschberechtigung. Für Prune existiert ein zweiter Key, der nur im separaten Wartungsjob verwendet wird. Default Retention und Object Lock werden beim Provisionieren geprüft, statt als Einstellung im Web-UI vorausgesetzt zu werden.

Damit liegen für Tier 1 zwei verschiedene Sicherungsformate in zwei Failure Domains vor: Borg auf dem lokalen ZFS-Pool und Restic im Object Store. Ein Restore aus B2 wird ohne den lokalen Borg-Cache getestet, weil jeder kürzere Pfad die falsche Kopie prüfen würde.

Tier 2 ist ein Mirror mit Rückrollfenster

VM-Backups haben ein anderes Profil. Sie bestehen aus wenigen grossen Dateien, ändern blockweise und werden bereits vom Virtualisierungs-Stack erzeugt. Ein zweites deduplizierendes Archiv um das erste Format würde vor allem Komplexität hinzufügen.

Tier 2 zieht deshalb die vorhandenen Proxmox-Sicherungen per rsync. Der Mirror darf Dateien entfernen, die gemäss Quell-Retention abgelaufen sind. --delete-before gibt Platz frei, bevor grosse neue Images geschrieben werden. Die Quell-Retention hält mehrere tägliche, wöchentliche und monatliche VM-Stände; der Mirror folgt ihr bewusst.

Das Recovery-Ziel ist hier die VM als Einheit. Die operative Datenbank liegt zusätzlich in Tier 1, denn ein VM-Image ist kein Ersatz für einen aktuellen, anwendungskonsistenten Dump.

Tier 3 löscht nicht

Bildarchive und originale Medien wachsen über lange Zeit. Ein Quellfehler soll sich bei ihnen nicht als Löschung fortpflanzen. Darum läuft Tier 3 mit derselben Pull-Richtung, aber ohne --delete.

Vor jeder Übertragung entsteht ein Snapshot. Für neu übertragene Dateien werden SHA-256-Werte berechnet und in ein bestehendes Manifest gemerged. Ein periodischer Volltest vergleicht Manifest und Dataset. Datei- und Byte-Zahlen dürfen unter normalen Bedingungen nicht schrumpfen.

Diese Form von Write Once Read Many, kurz WORM, hat einen Preis. Versehentlich kopierte Daten verschwinden nicht automatisch, und Kapazität muss über Jahre geplant werden. Genau deshalb besitzt der Pool Warn- und kritische Schwellen. «Nie löschen» ohne Kapazitätsmodell ist keine Retention, sondern ein zeitversetzter Ausfall.

SchutzklasseMechanismusLöschmodellVorgesehener Restore-Beweis
Tier 1: operativer StateBorg lokal plus Restic offsiteappend-only, separater Prune, Object Lockisolierter Datenbank- und Cloud-Restore
Tier 2: VM-Imagesrsync-Mirror auf ZFSQuell-Retention, Löschungen werden gespiegeltVM-Drill als eigener Freigabepunkt
Tier 3: Medienrsync ohne --deleteWORM plus SnapshotsManifest gegen Dataset und Stichprobe

Der Restore-Test prüft die Anwendung

Ein Backup-Archiv kann formal gesund und trotzdem unbrauchbar sein. Ein fehlender PostgreSQL-Role, eine falsche Major-Version oder ein unvollständiger Spool fällt bei einem Block-Checksum nicht auf.

Unsere Restore-Jobs extrahieren deshalb aktuelle Archive in ein kurzlebiges ZFS-Dataset und starten digest-gepinnte MongoDB- oder PostgreSQL-Container. Die Version folgt der jeweiligen Produktion. Danach prüfen anwendungsspezifische Gates Tabellen, Schemas, Rollen, Indizes, Row-Level-Security-Policies, Objektinventare und Sentinel-Dateien.

Für eine Anwendung mit PostgreSQL und Cloud Storage reicht es beispielsweise nicht, beide Archive einzeln zu lesen. Der Test begrenzt auch ihr Alter und den zeitlichen Abstand zwischen ihnen. Erst danach vergleicht er Objektzahl, Byte-Summe, Inventare und SHA-256-Werte. So wird aus zwei erfolgreichen Jobs ein gemeinsamer Recovery Point.

Jeder erfolgreiche Job sendet am Ende einen Push an Uptime Kuma. Bleibt er aus, läuft der Monitor nach dem erwarteten Intervall ab. Ein Startsignal wäre hier wertlos: systemd kann einen Restore pünktlich beginnen, der dreissig Minuten später in einen Timeout läuft.

Was die Live-Abnahme tatsächlich belegt

Am 4. September 2026 lief der Backup-Host als x86_64-VM unter KVM. ZFS meldete den Pool als gesund, mit 10,8 TB belegtem und 5,45 TB freiem Platz.

Zwei anwendungsspezifische Restore-Pfade waren im jeweils letzten Lauf grün:

  • Der Restore von Content Machine beendete Datenbankimport und Prüfungen erfolgreich.
  • Der kombinierte Twenty-Test stellte PostgreSQL und versionierte Cloud-Objekte wieder her und bestand seine Gates.

Die übrigen generischen und anwendungsspezifischen Restore-Jobs sind implementiert und werden automatisch ausgelöst. Ihr letzter gemessener Gesamtstand erfüllt unsere Freigabebedingung noch nicht. Darum bleibt ihr Status hier ausdrücklich offen. Die pauschale Aussage «restore-proven» verwenden wir erst, wenn die gesamte dafür behauptete Matrix einen aktuellen grünen Lauf besitzt.

Das ist kein Vorbehalt gegen die Architektur. Es ist ihre schärfste Anwendung. Monitoring soll verhindern, dass eine vorhandene Automation mit einer vorhandenen Wiederherstellbarkeit verwechselt wird.

Was der erste Entwurf falsch eingeschätzt hat

Der ursprüngliche Zeitplan hielt die Mirror-Jobs durch versetzte Startzeiten auseinander. Das funktionierte nur, solange jeder Lauf in sein vorgesehenes Fenster passte. Auf dem einzelnen HDD-vdev liefen ein Medien-Mirror nach 13 Stunden und ein zweiter nach 6,5 Stunden noch immer. Die Disk stand bei 98,24 Prozent Auslastung, als der nächste Job begann.

Weitere Abstände im Kalender hätten das Problem nicht gelöst. Die Laufzeit war länger als jeder vernünftige Abstand.

Heute serialisiert ein gemeinsames flock die grossen Mirrors. Wartende Jobs konkurrieren nicht mehr um denselben Spindelkopf. Nach zwölf Stunden endet die Warteschlange bewusst mit einem Fehler und lässt den Heartbeat aus. Ein Backlog, der jeden Tag weiter wächst, soll nicht grün aussehen.

Ein zweiter Fehler zeigte sich beim Entfernen alter Quellen. Ein Eintrag verschwand aus der Ansible-Liste, seine bereits installierte systemd-Unit blieb jedoch auf dem Host und feuerte weiter. Die Rolle führt deshalb heute ausgemusterte Quellen ausdrücklich und entfernt deren Skripte und Units, ohne ihre historischen Archive anzufassen. Das Löschen einer Quelle und das Löschen ihrer letzten Sicherung sind zwei verschiedene Entscheidungen.

Beide Korrekturen betreffen keinen exotischen Algorithmus. Sie betreffen Besitz: Der Scheduler muss die Konkurrenz um die Disk besitzen, und das gewünschte Inventar muss auch Abwesenheit beschreiben können.

Welche Grenzen bewusst offenbleiben

Der lokale ZFS-Pool besteht aus einem einzelnen vdev. Checksums erkennen beschädigte Blöcke, können sie ohne zweite Kopie aber nicht selbst reparieren. Für Tier 1 existiert deshalb die externe B2-Kopie. Tier 2 und Tier 3 besitzen diese Offsite-Abdeckung derzeit nicht vollständig.

Die Backup-VM und ein Teil des Quell-Storage teilen sich denselben Hypervisor. Die VM trennt Betriebssystem, Credentials und Netzpfade, aber keinen vollständigen Standortausfall. Ein defekter Compute-Host lässt sich ersetzen; ein gemeinsamer physischer Schaden bleibt eine akzeptierte Failure Domain.

Pull reduziert den Schreibzugriff aus der Produktion, konzentriert aber Leserechte auf der Backup-VM. Pro Quelle getrennte Schlüssel und Forced Commands verkleinern den Radius. Sie beseitigen ihn nicht.

Auch Object Lock ersetzt keine Schlüsselpflege. Ein verlorener Encryption-Key macht eine perfekte, unveränderbare Kopie ebenso unbrauchbar wie beschädigte Daten. Die exportierten Borg-Schlüssel und Passphrases müssen deshalb ausserhalb der Backup-Plattform wiederauffindbar bleiben.

Diese Grenzen stehen nicht im Kleingedruckten. Sie bestimmen, welche Kundendaten in welche Schutzklasse gehören und welches Leistungsversprechen daraus entstehen darf.

Was wir für andere Systeme wiederverwenden

Die konkrete Werkzeugkombination ist weniger wichtig als die Betriebsregeln dahinter:

  • Daten werden vor der Sicherung nach Wiederherstellungsziel klassifiziert.
  • Die Anwendung erzeugt den konsistenten Export.
  • Der tägliche Schreibpfad kann bestehende Recovery Points nicht frei löschen.
  • Prune, Retention und Object Lock besitzen getrennte Credentials.
  • Monitoring bewertet das Ausbleiben eines Erfolgs.
  • Ein Restore startet in einer isolierten, produktionsnahen Runtime und prüft fachliche Invarianten.
  • Offene Failure Domains werden dokumentiert und in RTO, RPO und Angebot eingerechnet.

Das ist die eigentliche Leistung eines Backup-Reviews. Wir zählen nicht zuerst Produkte und Terabytes. Wir verfolgen für jede wichtige Datenklasse den Weg von der Quelle bis zur restaurierten Anwendung und suchen die Stelle, an der eine Behauptung noch keinen Beleg hat.

Patrick Lehmann

Architecture & Governance Lead

Squibble GmbH

Bringt seit über zwanzig Jahren Struktur in gewachsene IT-Landschaften – als Architekt, Entwickler und Betreiber. Schreibt hier über die Systeme, die bei Squibble tatsächlich laufen, und über die Entscheide dahinter.