SSD Nodes Learn 🎉 VPS ab $5.50/Monat
Anleitungen Matt ConnorVon Matt Connor

VPS: Snapshots, Backups oder Clones?

Ein Snapshot liegt beim Provider und ist kein Backup. Erfahren Sie, was Snapshot, Backup und Clone wiederherstellen und was Sie vor dem Start eines Clones ändern müssen.

Was ein Snapshot, ein Backup und ein Clone tatsächlich sind

Ein VPS-Snapshot ist ein Festplattenabbild Ihres Servers, das bei Ihrem Provider auf dessen Infrastruktur in Ihrem Konto gespeichert wird. Ein Backup ist eine unabhängige Kopie Ihrer Daten, die Sie an einem anderen Ort wiederherstellen können, ohne die Hilfe des Providers zu benötigen, bei dem das Original gespeichert war. Ein Clone ist eine neue Instanz, die aus einem Snapshot bereitgestellt wird. Sie startet daher als exakte Kopie des Originals, einschließlich seiner Identität.

Sie lösen unterschiedliche Probleme. Mit einem Snapshot können Sie ein fehlgeschlagenes Upgrade innerhalb weniger Minuten zurücksetzen. Bei einem geschlossenen Konto hilft er jedoch nicht. Ein Backup bleibt erhalten, wenn der Provider seinen Betrieb einstellt. Die Wiederherstellung dauert länger, weil Sie den Server zunächst neu aufbauen müssen. Ein Clone stellt in einem Schritt einen zweiten laufenden Server bereit. Dadurch haben Sie jedoch auch zwei Maschinen, die glauben, dieselbe Maschine zu sein.

Warum ein VPS-Snapshot kein Backup ist

Das Problem ist die Fehlerdomäne, nicht die Qualität des Abbilds. Ein Snapshot liegt auf der Storage-Plattform Ihres Providers, normalerweise in derselben Region wie der Server, von dem er stammt, und immer innerhalb desselben Kontos. Ein einzelnes Ereignis kann den Server und seinen Snapshot gemeinsam betreffen.

  • Das Konto wird gesperrt, eine Zahlung schlägt fehl oder jemand stiehlt die Zugangsdaten.
  • Eine Person oder ein Skript mit API-Zugriff löscht die Instanz. Bei vielen Providern werden beim Löschen einer Instanz auch die zugehörigen Snapshots gelöscht. Lesen Sie die dokumentierte Funktionsweise Ihres Providers, bevor Sie etwas anderes annehmen.
  • In der Region tritt ein Problem auf, und alles darin ist gleichzeitig nicht erreichbar.
  • Etwas, das auf dem Server als root läuft, findet das Provider-API-Token, das Sie in /root hinterlegt haben, und löscht die Snapshots, bevor es den Datenträger verändert.

Ein Backup ist die Kopie, die alle vier Szenarien übersteht. Der Test besteht aus einer Frage: Wenn Ihr Provider-Konto heute Nachmittag nicht mehr existieren würde, was könnten Sie noch wiederherstellen, und wohin würden Sie es wiederherstellen? Alles, was diese Frage nicht erfüllt, ist ein Rollback-Werkzeug. Erstellen Sie weiterhin Snapshots, weil sich damit nichts schneller wiederherstellen lässt. Bewahren Sie zusätzlich eine zweite Kopie auf einem Storage auf, den Ihr Provider nicht kontrolliert.

Die alte Regel gilt weiterhin: drei Kopien der Daten auf zwei Arten von Storage, davon eine außerhalb der Plattform. Ein Provider-Snapshot zusammen mit einem restic-Backup-Repository auf einer separaten Infrastruktur deckt diese Regel mit zwei Komponenten ab.

Warum ein Snapshot einer laufenden Datenbank beim Wiederherstellen beschädigt sein kann

