secure k8 s

Backups

Summary: Backup- und Restore-Strategie für OpenBao — warum man sichert, was man sichert, wie man mit Integrated Storage Snapshots zieht und zurückspielt, und wie das Ganze in VM- und Kubernetes-Umgebungen automatisiert wird.

Sources: raw/docs/concepts/storage.md, raw/docs/commands/operator/raft.md, raw/docs/platform/k8s/helm/examples/snapshot-cronjob.md, raw/docs/configuration/storage/raft.md, raw/docs/internals/integrated-storage.md.

Last updated: 2026-05-19.


Was gesichert werden muss

Ein vollständiges Backup besteht immer aus zwei Teilen (source: raw/docs/concepts/storage.md):

  1. Die verschlüsselten Daten aus dem Storage-Backend (Raft-DB bzw. Postgres-Zeilen).
  2. Die Server-Konfiguration, die Management-Skripte und die Information, wie die Barrier entschlüsselt wird — also Seal-Konfig, Transit-Token bzw. KMS-Key-Referenz, TLS-Material, user-installed Plugins.

Ohne Teil 2 ist Teil 1 wertlos. Ein restaurierter Snapshot enthält nur Barrier-verschlüsselte Daten; ohne den passenden Seal lässt sich daraus nichts unsealen (siehe seal-unseal, storage).

Wofür Backups da sind — und wofür nicht

OpenBao trennt sauber zwischen Hochverfügbarkeit und Disaster-Recovery; Backups gehören in die zweite Kategorie (source: raw/docs/concepts/storage.md).

Wofür Backups gut sind:

  • Vor Upgrades. OpenBao garantiert keine Storage-Rückwärtskompatibilität — ohne Snapshot ist ein Downgrade nicht möglich (siehe upgrading).
  • Vor jeder größeren Cluster-Änderung — Rotationen, Seal-Migrationen, größere Policy-Refactorings.
  • Vor Schreiboperationen auf /sys-Endpoints (außer /sys/leases, /sys/namespaces, /sys/tools, /sys/wrapping, /sys/policies, /sys/pprof).
  • Datacenter-Ausfall. Selbst ein gut gespanntes HA-Cluster kann eine ganze Region nicht überleben — ein Snapshot, der außerhalb der Region liegt, schon.
  • Versehentliches Löschen oder Überschreiben. Mit der Einschränkung: ein Restore auf den Stand von 5 Uhr früh, ausgeführt um 10 Uhr, verliert die Schreibvorgänge der dazwischenliegenden fünf Stunden. (Lucy Davinhart hat dazu auf einer HashiConf einen lehrreichen “Oh no, I deleted my Vault secret”-Talk gehalten — siehe Referenz in raw/docs/concepts/storage.md.)

Wofür Backups nicht da sind:

  • Schutz gegen einzelne Maschinen-Ausfälle. Dafür gibt es high-availability. Ein Cluster über mehrere AZs ist die richtige Antwort, nicht ein Snapshot.
  • Als Ersatz für HA. Wer “Backup statt HA” baut, kauft sich Datenverlust und Downtime gleichzeitig ein.

Die Faustregel aus der Upstream-Doku: Backups und HA sind beide kritische Bausteine, keine Alternativen.

Snapshot-Mechanik (Integrated Storage)

Wenn Raft als storage läuft, sind Snapshots das offizielle Backup-Primitive (siehe raft für die Konsens-Mechanik darunter). Sie sind dank des FSM-on-BoltDB-Designs sehr leichtgewichtig — der Snapshot-Prozess muss im Wesentlichen nur das Raft-Log abschneiden, die Daten liegen ohnehin schon auf der Platte (source: raw/docs/internals/integrated-storage.md).

$ bao operator raft snapshot save raft.snap
$ bao operator raft snapshot restore raft.snap

Wichtige Eigenschaften (source: raw/docs/commands/operator/raft.md):

  • Atomar. Der Snapshot ist ein konsistenter Punkt-in-Zeit-Stand des Clusters, kein File-Tree-Copy.
  • Nicht unterstützt, wenn Raft nur als ha_storage läuft. In diesem Fall kommen die Daten aus dem eigentlichen Storage-Backend (Postgres etc.); dessen Backup-Mechanismen sind dann zu nutzen.
  • Restore überschreibt den Cluster-State mit dem Inhalt des Snapshots. Das ist eine Hard-Replace-Operation, kein Merge.

Die Snapshot-Datei ist barrier-verschlüsselt. Wer sie stiehlt, hat ohne Seal/KMS-Zugriff trotzdem keinen Klartext. Wer sie restoren will, braucht zwingend dasselbe Seal-Material wie zum Zeitpunkt des snapshot save (siehe seal-unseal).

Abgrenzung: Raft-interne vs. operator-getriggerte Snapshots

Nicht verwechseln (source: raw/docs/configuration/storage/raft.md):

WasWer triggertWofür
Raft-interne Snapshots (snapshot_interval, snapshot_threshold, trailing_logs)Raft selbst, automatischLog-Kompaktierung, damit das WAL nicht ewig wächst und neue Follower nicht ewig nachladen
bao operator raft snapshot saveOperatorBackup-File für Disaster-Recovery

Die internen Snapshots sind ein Implementierungsdetail des Konsensus-Algorithmus — die Tuning-Parameter sind unter raft beschrieben. Sie ersetzen ein operator-getriggertes Backup nicht.

Offline vs. Online

Die Upstream-Empfehlung ist eindeutig (source: raw/docs/concepts/storage.md):

  • Idealfall: offline. OpenBao herunterfahren, Datenträger sichern.
  • Realistischer Fall: online. Funktioniert dann zuverlässig, wenn das Storage-Backend atomare Snapshots beherrscht — Integrated Storage tut das, andere Backends (Postgres, Datei-basiert) haben eigene Mechanismen.
  • Wenn das Backend keine atomaren Snapshots kann: nur offline sichern. Online-Backups eines nicht-atomaren Backends ergeben mit hoher Wahrscheinlichkeit einen inkonsistenten und damit unbrauchbaren Stand.

Automatisierung

Es gibt kein eingebautes Schedule-Feature für Snapshots (source: raw/docs/concepts/storage.md). Stattdessen pflegt das OpenBao-Projekt einen separaten Snapshot-Agent (Repo: openbao/openbao-snapshot-agent), der wahlweise per systemd-Timer/Cron auf VMs oder als Kubernetes-CronJob läuft.

VM-Variante

Klassischer Aufbau: bao operator raft snapshot save aus einem systemd-Unit-File heraus, getriggert über Timer; das resultierende Snapshot-File wird in einen externen Bucket (S3 o. ä.) hochgeladen. Details und Beispiel-Units im Snapshot-Agent-Repo.

Kubernetes-Variante (Helm)

Für das K8s-spezifische End-to-End-Runbook (Drei-Schichten-Modell, Restore-Verfahren, Sandbox-Tests, NetworkPolicies, Monitoring): siehe k8s-backups. Der folgende Abschnitt fasst nur den Helm-snapshotAgent-Teil zusammen.

Der Helm-Chart bringt seit Version 0.22.0 einen snapshotAgent mit, der den CronJob für einen ablegt (source: raw/docs/platform/k8s/helm/examples/snapshot-cronjob.md). Minimale values.yaml:

snapshotAgent:
  enabled: true
  schedule: "*/15 * * * *"
  s3CredentialsSecret: "my-s3-credentials"
  config:
    s3Host: "s3.eu-east-1.amazonaws.com"
    s3Bucket: "openbao-snapshots"
    s3Uri: "s3://openbao-snapshots"
    s3ExpireDays: "14"
    baoAuthPath: "kubernetes"
    baoRole: "snapshot"

