Zum Inhalt springen
Alle Artikel

Restore-Tests: Ein Backup, das nie wiederhergestellt wurde, ist nur eine Hoffnung

Die meisten Backup-Dashboards sind grün. Sie melden, dass ein Job lief und eine Datei geschrieben wurde, und das sagt nichts darüber, ob Sie aus dieser Datei Ihr Geschäft zurückbekommen, wie lange das dauert oder ob die Kopie einen Angreifer mit Admin-Rechten übersteht. Der einzige Beweis ist ein Restore. Auf den Plattformen, die ich betreibe, werden Backups alle paar Stunden ausserhalb des Hosting-Anbieters geschrieben und jede Nacht automatisch in einen isolierten Zwilling wiederhergestellt. So richtet man das ein.

9 Min. Lesezeit

1. Festlegen, was "wiederhergestellt" heisst

Zwei Zahlen pro System rahmen jede Backup-Entscheidung. Das Recovery Point Objective (RPO) ist, wie viele Daten Sie verlieren dürfen: Kommen den ganzen Tag Buchungen herein, können vier Stunden verlorene Buchungen schon zu viel sein. Das Recovery Time Objective (RTO) ist, wie lange das Geschäft warten kann, bis das System wieder läuft. Der Leitfaden des NIST zur Notfallplanung für IT-Systeme verwendet genau diese Begriffe, und es lohnt sich, sie mit dem Fachverantwortlichen aufzuschreiben, statt sie vom Plattform-Team schätzen zu lassen.

Das RPO bestimmt die Backup-Häufigkeit; das RTO bestimmt, wie schnell ein Restore sein muss, und wird weiter unten zur Schwelle, an der Ihr nächtlicher Test gemessen wird.

2. Backups ausser Reichweite bringen

Ein Backup im selben Konto, mit denselben Admin-Zugängen, fällt mit dem System, das es schützen soll: Ein Ausfall des Anbieters, ein gelöschtes Abonnement oder ein Angreifer mit der Admin-Rolle nimmt beides mit. Also das Backup verschlüsseln, bevor es das System verlässt, es in einen Speicher ausserhalb des Hosting-Anbieters oder zumindest ausserhalb des Kontos schreiben und es unveränderlich machen. Der unveränderliche Tresor von Azure Backup verhindert, dass Wiederherstellungspunkte vor ihrem Ablauf gelöscht werden, und Amazon S3 Object Lock speichert Objekte nach dem Prinzip write once, read many mit einer Aufbewahrungsfrist.

Dem Backup-Job Zugangsdaten geben, die schreiben, aber nicht löschen dürfen. Auf einer Plattform, die ich betreibe, wird sogar der Audit-Trail so geschrieben: S3 Object Lock, 90 Tage aufbewahrt, mit reinen Schreib-Zugängen, damit eine kompromittierte Anwendung Einträge hinzufügen, aber nie entfernen kann.

Tipp aus der Praxis

Mindestens eine Kopie bei einem anderen Anbieter oder in einer anderen Region und mit anderen Zugangsdaten halten. Zwei Kopien hinter demselben Passwort sind eine Kopie.

Backups ausser Reichweite, jede Nacht in einen isolierten Zwilling wiederhergestellt, geprüft, gemessen, und bei einem Fehler wird eine Person alarmiert.
Architektur für Restore-Tests: Die Produktion mit Anwendung und PostgreSQL-Datenbank schreibt alle paar Stunden verschlüsselte Backups in einen unveränderlichen Speicher ausserhalb des Anbieters, mit einer zweiten Kopie in einer anderen Region oder bei einem anderen Anbieter; jede Nacht legt ein Restore-Job in einem isolierten Zwilling eine frische Datenbank an, prüft Zeilenzahlen, Prüfsummen und einen Smoke-Test der Anwendung, misst die Dauer am RTO und alarmiert eine Person, wenn eine Prüfung scheitert.

3. Jede Nacht in einen isolierten Zwilling wiederherstellen

Den Restore zu einem geplanten Job machen, nicht zu einer Notfallprozedur. Jede Nacht nimmt er das neuste Backup, legt in einer isolierten Umgebung ohne Netzwerkweg zur Produktion eine frische Datenbank an und stellt dort wieder her. Isolation zählt doppelt: Ein Test darf nie Live-Daten berühren, und eine wiederhergestellte Kopie enthält dieselben Personendaten wie die Produktion, bekommt also denselben Schutz und wird nach den Prüfungen gelöscht.

Die Werkzeuge gibt es auf jeder Plattform. AWS Backup hat Restore Testing, das Restore-Jobs nach Zeitplan ausführt und ihre Dauer erfasst. Auf Kubernetes kann CloudNativePG einen neuen PostgreSQL-Cluster aus einem Backup aufbauen. Ein einfaches Skript mit pg_restore in eine Wegwerf-Datenbank funktioniert überall und lässt sich um drei Uhr morgens gut lesen.