Ein Provider-Snapshot kopiert das Blockgerät so, wie es in einem bestimmten Moment aussieht. Er fordert Ihre Anwendungen nicht vorher zum Anhalten auf und kann nicht sehen, was noch im Page Cache liegt. Das Abbild ist daher bestenfalls crash-konsistent. Es entspricht genau dem Zustand, den die Festplatte nach dem Ziehen des Netzkabels hätte.

Der größte Teil des Stacks kann damit umgehen. ext4 und XFS spielen ihr Journal beim Einhängen wieder ein, sodass das Dateisystem verfügbar wird. PostgreSQL spielt beim Start sein Write-Ahead-Log wieder ein. Die entsprechende Meldung sieht so aus:

LOG:  database system was not properly shut down; automatic recovery in progress

InnoDB arbeitet genauso und gibt beim Start eigene Meldungen zur Crash-Recovery aus. Diese Wiederherstellung entspricht dem vorgesehenen Verhalten der Datenbank. Deshalb lässt sich ein Snapshot eines einzelnen Volumes mit einer wenig ausgelasteten PostgreSQL- oder MySQL-Instanz normalerweise problemlos wiederherstellen.

Es gibt reale Fälle, in denen Crash-Konsistenz nicht ausreicht. Diese Fälle verursachen die größten Probleme. Wenn sich Ihre Daten über zwei Volumes erstrecken, werden die Root-Disk und eine separate Daten-Disk zu unterschiedlichen Zeitpunkten gesnapshottet. Dadurch können die Datendateien und das Log-Verzeichnis voneinander abweichen, und für die Wiederherstellung stehen keine korrekten Daten zur Verfügung. Jede Datei, in die eine Anwendung schreibt, ohne fsync aufzurufen, kann unvollständig zurückkommen, etwa ein nur teilweise empfangener Upload oder eine Queue-Datei. Alles, was die Anwendung im Arbeitsspeicher hält und nach einem Zeitplan schreibt, ist im Abbild nicht enthalten.

Schreiben Sie daher vor dem Snapshot einen Dump auf die Festplatte. Das Abbild enthält dann eine Datei, deren interner Zustand konsistent ist, unabhängig vom Zustand der aktiven Datendateien.

sudo -u postgres pg_dumpall --clean --file=/var/backups/pg-$(date +%F).sql
sudo mysqldump --single-transaction --routines --all-databases > /var/backups/mysql-$(date +%F).sql

--single-transaction erstellt einen konsistenten Dump von InnoDB-Tabellen, ohne Schreibvorgänge zu blockieren, weil der Dump innerhalb einer Transaktion mit Repeatable-Read-Isolation ausgeführt wird. MyISAM-Tabellen werden nicht erfasst. Für diese Tabellen ist eine Sperre oder ein angehaltener Server erforderlich. Prüfen Sie den Dump, bevor Sie ihm vertrauen: Er darf nicht leer oder abgeschnitten sein. Bei einem vollständigen mysqldump endet tail -n 1 /var/backups/mysql-$(date +%F).sql mit einem Dump completed-Kommentar.

Wenn Sie ein separates Daten-Volume haben, können Sie es für die Sekunden einfrieren, die der Snapshot benötigt:

sudo fsfreeze -f /srv
# take the snapshot from your provider's panel or API
sudo fsfreeze -u /srv

Frieren Sie nur ein Daten-Volume ein. Frieren Sie niemals / ein. Ein eingefrorenes Root-Dateisystem blockiert jeden Schreibvorgang auf dem System, einschließlich der Shell, in der Sie den Befehl zum Aufheben des Freeze eingeben würden. Dadurch sperren Sie sich selbst aus und müssen auf einen Hard Reset warten.

Die Offsite-Hälfte: restic oder Borg