Dazu braucht es:

  1. Ein vorab angelegtes Kubernetes-Secret mit AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY (Name passt zu s3CredentialsSecret).
  2. Eine OpenBao-Policy, die den Snapshot-Endpoint freigibt:
    path "sys/storage/raft/snapshot" {
      capabilities = ["read"]
    }
  3. Eine Kubernetes-Auth-Role, die ServiceAccount und Namespace des CronJobs an diese Policy bindet:
    $ bao write auth/kubernetes/role/snapshot \
        bound_service_account_names=<SA_NAME> \
        bound_service_account_namespaces=<NS> \
        policies=snapshot \
        ttl=1h

Verifikation per kubectl logs <pod>. Der Job läuft erst, wenn der Cluster initialisiert und unsealed ist — daher beim ersten Bring-up nach k8s-ha-setup vorgehen.

Restore-Verfahren

Restore ist eine seltene und folgenschwere Operation — vor dem Ernstfall mindestens einmal in einer Test-Umgebung üben (siehe Anti-Pattern unten).

Ablauf für Integrated Storage:

  1. Snapshot-File verfügbar machen (aus S3 holen o. ä.).
  2. Seal/KMS-Material bereitstellen. Ohne das identische Seal-Setup wie zum Snapshot-Zeitpunkt kann der Cluster den Inhalt nicht unsealen.
  3. Cluster mit demselben Seal-Setup hochfahren (ein Knoten reicht für den Restore; weitere Voter werden danach beigetreten).
  4. bao operator raft snapshot restore raft.snap auf dem Leader ausführen.
  5. Unseal (siehe seal-unseal).
  6. Weitere Knoten per bao operator raft join beitreten lassen — sie holen sich den State vom neuen Leader (siehe raft).

Wichtiger Caveat aus upgrading: Beim Restore in eine Test-Umgebung dem Test-Cluster den Netzzugriff auf externe Systeme (Datenbanken, Cloud-Provider) wegnehmen — sonst rotiert er Credentials, die das echte Produktiv-Cluster gerade noch benutzt.

Anti-Patterns

  • Snapshot ohne Seal-Backup. Häufigster Fehler. Ohne Seal-Konfiguration / KMS-Zugang ist der schönste Snapshot ein verschlüsselter Datenmüll. Backup-Strategie immer für beide Teile gleichzeitig planen.
  • Backup statt HA. Erkauft sich gleichzeitig Datenverlust und Downtime. Beides braucht es nebeneinander.
  • Snapshot-Speicherort = Produktions-Region. Wenn die Region weg ist, ist auch der Snapshot weg. Off-Region kopieren.
  • Restore nie geübt. Ein nie getesteter Restore ist ein Hoffnungswert, kein Backup. Mindestens einmal vor dem Go-Live in einer Test-Umgebung durchspielen.
  • Snapshots seltener als die /sys-Schreibfrequenz. Vor jeder größeren /sys-Operation gehört ein frischer Snapshot her, nicht der vom letzten Quartal.
  • Backup-Bucket ohne Retention/Verschlüsselung-at-rest. Snapshots enthalten zwar nur Barrier-verschlüsselte Daten, aber Metadaten und die schiere Existenz alter Stände will man trotzdem unter Kontrolle halten — Bucket-Verschlüsselung, ACLs, sinnvolle Expiry (s3ExpireDays o. ä.).
  • raft — Konsens-Mechanik, Snapshot-Tuning-Parameter, Recovery-Workflows
  • storage — Storage-Backends und ihre jeweiligen Backup-Mechanismen
  • seal-unseal — Warum ohne Seal kein Restore funktioniert
  • upgrading — Snapshot-vor-Upgrade als feste Regel
  • k8s-ha-setup — Snapshot-CronJob im Helm-Setup
  • k8s-backups — K8s-spezifisches Backup-/Restore-Runbook (Drei-Schichten-Modell, Sandbox-Tests, Monitoring)
  • high-availability — Backups sind kein HA-Ersatz, gehören aber daneben