bash
#!/usr/bin/env bash
# Nightly restore test: latest backup -> fresh database in the isolated twin -> checks
set -euo pipefail
LATEST=$(ls -1 /backups/db/*.dump.gpg | sort | tail -1)   # synced from the off-site store
gpg --batch --decrypt --output /tmp/latest.dump "$LATEST"

START=$(date +%s)
dropdb --if-exists -h restore-twin restore_check
createdb -h restore-twin restore_check
pg_restore -h restore-twin -d restore_check --no-owner --jobs 4 /tmp/latest.dump
echo "restore_seconds $(( $(date +%s) - START ))"            # compare with the RTO

psql -h restore-twin -d restore_check -v ON_ERROR_STOP=1 -f checks.sql
rm -f /tmp/latest.dump

4. Die Daten prüfen, nicht den Exit-Code

Ein Restore kann ohne Fehler durchlaufen und trotzdem nutzlos sein: eine Tabelle, die nie im Backup war, ein abgeschnittener Dump, eine Kopie, die drei Tage alt ist, weil der Backup-Job still gescheitert ist. Also das Ergebnis mit der Produktion vergleichen. Exakte Zeilenzahlen der wichtigen Tabellen gegen ein Produktions-Replica, eine Prüfsumme über die Zeilen der Tabellen, auf die es ankommt, so sortiert, dass die physische Anordnung das Ergebnis nicht verändert, und der neuste Zeitstempel, der innerhalb des RPO liegen muss.

Dieselben Prüfungen machen auch Migrationen sicher. Als ich Mandanten-Datenbanken mit CloudNativePG in einen Kubernetes-Cluster umgezogen habe, mussten Zeilenzahlen und Prüfsummen identisch sein, bevor irgendetwas umgeschaltet wurde, und sie waren es.

sql
-- checks.sql: run the same queries on a production replica and compare
-- 1. Exact row counts of the key tables
SELECT 'bookings' AS tbl, count(*) FROM bookings
UNION ALL SELECT 'payments', count(*) FROM payments
UNION ALL SELECT 'customers', count(*) FROM customers;

-- 2. Checksum independent of physical row order
SELECT md5(string_agg(b::text, '|' ORDER BY b.id)) AS bookings_checksum
FROM bookings b WHERE b.created_at < date_trunc('day', now());

-- 3. Freshness: the newest row must be inside the RPO
SELECT now() - max(created_at) AS data_age FROM bookings;

Tipp aus der Praxis

Die Prüfsumme nur über Zeilen bilden, die älter sind als der Start des Backups, wie im Beispiel. Sonst lässt jede neue Buchung in der Produktion den Vergleich aus dem falschen Grund scheitern.

5. Die Anwendung gegen den Restore laufen lassen

Daten, die richtig aussehen, können trotzdem unbrauchbar sein: eine Datenbank-Erweiterung, die im Restore-Ziel fehlt, Rollen und Berechtigungen, die der Dump nicht mitgenommen hat, Secrets, die nur in der Produktion existieren. Ein kurzer Smoke-Test findet das: die Anwendung gegen die wiederhergestellte Datenbank starten und sie einloggen, einen Datensatz lesen und einen schreiben lassen. Klappt das, haben Sie ein System zurück, nicht nur einen Satz Tabellen.

Den Smoke-Test klein und deterministisch halten. Er ist keine vollständige Test-Suite; er beantwortet jeden Morgen eine Frage: Könnten wir das Geschäft mit dem Backup von letzter Nacht betreiben?

6. Die Restore-Dauer am RTO messen

Datenbanken wachsen, und mit ihnen die Zeit, um sie zurückzuholen. Ein Restore, der letztes Jahr zwanzig Minuten dauerte, braucht jetzt vielleicht zwei Stunden, und niemand merkt es bis zu dem Tag, an dem es darauf ankommt. Die Dauer jedes nächtlichen Restores festhalten, vom Start des Downloads bis zum bestandenen Smoke-Test, und sie neben dem RTO darstellen.

Nähert sich die Linie dem Ziel, handeln, bevor ein Vorfall es tut: parallele Restore-Jobs, eine schnellere Speicherklasse für den Zwilling, eine andere Backup-Methode für die grössten Tabellen oder ein ehrliches Gespräch über ein längeres RTO.

7. Bei gescheiterten Restores alarmieren und mit Menschen üben

Die meisten Monitorings alarmieren, wenn ein Backup-Job scheitert. Auch dann alarmieren, wenn ein Restore scheitert: Eine fehlgeschlagene Prüfung, ein nicht bestandener Smoke-Test oder eine Dauer über dem RTO weckt morgens eine Person, in einem Kanal, den jemand liest. Ein Backup, das sich nicht wiederherstellen lässt, ist ein Ausfall, den Sie nur noch nicht hatten.

Automatisierung beweist die Daten, nicht die Menschen. Einmal pro Quartal einen Restore mit dem Team anhand des Runbooks durchspielen, inklusive wer entscheidet, wer kommuniziert und wo die Zugangsdaten liegen. Die Checkliste unten führt das unter den Grundlagen, die eine Plattform braucht, bevor sie sich produktionsreif nennt.

Interaktiv

Ist Ihre KI-gebaute App bereit für Produktion?

Haken Sie ab, was schon stimmt. Was übrig bleibt, ist Ihre To-do-Liste, in Reihenfolge.

0/12 bereit

Ihre nächsten drei Schritte

  1. Code liegt in Git, Änderungen laufen über Pull Requests
  2. Keine geheimen Keys im Frontend, Server-Keys nur auf dem Server
  3. Row-Level-Security (oder Gleichwertiges) auf jeder Tabelle
Production-Readiness-Review anfragen
Alle Rechner und Checklisten

Fazit

Backups sind ein Versprechen, Restores der Beweis. Jede Nacht wiederherstellen, Daten und Anwendung prüfen, die Dauer am RTO messen und einen gescheiterten Restore jemanden wecken lassen.

Weitere Artikel

    Kontakt aufnehmen

    Erzählen Sie mir von Ihrem Projekt, ich antworte innerhalb von 1–2 Werktagen.

    Dominik Heinrich
    Unternehmen
    MADO Consulting

    Weltweit verfügbar, remote. Vor Ort auf Anfrage, je nach Land.

    Ich antworte innerhalb von 1–2 Werktagen. Freie Termine: siehe Kalender

    Öffnet hier den Buchungskalender von Calendly. Beim Laden werden Daten an Calendly übertragen (siehe Impressum).