Der Snapshot ist die schnelle Hälfte. Die Offsite-Kopie ist die Hälfte, die einen Ausfall Ihres Providers übersteht. restic ist eine gute Standardwahl, weil es dedupliziert, clientseitig verschlüsselt und in S3-kompatiblen Objektspeichern, per SFTP oder in ein normales Verzeichnis schreibt. Ein Storage-VPS als Offsite-Ziel eignet sich dafür gut, weil Backup-Repositorys Kapazität und nicht IOPS benötigen.

sudo apt update && sudo apt install -y restic
sudo sh -c 'umask 077; head -c 24 /dev/urandom | base64 > /root/.restic-pass'
sudo chmod 600 /root/.restic-pass
sudo cat /root/.restic-pass

Kopieren Sie diese Passphrase jetzt in einen Passwortmanager auf einem Gerät, das nicht dieser Server ist. Ein restic-Repository kann ohne sie nicht geöffnet werden, und es gibt keinen Wiederherstellungsweg. Wenn die einzige Kopie des Passworts auf dem gerade verlorenen Server lag, ist das Backup nur verschlüsselter Datenmüll.

export RESTIC_REPOSITORY="s3:https://s3.example.com/vps-backups"
export RESTIC_PASSWORD_FILE=/root/.restic-pass
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
sudo -E restic init
sudo -E restic backup /etc /srv /var/backups
sudo -E restic snapshots

sudo -E behält diese Variablen bei, denn ohne diese Option erhält root eine saubere Umgebung und restic meldet, dass kein Repository-Speicherort angegeben wurde. restic snapshots sollte den gerade ausgeführten Lauf mit seinem Host und seinen Pfaden auflisten. Überprüfen Sie das Repository selbst regelmäßig und lesen Sie einige Daten zurück, statt nur die Struktur zu prüfen:

sudo -E restic check --read-data-subset=5%
sudo -E restic restore latest --target /tmp/restore-check
sudo -E restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

Ein nicht getestetes Backup ist eine Vermutung. Stellen Sie es mindestens einmal auf einem anderen VPS wieder her, messen Sie die dafür benötigte Zeit und notieren Sie sie, denn diese Zahl ist Ihr tatsächliches Wiederherstellungsziel. Borg ist die andere zuverlässige Wahl und speichert sein Repository über SSH statt in einem Objektspeicher. Die Unterschiede werden im Vergleich von restic und BorgBackup behandelt.

Was vor dem Einsatz eines geklonten VPS in der Produktion zu beheben ist

Ein Klon ist eine exakte Kopie. Das ist sein Vorteil und zugleich das Problem. Alles, was das Original eindeutig gemacht hat, wird dupliziert, und Duplikate führen zu Konflikten.

Generieren Sie die SSH-Hostschlüssel neu. Der Klon enthält die /etc/ssh/ssh_host_*-Dateien des Originals. Dadurch präsentieren zwei Server dieselbe Hostidentität. Wer einen der Server kontrolliert, kann sich gegenüber jedem Client, der diesen Schlüssel akzeptiert hat, als der andere ausgeben. SSH gibt dabei keine Warnung aus, weil der Schlüssel dem entspricht, den der Client erwartet.

sudo rm -f /etc/ssh/ssh_host_*
sudo ssh-keygen -A
sudo systemctl restart ssh
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

ssh-keygen -A schreibt für jeden vom Daemon erwarteten Typ einen neuen Schlüssel. Der Fingerabdruck aus dem letzten Befehl muss sich von dem des Originals unterscheiden. Ihre aktuelle Sitzung bleibt bestehen, weil ein Neustart von sshd bestehende Verbindungen nicht schließt. Führen Sie dies aus, bevor sich jemand mit dem Klon verbindet. Wenn Sie damit warten, erhält jeder Client, der dem übernommenen Schlüssel bereits vertraut, WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! und muss zuerst ssh-keygen -R <host> ausführen.

Setzen Sie die machine ID zurück. /etc/machine-id ist eine eindeutige Kennung, die systemd beim ersten Boot einmalig erzeugt und die der Klon übernimmt.

