Veröffentlicht am

Kubernetes Backup Datenbank: Velero, Postgres, MySQL

Teilen:
Authors

Kubernetes Backup für Datenbanken: Velero, Postgres, MySQL

TL;DR

  • Velero sichert Kubernetes-Ressourcen und Persistent Volumes. Beides ist notwendig, für eine Datenbank reicht keines allein.
  • Ein Volume-Snapshot einer laufenden Postgres- oder MySQL-Instanz kann inkonsistent sein. Vor dem Backup einen Dump per Hook erzeugen.
  • Backups ohne regelmäßige Restore-Tests sind wertlos. Mindestens monatlich in einem separaten Namespace prüfen.
  • Kritische Datenbanken stündlich, alles andere täglich. Das Intervall folgt dem RPO, nicht dem Gefühl.
  • Backup-Ziel: S3-kompatibler Speicher außerhalb des Clusters, sonst fällt die Sicherung mit dem Rechenzentrum aus.

Warum ein Volume-Backup die Datenbank nicht rettet

Ein Kubernetes-Cluster hat zwei Datenarten: den API-Zustand (Deployments, Services, Secrets, CRDs) und die Persistent Volumes. Viele Teams sichern nur eines und merken es beim Restore.

Für Postgres und MySQL kommt eine dritte Schicht dazu. Ein Dateisystem-Snapshot mitten in einem Write kann eine kaputte Datendatei liefern, die der Server nicht öffnet. Velero löst den Cluster-Teil: API-Export plus Volume über Kopia oder einen Storage-Snapshot. Den konsistenten Dump muss ein Pre-Hook erzeugen, bevor Velero das Volume liest.

Klassische VM-Snapshots helfen nicht. Ohne etcd-Zustand ist der Node nutzlos, und ohne Dump ist das Volume eine Wette.

Velero installieren

Über die CLI, mit S3-kompatiblem Backend:

curl -fsSL https://github.com/vmware-tanzu/velero/releases/download/v1.15.0/velero-v1.15.0-linux-amd64.tar.gz | tar xz
sudo mv velero-v1.15.0-linux-amd64/velero /usr/local/bin/

cat <<EOF > /tmp/credentials-velero
[default]
aws_access_key_id=IHRE_ACCESS_KEY
aws_secret_access_key=IHRE_SECRET_KEY
EOF

velero install \
  --provider aws \
  --plugins velero/velero-plugin-for-aws:v1.11.0 \
  --bucket kubernetes-backups \
  --secret-file /tmp/credentials-velero \
  --backup-location-config region=eu-central-1,s3ForcePathStyle=true,s3Url=https://s3.eu-central-1.amazonaws.com \
  --use-node-agent \
  --default-volumes-to-fs-backup

kubectl get pods -n velero
velero version

--use-node-agent schaltet das Dateisystem-Backup ein. Das brauchen Volumes ohne nativen Snapshot. Für die Datenbank ist das der zweite Schritt, nach dem Dump.

Frequenz nach RPO

WorkloadRPOFrequenzAufbewahrung
Datenbanken1 Stundestündlich7 Tage
Stateful Services4 Stunden4× täglich14 Tage
Stateless APIs24 Stundentäglich7 Tage
Cluster-Config24 Stundentäglich30 Tage
velero schedule create production-hourly \
  --schedule="0 * * * *" \
  --include-namespaces production \
  --ttl 168h

velero schedule create cluster-daily \
  --schedule="0 2 * * *" \
  --include-cluster-resources=true \
  --ttl 720h

Datenbank-Backup: Dump vor dem Volume

Postgres, konsistenter Dump in ein Verzeichnis auf dem Volume, das Velero danach mitnimmt:

apiVersion: v1
kind: Pod
metadata:
  name: postgres-0
  annotations:
    pre.hook.backup.velero.io/command: '["/bin/bash", "-c", "PGPASSWORD=$POSTGRES_PASSWORD pg_dump -U postgres -Fc -d myapp > /backup/dump.dump"]'
    pre.hook.backup.velero.io/timeout: "120s"

MySQL analog:

annotations:
  pre.hook.backup.velero.io/command: '["/bin/bash", "-c", "mysqldump -u root -p$MYSQL_ROOT_PASSWORD --single-transaction --all-databases > /backup/dump.sql"]'
  pre.hook.backup.velero.io/timeout: "300s"

