featured image Wer den Schaden hat...

26.11.2019 von Boris Schaa in Technology

Wer den Schaden hat...

Wie man mit Restic Daten wiederherstellen kann

Im ersten Teil dieser Artikelserie wurde beschrieben, wie leicht und schnell man Sicherungen im Kontext von Containern mit Restic herstellen kann. Die Sicherung von Daten stellt aber keinen Selbstzweck dar, sondern dient der Wiederherstellung von Daten, wenn das gesicherte System versagen sollte. Dieser Beitrag widmet sich genau diesem Aspekt, der im Falle von Docker ebenso simpel ist, wie die vorherige Sicherung. Schließlich wird zusätzlich noch auf das Entfernen von Sicherungen eingegangen, falls der Speicherplatz einmal knapp werden sollte.

In diesem Teil wird davon ausgegangen, dass Restic bereits installiert und Snapshots mit Restic gesichert wurden. Weitere Installationshinweise befinden sich im ersten Teil dieser Serie.

Restic-Kommandos in diesem Artikel

Für diesen Artikel sind insbesondere diese Kommandos interessant:

  • snapshots zum Anzeigen existierender Sicherungen,
  • restore zum Wiederherstellen von Dateien und Verzeichnissen sowie
  • forget zum Entfernen von Sicherungen.

Zur Erinnerung: Restic gibt auf jeder Kommandoebene mittels dem --help-Argument weitere Informationen darüber, welche Argumente akzeptiert werden, z. B. restic --help oder restic backup --help. Um etwaige Probleme mit Dateirechten zu vermeiden, wird in diesem Beitrag mit root-Rechten per sudo su gearbeitet.

Aus einer Sicherung wiederherstellen

Nachdem erfolgreich Sicherungen in einem Restic Repository angelegt wurden, geht es nun an den eigentlichen Zweck von Sicherungen: Die Wiederherstellung der gesicherten Daten. Wenn der Container noch funktioniert, lässt sich der Inhalt elegant über das Volume wiederherstellen. Um den Effekt darzustellen, wird als künstliches Störungsereignis der Inhalt des Docker-Volumes gelöscht.

rm /var/lib/docker/volumes/nginxData/_data/

Wenn nun im Browser die Seite unter http://localhost:8080 aufgerufen wird, sollte eine Fehlermeldung erscheinen. Nun kann die Wiederherstellung erfolgen. Für eine Wiederherstellung gelten bezüglich offener Dateien jedoch Regeln analog zu denen der Sicherung. Das bedeutet, dass auch für eine Wiederherstellung die logischen bzw. technischen Abhängigkeiten zwischen Containern befolgt werden müssen:

  1. Container stoppen
  2. Volume(s) wiederherstellen
  3. Container starten.

Vor der Wiederherstellung muss sichergestellt werden, dass der zuvor genutzte Minio-Server auch gestartet wurde, denn dieser hält zu Testzwecken schließlich die Sicherungen aus dem ersten Teil dieser Serie vor:

docker start minio

Der zuverlässigste Weg, um eine Sicherung zur Wiederherstellung auszuwählen, ist die gewünschte Snapshot ID zu übergeben. Diese lässt sich über restic snapshots oder aus der Ausgabe von restic backup ermitteln. Da der gesicherte Pfad ein absoluter Pfad ist (also ab / abwärts), muss auch die --target-Option auf / gesetzt werden. Würde man hier den kompletten Pfad /var/lib/docker/volumes/nginxData/_data/index.html verwenden, so würde der gesamte Verzeichnisbaum rekursiv in das _data/-Verzeichnis gesteckt werden. Als erstes sollte geklärt werden, welche Snapshots vorliegen:

1
2
3
4
5
6
7
8
9
10
restic snapshots
repository 00d7d2bb opened successfully, password is correct
ID Time Host Tags Paths
--------------------------------------------------------------------------------
----------------------------
aed06d2f 2019-04-05 13:00:01 MY-HOST-1337 Komplettsicherung KW15
/var/lib/docker/volumes/nginxData/_data
d7e6092d 2019-04-12 15:52:32 MY-HOST-1337 Komplettsicherung KW16
/var/lib/docker/volumes/nginxData/_data
--------------------------------------------------------------------------------

Die ID d7e6092d aus dem Listing wird nun für die konkrete Wiederherstellung verwendet. Der Befehl zum Wiederherstellen des Volume-Inhaltes sieht danach wie folgt aus:

1
2
3
4
5
docker stop prod-nginx
prod-nginx
restic restore d7e6092d --target /
docker start prod-nginx
prod-nginx

Alternativ existiert noch der Befehl restic restore latest, der den letzten Snapshot zum Restore verwendet. Hiervon ist jedoch abzuraten, denn dieser Fall ist ganz ähnlich gelagert wie bei Container-Images mit dem “latest”-Tag: Wenn unterschiedliche Sicherungen unterschiedlicher Volumes vorliegen, dann ist nicht klar, welche Daten in dem zuletzt gesicherten Snapshot tatsächlich liegen. Prinzipiell gibt es die Möglichkeit, einen Suchpfad mitzugeben, allerdings steht dies im Widerspruch zum Prinzip der einfachen Nutzung.

Da in der Regel bei Produktionsdaten besondere Vorsicht gilt, ist es für eine Wiederherstellung ratsam, das Argument --verify mitzugeben:

restic restore d7e6092d --target / --verify

Dies versteht sich als zusätzliche Sicherheitsmaßname zu verstehen. Hierbei gleicht Restic die wiederhergestellten Daten mit denen aus dem Backup-Repository ab.

Sicherungen entfernen

Mit diesem Wissen lässt es sich im Bereich Sicherung und Wiederherstellung sinnvoll arbeiten. Wenn jedoch auf eigenen Datenträgern gesichert wird, so zeigt die Erfahrung, dass der Speicherplatz doch recht schnell knapp wird. Wenn andererseits in der Cloud gesichert wird, dann kann je nach Storage-Ansatz und Vertragslage auch unendlich viel Speicherplatz vorhanden sein. Dann ist es durchaus wünschenswert, die Liste der Snapshots auf ein übersichtliches Maß zu verkleinern.

Für diese Fälle sieht Restic ebenfalls eine Funktionalität vor, nämlich restic forget. Bevor auf die Eigenheiten von restic forget eingegangen wird, sollte vorweg ein Blick auf die Funktionsweise von Restic geworfen werden. Um die Geschwindigkeit anbieten zu können, arbeitet Restic neben der Verschlüsselung intensiv mit Referenzen und Hashes. Vor jeder Übertragung wird der Hash des zu sichernden Teils errechnet. Wenn der Hash zeigt, dass dieser Teil bereits vorhanden ist, dann wird er nicht mehr übertragen, sondern nur noch referenziert. Diese Deduplikation spart Zeit und Platz. Für Wissbegierige: Der Befehl restic stats --mode raw-data zeigt den tatsächlichen Speicherverbrauch an, den das Backup-Repository einnimmt.

Wenn nun Snapshots aus dem Backup-Repository entfernt werden sollen, dann verschwinden sie zwar aus der Übersicht, doch belegen sie immer noch Platz auf der Festplatte. Dies liegt daran, dass die Suche nach unreferenzierten Daten Zeit benötigt. Restic bietet zwei Alternativen an, um den Platz tatsächlich freizugeben. Entweder mit einem eigenen Kommando restic prune oder als Parameter restic forget --prune.

Die leichteste Variante, Sicherungen zu entfernen, ist die Verwendung von Snapshot-IDs. Denn hier gibt es keine Arbeitsverweigerung, auf die später zurückgekommen wird. Beispielsweise entfernt dieser Befehl drei genannte Snapshots und gibt die Daten auf der Festplatte frei.

restic forget 40dc1520 79766175 590c8fc8 –prune

Policy

Wenn man sich ein automatisiertes Backup eingerichtet hat, ist ein gängiges Vorgehen auch automatisiert alte Sicherungen zu rotieren, z. B. in dem man für ein Zeitintervall nur eine bestimmte Menge von Sicherungen vorhalten möchte. Dann kann das Vorgehen über die Verwendung von Snapshot-IDs eher unpraktisch wirken. Eine Alternative zu der Verwendung von Snapshot-IDs sind sogenannte Policies, die eine kriterienbasierte Auswahl von Snapshots bereitstellt, die nicht entfernt werden sollen.

In der Praxis zeigt es sich als hilfreich, den Parameter restic forget --dry-run auszuprobieren, um die Auswirkung zu sehen, ohne Daten Verlust befürchten zu müssen. Restic geht dabei viele Meilen, um versehentlichen Datenverlust zu vermeiden. Wenn eine Policy- Kombination ergibt, dass alle Snapshots gelöscht würden, so verweigert dies Restic und löscht gar keine Snapshots, wie in dem folgenden Beispiel.

1
2
3
restic forget --keep-last 0 --prune
repository 8460094c opened successfully, password is correct
no policy was specified, no snapshots will be removed

Eine einfache Policy wird durch den Parameter --keep-last bereitgestellt, der die übergebene Anzahl der zeitlich letzten Sicherungen vorhält. Dieses Beispiel behält von jedem Pfad die letzten drei Snapshots. Als

restic forget --keep-last 3 –prune

Darüber hinaus gibt es eine Menge von Alternativen, um die Auswahl der zu behaltenden Snapshots einzugrenzen. So gibt es --keep-hourly, die eine Anzahl von stündlichen Snapshots des gleichen Dateipfades behält. Hinzu kommen Entsprechungen auf Tages-, Wochen- bis hin zur Jahresebene.

Es gibt zwei weitere, interessante Policy-Parameter, die sich von den anderen zeitlichen Parametern absetzen. Während --keep-tag die Snapshots mit einem gegebenen Tag behält, ist es möglich mit --keep-within {duration} eine Dauer bis zum neuesten Snapshot anzugeben. Dieses Beispiel etwa behält alle angelegten Snapshots der letzten 2 Jahre, 5 Monate, 7 Tage und 3 Stunden vor dem neuesten Snapshot:

restic forget --keep-within 2y5m7d3h –forget

Policy-Bausteine

Alle Policies von Restic lassen sich bequem kombinieren. Dies lässt sich dadurch erreichen, dass ein Parameter wiederholt wird. Soll zum Beispiel Restic je Monat, Woche und Tag einen Snapshot vorhalten, so lässt sich dies sehr elegant mit den folgenden Parametern ausdrücken:

restic forget --keep-daily 1 --keep-weekly 1 --keep-monthly 1 –prune

Hierbei lohnt sich ein Blick in die Dokumentation, insbesondere wenn die Policy mit Tag-Listen angereichert wird, auf die hier nicht weiter eingegangen werden kann.

Zusammenfassung

Restic ist ein mächtiges Werkzeug, dass überragend viele relevante Aspekte von Backup und Restore löst, insbesondere hinsichtlich der Einfachheit der Bedienung kombiniert mit der Geschwindigkeit und Sicherheit. Die Entfernung von Snapshots mit Policies kann in komplexeren Fällen Kopfzerbrechen bereiten, aber es gibt immer den Weg der Verwendung von Snapshot-IDs. Sozusagen als Backup.


Boris Schaa
Boris Schaa

- Senior Software Developer -

Boris ist Senior Software Developer und Principal Unicorn Researcher bei der Cloudogu GmbH und beschäftigt sich neben dem Thema Backup & Restore des Cloudogu EcoSystem stark mit Go und Java. Daneben sammelt er gerne Hobbies wie aktives Musizieren, Grafische Gestaltung oder schreibt Science Fiction.