sudo truncate -s 0 /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id
sudo ln -s /etc/machine-id /var/lib/dbus/machine-id
sudo reboot

Ein leeres /etc/machine-id weist systemd an, beim nächsten Boot einen neuen Wert zu erzeugen. Deshalb leeren Sie die Datei, statt sie zu löschen. Wenn die Kennung dupliziert ist, treten zwei Probleme auf. Bei Images, die ihre Adresse über DHCP beziehen, leitet systemd-networkd die DHCP-Clientkennung standardmäßig aus der machine ID ab. Beide Klone fragen dann als derselbe Client nach einem Lease, und der Server weist ihnen dieselbe Adresse zu. Außerdem versieht journald jeden Eintrag mit der machine ID. Ein zentraler Log-Collector ordnet dadurch beide Server derselben Maschine zu. Führen Sie nach dem Reboot cat /etc/machine-id aus und bestätigen Sie, dass sich der Wert geändert hat.

Ändern Sie den Hostnamen.

sudo hostnamectl set-hostname web-02
grep 127.0.1.1 /etc/hosts

hostnamectl schreibt /etc/hostname und übernimmt den Namen sofort. /etc/hosts wird dabei nicht geändert. Bearbeiten Sie die Zeile 127.0.1.1 entsprechend. Andernfalls kann der neue Name nirgends aufgelöst werden. Jeder Aufruf von sudo wartet dann auf eine fehlgeschlagene Namensauflösung und gibt sudo: unable to resolve host web-02: Name or service not known aus.

Rotieren Sie alle im Image hinterlegten Zugangsdaten. Der Klon enthält die Geheimnisse des Originals. Nun können zwei Maschinen als das Original handeln. Prüfen Sie die SSH-authorized_keys-Dateien, Provider- und DNS-API-Tokens, anwendungsspezifischen .env-Dateien, Datenbankpasswörter, privaten TLS-Schlüssel, Tokens für die Monitoring-Registrierung, das Passwort des restic-Repositorys und alle weiteren Zugangsdaten. Damit finden Sie die meisten:

sudo grep -rIlE 'PASSWORD|SECRET|TOKEN|API_KEY' /etc /srv /opt /home 2>/dev/null
sudo find / -name '.env' -not -path '/proc/*' -not -path '/sys/*' 2>/dev/null

Wenn der Klon eine Testkopie ist, die niemals Netzwerkverkehr bedienen wird, widerrufen Sie die Zugangsdaten statt sie zu rotieren. Ein Staging-Server mit einem aktiven Produktions-API-Token ist ein Produktionsserver mit schlechterem Patchstand.

Deaktivieren Sie die Jobs, die jetzt doppelt ausgeführt werden. Zwei Server, die dieselbe Crontab ausführen, greifen in derselben Minute auf dieselben externen Systeme zu.

systemctl list-timers --all
sudo crontab -l
sudo ls -l /etc/cron.d /etc/cron.daily

Der Fall mit restic verdient eine ausführliche Erklärung, weil dadurch Ihre Aufbewahrung beschädigt wird, anstatt dass nur ein offensichtlicher Fehler auftritt. restic versieht jeden Snapshot mit dem Hostnamen, und restic forget --keep-daily 7 wendet seine Richtlinie pro Host an. Zwei Maschinen mit demselben Hostnamen werden als ein Host behandelt. Dadurch können alle sieben „täglichen“ Snapshots vom Klon stammen, während die Snapshots des Originals entfernt werden. Ändern Sie den Hostnamen vor dem ersten Backup-Lauf oder stoppen Sie den Timer auf dem Klon. Bei certbot ist der Fall einfacher: Zwei Server, die dieselben Namen erneuern, stoßen beim Certificate Authority an das Rate Limit für doppelte Zertifikate. Der unterlegene Lauf schlägt mit einem Fehler fehl, dass für genau diese Namensgruppe bereits zu viele Zertifikate ausgestellt wurden. Ein Klon, dessen Domain weiterhin auf das Original zeigt, kann eine HTTP-Challenge ohnehin nicht bestehen. Deaktivieren Sie die Erneuerung daher auf diesem Server.

Kümmern Sie sich um den Monitoring-Agenten. Die meisten Agents identifizieren sich über den Hostnamen oder über eine bei der Installation angelegte ID-Datei. Dadurch führen zwei Agents, die als ein Host melden, ihre Metriken in einer gemeinsamen Zeitreihe zusammen. CPU-Diagramme zeigen dann Werte, die keine einzelne Maschine erzeugt hat, und Alerts wechseln ständig zwischen den Zuständen. Stoppen und entfernen Sie den Agenten auf dem Klon oder registrieren Sie ihn unter dem neuen Hostnamen erneut. Verwenden Sie dafür das vom Hersteller dokumentierte Verfahren.

Prüfen Sie die Netzwerkkonfiguration auf die Adresse des Originals. Wenn das Image eine statische Adresse in netplan enthält, beansprucht der Klon eine IP-Adresse, die zu einem anderen Rechner gehört.

ip -br addr
sudo grep -r addresses /etc/netplan/

Löschen Sie den cloud-init-Status, wenn dieser Klon als Template verwendet wird.

sudo cloud-init clean --logs

Dadurch wird der cloud-init-Status unter /var/lib/cloud entfernt. Beim nächsten Boot werden die First-Boot-Module erneut ausgeführt. Dazu gehört auch das Generieren von SSH-Hostschlüsseln, wenn keine vorhanden sind. Einige Versionen unterstützen außerdem ein Flag zum Zurücksetzen der machine ID. Führen Sie auf Ihrem eigenen Image cloud-init clean --help aus, um zu prüfen, welche Optionen Ihre Version unterstützt, statt einer fremden Liste von Flags zu vertrauen.

Welche Methode wann verwenden

Ein riskantes Upgrade zurücksetzen: einen Snapshot erstellen. Erstellen Sie den Snapshot wenige Minuten vor der Änderung, führen Sie das Upgrade durch und stellen Sie das Image wieder her, wenn etwas schiefgeht. Bei der Wiederherstellung werden alle Schreibvorgänge seit dem Snapshot verworfen. Sichern Sie deshalb auf einem Server mit aktivem Netzwerkverkehr zuerst die Datenbank und legen Sie genau fest, welches Zeitfenster Sie verlieren würden. Für einen do-release-upgrade auf einem Server, den Sie zehn Minuten offline nehmen können, ist ein Snapshot der gesamte Ablauf.

Auf einen größeren Tarif migrieren: einen Klon bereitstellen. Erstellen Sie den Klon aus einem Snapshot im größeren Tarif, arbeiten Sie die obige Identitätsliste durch und testen Sie ihn unter seiner eigenen IP-Adresse, bevor Netzwerkverkehr umgeleitet wird. Setzen Sie die DNS-TTL einen Tag vorher herab, damit die Umschaltung schnell erfolgt, und lassen Sie den ursprünglichen Server weiterlaufen, bis der neue Server realen Netzwerkverkehr verarbeitet hat. Prüfen Sie zuerst anhand von derselben Benchmark-Methode auf beiden Servern, ob der größere Tarif für Ihre Arbeitslast tatsächlich schneller ist. Mehr vCPUs auf ausgelasteterer Hardware sind nicht immer ein Upgrade.

Eine Vorlage erstellen: einen bereinigten Rechner als Snapshot sichern. Installieren und härten Sie einen Server. Entfernen Sie anschließend alles, was vor dem Erstellen des Images eindeutig für diesen Server gilt. Dazu gehören Hostschlüssel, eine leere machine ID, keine persönlichen authorized_keys und bereinigtes cloud-init. Erstellen Sie danach den Snapshot. Jede daraus bereitgestellte Instanz erzeugt beim ersten Boot ihre eigene Identität. Dadurch muss die obige Checkliste nicht mehr manuell abgearbeitet werden. Kombinieren Sie dies mit den standardmäßigen ersten zehn Minuten auf einem neuen VPS, damit die Vorlage die Arbeiten bereits enthält, die Sie sonst wiederholen müssten.