--single-transaction bei InnoDB, sonst sperrt der Dump die Tabellen. Den Dump nicht nach dem Backup löschen, bevor ein Restore ihn einmal benutzt hat. Ein Hook, der die Datei sofort entfernt, sichert eine leere Hülle, sobald Velero das Volume erst nach dem Post-Hook liest. Reihenfolge prüfen: Dump schreiben, Velero lesen, erst dann aufräumen.

Große Datenbanken sprengen das Hook-Timeout. Dann läuft der Dump als CronJob in ein Objektstorage, und Velero sichert nur noch Manifeste und das leere Claim. Zwei Sicherungen, eine davon ist die, die Sie zurückspielen.

Restore testen

velero restore create test-restore \
  --from-backup production-hourly-20260210120000 \
  --namespace-mappings production:restore-test

velero restore describe test-restore --details
kubectl get pods -n restore-test

Danach die Datenbank öffnen und eine Zeile lesen, die nach dem letzten Dump existiert haben muss. kubectl get pods sagt nur, dass der Container startet. Wenn der Restore länger dauert als das RTO, ist die Frequenz egal.

RPO, RTO, zweites Ziel

MetrikBedeutungWoran Sie es sehen
RPOWie viel Datenverlust Sie akzeptierenAbstand zwischen letztem Dump und Ausfall
RTOWie lange der Dienst weg sein darfZeit bis die Anwendung wieder schreibt
ErfolgsquoteOb der Job wirklich liefAlert, nicht das Dashboard von letzter Woche

Das Backup-Ziel darf nicht im selben Rechenzentrum sterben wie der Cluster. Ein Bucket in derselben Region für schnelle Restores, ein zweiter bei einem anderen Anbieter für den Ausfall der Region. Velero kann mehrere BackupStorageLocations. Eine reicht nicht.

Was Velero nicht ersetzt

Veleroetcd-SnapshotDump (pg_dump, mysqldump)
API-Objekteausgewählte Namespacesgesamter Cluster-Zustandnein
Volume-Dateienja, mit Node-Agentneinnein
Konsistente Datenbanknur mit Hookneinja
Managed Kubernetesjader Anbieter sichert etcdja, Ihre Daten
Self-managedjazusätzlichja

Auf AKS, EKS und GKE brauchen Sie kein eigenes etcd-Backup. Den Datenbank-Dump brauchen Sie trotzdem. Auf kubeadm, k3s oder RKE2 beide: Velero für die Anwendung, etcd-Snapshot für den Worst Case der Control Plane.

Vier Fehler, die das Backup wertlos machen

  1. Nur Manifeste, keine Volumes. Ohne --default-volumes-to-fs-backup fehlen die Dateien.
  2. Kein Alert, wenn der Job fehlschlägt. Velero legt Metriken auf Port 8085. Ein stiller Fehler ist schlimmer als kein Backup.
  3. Restore nie geprobt. Das ist der teure Fall, und er fällt erst im Incident auf.
  4. Aufbewahrung kürzer als die Zeit, in der Sie einen korrupten Stand bemerken. Sieben Tage reichen nicht, wenn der Fehler in der Anwendung eine Woche unbemerkt bleibt.

Secrets liegen im Backup. Bucket nicht öffentlich, serverseitig verschlüsselt, Object Lock gegen Löschen. Der Velero-Account darf nur diesen Bucket.

Wenn Pods nicht starten

Operative Stoerungen (CrashLoop, ImagePull, Pending) klaeren Sie Schritt fuer Schritt im Guide Pod startet nicht – von dort verzweigen Exit-Codes, RBAC und Netzwerk-Checks.

Fazit

Kubernetes-Backup für eine Datenbank ist Dump plus Volume plus Restore-Probe. Velero übernimmt Cluster und Volume. Postgres und MySQL brauchen den Hook oder einen eigenen CronJob. Ohne monatlichen Test wissen Sie nicht, ob davon etwas zurückkommt.

Wenn die bestehende Installation geprüft werden soll: Kontakt. Die Härtung des Clusters daneben steht in der Security-Checkliste.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen