Ein Kubernetes Backup ist kein einzelner Vorgang, sondern die Sicherung von drei getrennten Schichten: die Konfiguration in Git, der Cluster-Zustand in etcd und die Daten auf den Volumes. Wer nur eine davon sichert, verliert im Ernstfall trotzdem etwas, entweder den Zustand des Clusters, die eigentlichen Daten oder beides zusammen.
Die drei Schichten brauchen unterschiedliche Werkzeuge und unterschiedliche Zeitpläne. Ein etcd-Snapshot rettet dich bei einem kaputten Control-Plane, ein Volume-Backup bei gelöschten oder beschädigten Daten, und Git rettet dich bei einer verpfuschten Änderung. Alle drei zusammen ergeben ein Backup, dem du im Ernstfall vertrauen kannst.
Ich betreibe Kubernetes-Cluster in Produktion und habe das Kubernetes-Praxisbuch bei Rheinwerk geschrieben. Alle meine Beiträge zu Kubernetes findest du gesammelt auf der Seite Kubernetes.
Was in einem Kubernetes-Cluster wirklich verloren gehen kann
Drei Dinge gehen typischerweise verloren, wenn ein Cluster oder eine Node ausfällt. Erstens die Manifeste selbst: Deployments, Services, ConfigMaps, Ingress-Regeln. Zweitens der aktuelle Zustand: welcher Pod läuft gerade wo, welche Secrets existieren, welche Zuordnung zwischen Persistent Volume und Persistent Volume Claim gerade gilt. Drittens die eigentlichen Daten in den Volumes, also das, was deine Datenbank oder dein Dateispeicher enthält.
Der zweite Punkt wird oft unterschätzt. Der aktuelle Zustand des Clusters, inklusive aller Objekte, Rollenzuweisungen und internen Referenzen, liegt in etcd, dem verteilten Schlüssel-Wert-Speicher hinter der Kubernetes-API. Ein Manifest in Git zeigt dir, was gelten soll. etcd zeigt dir, was gerade gilt, und genau das kann bei einem Totalausfall der Control-Plane weg sein, selbst wenn deine Manifeste in Git unversehrt daliegen.
Kubernetes Backup in drei Schichten: Git, etcd und Volumes
Die folgende Tabelle zeigt, was jede Schicht abdeckt und womit du sie sicherst.
| Schicht |
Was sie enthält |
Verloren bei |
Sicherung mit |
| Git |
gewünschter Zustand deiner Manifeste |
menschlichem Fehler, Fehlkonfiguration |
Versionskontrolle, Pull Requests |
| etcd |
tatsächlicher Cluster-Zustand, Secrets, Zuordnungen |
Ausfall der Control-Plane |
etcd-Snapshot |
| Volumes |
Anwendungsdaten, Datenbankinhalte |
Node-Ausfall, versehentliches Löschen |
Velero, CSI-Snapshot, Dateisystem-Backup |
Wer seine Cluster mit GitOps betreibt, hat die erste Schicht praktisch geschenkt. Wenn ArgoCD oder ein vergleichbares Werkzeug den gewünschten Zustand aus einem Git-Repository ausrollt, ist jede Deployment- und ConfigMap-Definition ohnehin versioniert und wiederherstellbar. In meinen eigenen Clustern ersetzt das ein separates Backup der Manifeste vollständig: Ich muss keine laufenden Objekte aus dem Cluster exportieren, ich muss nur das Repository wiederherstellen und den Sync erneut anstoßen. Das ändert aber nichts daran, dass etcd und Volumes trotzdem eigene Sicherungen brauchen, denn beide enthalten Zustand, den niemand in Git schreibt: Laufzeitdaten in den Volumes, vom Cluster selbst erzeugte Werte in etcd.
etcd sichern: Snapshot statt Vertrauen
Ein etcd-Snapshot ist eine vollständige Kopie des Cluster-Zustands zu einem bestimmten Zeitpunkt: alle Objekte, alle Secrets, alle internen Zähler. Ohne diesen Snapshot ist ein Cluster nach einem Totalausfall der Control-Plane nicht wiederherstellbar, egal wie sauber deine Manifeste in Git liegen, denn ein Repository enthält nur das, was du bewusst hineinschreibst. Verschlüsselte Secrets können durchaus in Git liegen, etwa über SOPS, und ich halte meine eigenen genau so. Was dort nicht steht, sind die vom Cluster selbst erzeugten Werte: automatisch angelegte Service-Account-Token, aktuelle Ressourcenzustände und interne Referenzen zwischen Objekten.
Der einfachste Weg führt an Kubernetes-Objekten vorbei: k3s legt geplante etcd-Snapshots standardmäßig zweimal täglich an und kann sie direkt in einen S3-kompatiblen Speicher schreiben, konfiguriert über Startparameter des Servers (k3s-Dokumentation zu etcd-Snapshots). Wer k3s einsetzt, sollte diesen eingebauten Weg nehmen, weil dabei nichts an Zertifikatspfaden, Rechten oder Datenverzeichnissen selbst zusammengebaut werden muss.
Wer denselben Ablauf lieber als Cluster-Objekt hätte, kann ihn im Prinzip als CronJob abbilden, der auf einer Control-Plane-Node den Snapshot-Befehl ausführt. Ein fertiges Manifest zeige ich hier bewusst nicht. Ein solcher Job braucht Zugriff auf das Datenverzeichnis samt etcd-Zertifikaten, eine fest gepinnte Image-Version statt eines beweglichen Tags und die S3-Zugangsdaten sauber aus einem Secret statt im Klartext im Manifest. Diese Details unterscheiden sich je Installation, und ein Wiederherstellungsweg, der nur auf dem Papier funktioniert, ist gefährlicher als gar keiner. Der eingebaute Zeitplan von k3s deckt denselben Zweck ab, ohne dass du etwas davon selbst zusammenbauen musst.
Wichtiger als das Anlegen ist ohnehin das Zurückspielen, und dort läuft der Restore bei k3s nicht auf allen Control-Plane-Nodes gleichzeitig, sondern in einer festen Reihenfolge: k3s auf allen Servern stoppen, auf der Node mit dem Snapshot k3s server --cluster-reset --cluster-reset-restore-path=<Pfad> ausführen, diese Node anschließend ohne das Reset-Flag neu starten, und erst danach auf jeder weiteren Server-Node das alte Verzeichnis server/db sichern, löschen und die Node wieder verbinden (k3s-Dokumentation zu etcd-Snapshots). Ein Restore betrifft immer den gesamten Cluster-Zustand und ist ein Vorgang für echte Notfälle, kein Werkzeug für den Alltag. Für Cluster ohne k3s beschreibt die Kubernetes-Dokumentation zum Sichern eines etcd-Clusters den allgemeinen Weg.
Volumes sichern: Velero, CSI-Snapshots oder Dateisystem-Backup
Für die Daten in deinen Persistent Volumes reicht ein etcd-Snapshot nicht, denn der sichert nur die Beschreibung des Volumes, nicht dessen Inhalt. Dafür braucht es ein eigenes Werkzeug, und in der Praxis hat sich Velero als Standard etabliert.
Velero sichert zwei Dinge gleichzeitig: die Kubernetes-Objekte eines Namespace, also auch die PVC-Definitionen, und optional die Daten der zugehörigen Volumes. Für die Daten stehen dir zwei Wege offen. Unterstützt dein Storage-Treiber CSI-Snapshots, nutzt Velero diese nativ und erstellt einen Snapshot auf Storage-Ebene. Der ist blockkonsistent, aber nicht automatisch anwendungskonsistent: Eine Datenbank mit offenen Transaktionen braucht zusätzlich einen Hook, der sie vor dem Snapshot in einen sauberen Zustand bringt. Und ein CSI-Snapshot liegt in aller Regel beim selben Storage-Anbieter wie das Volume, ersetzt also kein Backup an einen zweiten Ort (Velero-Dokumentation zu CSI-Snapshots). Fehlt diese Unterstützung, kopiert Velero die Dateien über ein eingebautes Dateisystem-Backup, was langsamer ist, aber mit praktisch jedem Storage-Typ funktioniert.
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: taeglich-namespace-backup
namespace: velero
spec:
schedule: "0 4 * * *"
template:
includedNamespaces:
- produktion
snapshotVolumes: true
ttl: 720h0m0s
storageLocation: hetzner-object-storage
Dieses Schedule-Objekt legt täglich um vier Uhr ein Backup des Namespace produktion an, inklusive Volumes, mit einer Aufbewahrung von 30 Tagen. Die storageLocation verweist auf eine zuvor angelegte BackupStorageLocation, die auf deinen S3-kompatiblen Speicher zeigt, bei mir liegt das auf Hetzner Object Storage. Verschlüsselung regelst du dabei auf zwei Ebenen: einmal über die Zugriffsrechte auf den Bucket selbst, einmal optional über eine serverseitige Verschlüsselung des Objektspeichers.
Restore üben, bevor du ihn brauchst
Ein Backup, das du nie wiederhergestellt hast, ist eine Vermutung, kein Backup. Der einzige Test, der wirklich zählt, ist ein vollständiger Restore in eine isolierte Umgebung: ein separater Namespace oder, besser noch, ein separater Test-Cluster, in dem du das Backup einspielst und prüfst, ob die Anwendung mit den wiederhergestellten Daten tatsächlich startet.
Für Velero bedeutet das konkret einen velero restore create gegen ein bestehendes Backup, mit einem --namespace-mappings, das den Namespace beim Restore umbenennt, damit du nicht versehentlich die Produktionsumgebung überschreibst. Für den etcd-Snapshot heißt das, den Restore mindestens einmal an einem Wegwerf-Cluster durchzuspielen, damit du im echten Notfall weißt, welche Schritte in welcher Reihenfolge kommen und wie lange sie dauern. Ich lege diesen Test-Restore als wiederkehrenden Job in einer separaten Testumgebung an, wie in Kubernetes Jobs und CronJobs erklärt beschrieben, damit die Übung nicht in Vergessenheit gerät.
Für die Zeitpläne selbst hat sich bei mir eine einfache Faustregel bewährt: etcd-Snapshots mehrmals täglich, weil sie klein und schnell sind, Volume-Backups einmal täglich außerhalb der Hauptnutzungszeit, weil sie mehr Last erzeugen, und eine Aufbewahrung, die sich an deiner tatsächlichen Wiederherstellungsfrist orientiert, nicht an einem beliebig gewählten Wert.
Häufige Fragen
Sichert Velero auch etcd?
Nein. Velero sichert Kubernetes-Objekte und optional die Daten von Volumes, aber nicht den internen Zustand von etcd. Für die Control-Plane brauchst du zusätzlich einen etcd-Snapshot, beide Sicherungen ergänzen sich, keine ersetzt die andere.
Brauche ich Velero, wenn ich schon GitOps nutze?
Für die Manifeste selbst kaum, denn die liegen mit GitOps ohnehin in einem Repository und lassen sich von dort erneut ausrollen. Sobald deine Anwendungen aber Daten in Persistent Volumes speichern, zum Beispiel eine Datenbank, brauchst du Velero oder ein vergleichbares Werkzeug trotzdem, weil Git keine Laufzeitdaten enthält.
Wie sichere ich eine Persistent Volume Claim in Kubernetes?
Direkt sicherst du keine PVC, sondern das Volume dahinter. Unterstützt dein Storage-Treiber CSI-Snapshots, kannst du darüber einen Snapshot des Volumes auf Storage-Ebene erstellen, den Velero automatisch mit anstößt. Anwendungskonsistent ist er damit noch nicht, dafür braucht eine Datenbank einen passenden Hook. Ohne CSI-Unterstützung bleibt ein Dateisystem-Backup der einzige Weg.
Wie oft sollte ich mein Cluster sichern?
Das hängt von deiner Änderungsrate ab, nicht von einer allgemeinen Regel. Als Anhaltspunkt aus meiner eigenen Praxis: etcd mehrmals täglich, weil der Snapshot klein und schnell ist, Volumes mindestens einmal täglich. Wichtiger als die Frequenz ist, dass du überhaupt regelmäßig testest, ob ein Restore gelingt.
Welche Kubernetes Backup Lösungen gibt es neben Velero?
Velero ist der verbreitetste Ansatz, weil er Objekte und Volumes in einem Werkzeug kombiniert. Daneben kannst du CSI-Snapshots auch direkt über deinen Storage-Treiber ansteuern, ohne Velero dazwischen, oder Dateisystem-Werkzeuge wie Kopia oder Restic für reine Datei-Backups einsetzen. Für den etcd-Anteil bleibt der native Snapshot-Befehl in jedem Fall die richtige Wahl.
Wie du weitermachst
Bevor du dich um Backups kümmerst, lohnt sich ein Blick auf die Frage, wo dein Cluster überhaupt läuft: Auf Kubernetes on-premise oder Cloud? gehe ich darauf ein, welche Backup-Verantwortung bei dir bleibt und welche ein Anbieter übernimmt. Und wer die Grundlagen von Volumes noch einmal nachlesen will, findet sie in Persistent Volumes und PVC in Kubernetes.
Mein Vorschlag für diese Woche: Richte, falls noch nicht geschehen, einen automatisierten etcd-Snapshot ein, lege ein Velero-Schedule für deinen wichtigsten Namespace an und plane einen Termin für den ersten Test-Restore, am besten noch bevor du ihn wirklich brauchst.
Ausführlich mit allen Beispielen zu Persistent Volumes und dem Zusammenspiel mit StatefulSets steht das in Kapitel 6 meines Kubernetes-Praxisbuchs bei Rheinwerk.