FAQ

Ist ein VPS-Snapshot ein Backup?

Nein, denn er liegt in derselben Fehlerdomäne wie der Server, von dem er erstellt wurde. Der Snapshot liegt im Storage Ihres Providers, in Ihrem Account und normalerweise in derselben Region. Eine Account-Sperrung, ein gestohlener API-Key oder das versehentliche Löschen der Instanz kann den Server und seine Snapshots mit einer einzigen Aktion entfernen. Bei vielen Providern werden die Snapshots beim Löschen einer Instanz konstruktionsbedingt ebenfalls gelöscht. Ein Snapshot ist der schnellste verfügbare Rollback. Erstellen Sie daher weiterhin Snapshots und bewahren Sie zusätzlich eine zweite verschlüsselte Kopie auf einer Infrastruktur auf, die Ihr Provider nicht kontrolliert.

Muss ich meine Datenbank vor dem Erstellen eines Snapshots stoppen?

Nicht immer. Sie müssen jedoch akzeptieren, welchen Zustand Sie erhalten. Ein Provider-Snapshot ist crash-konsistent. Das Image entspricht dem Zustand, den die Festplatte nach einem Stromausfall hätte. PostgreSQL und InnoDB stellen diesen Zustand beim Start wieder her. PostgreSQL protokolliert diesen Vorgang in database system was not properly shut down; automatic recovery in progress. Die Wiederherstellung ist nicht garantiert, wenn sich Ihre Daten auf zwei Volumes befinden, von denen Snapshots zu unterschiedlichen Zeitpunkten erstellt wurden, oder wenn eine Anwendung ohne fsync schreibt. Schreiben Sie vorher ein pg_dumpall oder ein mysqldump --single-transaction auf die Festplatte. Dann enthält das Image eine Datei, deren Konsistenz Sie kennen.

Warum konkurrieren zwei geklonte Server um dieselbe IP-Adresse?

Weil sie /etc/machine-id gemeinsam verwenden. Bei Images mit DHCP erstellt systemd-networkd die DHCP-Client-ID standardmäßig aus der Machine-ID. Beide Klone fordern dann als derselbe Client ein Lease an, und der DHCP-Server weist beiden dieselbe Adresse zu. Kürzen Sie /etc/machine-id auf 0 Bytes, entfernen Sie /var/lib/dbus/machine-id, verlinken Sie es wieder symbolisch auf /etc/machine-id und führen Sie einen Reboot durch. Dadurch erzeugt systemd einen neuen Wert. Die andere häufige Ursache ist eine statische Adresse in /etc/netplan/, die der Klon unverändert übernommen hat. Prüfen Sie dies mit ip -br addr.

Wie prüfe ich am schnellsten, ob ein Klon für den Produktionseinsatz geeignet ist?

Vergleichen Sie vier Punkte mit dem ursprünglichen Server. Führen Sie ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub auf beiden Servern aus und prüfen Sie, ob sich die Fingerprints unterscheiden. Führen Sie cat /etc/machine-id auf beiden Servern aus und prüfen Sie, ob sich die Werte unterscheiden. Führen Sie hostnamectl status aus und prüfen Sie, ob der Name neu ist und aufgelöst wird, sodass sudo keine Warnung ausgibt. Führen Sie anschließend systemctl list-timers --all aus und stoppen Sie jeden Timer, der mit einem gemeinsam genutzten System kommuniziert, beispielsweise für Backups, die Zertifikatserneuerung oder einen Monitoring-Agenten. Lassen Sie diese Timer gestoppt, bis Sie entschieden haben, welcher Rechner diese Aufgabe übernimmt.