Containerized Workloads: Deep Dive into Resilient Backup Strategies (Velero, CSI, and Volume Snapshot Integration)
Dieser Deep Dive beleuchtet die komplexen Herausforderungen der Sicherung von Zustand und Konfiguration in Container-Orchestrierungsumgebungen (Fokus: Kubernetes). Wir untersuchen die Architektur hinter anwendungs-konsistenten Backups mithilfe von Velero, CSI-Treibern und Pre/Post-Backup Hooks, um einen robusten DR-Plan zu gewährleisten.
# Container Backup – Sicherung von Kubernetes und Zustand (Velero Deep Dive)
TL;DR / Management Summary Traditionelle Sicherungsmethoden versagen bei Kubernetes, da sie weder den Cluster-Zustand (ETCD) noch die verteilten Persistent Volumes (PVs) koordiniert erfassen. Wir benötigen einen Orchestrator. Velero (früher Heptio Ark) ist der De-facto-Standard für anwendungs-konsistente Backups in K8s. Es sichert Cluster-Ressourcen (Deployments, Services, ConfigMaps) in Object Storage und orchestriert volumenbasierte Snapshots über das CSI-API. Nutzen Sie Velero immer für zustandsbehaftete K8s-Workloads, um einen zuverlässigen Recovery Point Objective (RPO) und Recovery Time Objective (RTO) zu erreichen.
# 1. Einführung & Architektur
Die Sicherung einer modernen Microservice-Architektur ist weit komplexer als die Sicherung einer einzelnen VM. Wir müssen den globalen Zustand des Clusters (ETCD) sowie die lokalen Zustände der Anwendungen (Persistent Volumes) im Moment der Sicherung synchronisieren.
# Warum brauchen wir das?
- Problemstellung aus der Praxis: Container sind per Definition ephemer. Die Konfiguration (YAMLs, Secrets) und der Cluster-Zustand sind auf ETCD gespeichert, während die Nutzdaten auf externen Speichern (NFS, Ceph, Cloud-Volumes) liegen. Ein einfaches Dateisystem-Backup des Worker-Nodes sichert nur den Host, nicht die Applikation.
- Anwendungs-Konsistenz (Application Consistency): Dies ist der kritischste Aspekt. Ein Crash-konsistentes Backup (ein einfacher Snapshot des Blockspeichers) reicht nicht aus, wenn eine Datenbank gerade eine Transaktion durchführt. Wir benötigen Mechanismen, um die Anwendung (z.B. Postgres) anzuweisen, alle Daten auf die Disk zu flushen und I/O temporär zu stoppen (Quiescing), bevor der Snapshot erstellt wird.
# Vergleich mit Alternativen
| Methode | Ziel | Konsistenz | Ideal für |
|---|---|---|---|
Native Tools (e.g., docker export) |
Einzelne Container | Crash-Konsistent | Entwicklung/Einzelsysteme |
| Traditional VM/Host Backup | Host OS, Container Runtime Files | Datei-Konsistent | Nicht anwendbar für K8s |
| Velero + CSI Snapshots | Cluster-Zustand & PVs | Anwendungs-Konsistent | Produktions-K8s (HA) |
| Operator-level Backup | Einzelne Datenbank-Instanz | Hoch (Log-Shipping) | Spezifische Datenbanken (z.g. CockroachDB Operator) |
# Architektur-Diagramm (Kernel- und Orchestrierungssicht)
Velero fungiert als der zentrale Orchestrator. Es arbeitet auf der Ebene der Kubernetes API und nutzt die Standard-CRDs (Custom Resource Definitions) für die Interaktion mit dem Speicher.
# Der Velero/CSI Backup-Stack
graph TD
A[K8s API Server] -->|Watch List| B(Velero Controller Pod);
B -->|1. Backup Request (CRD)| C{Application Pod (e.g. Postgres)};
C -->|2. Pre-Backup Hook (Exec)| D[Quiescing/Flush Data];
B -->|3. Create VolumeSnapshot (CRD)| E(CSI Driver);
E -->|4. Request Block Snapshot| F[Storage Backend (Cloud/On-Prem)];
B -->|5. Store YAML Definitions| G[Object Storage (S3/Azure Blob)];
D -->|6. Post-Backup Hook (Exec)| H[Resume I/O];
subgraph K8s Control Plane
A
end
subgraph Data Plane / External
E
F
G
end
style B fill:#f9f,stroke:#333,stroke-width:2px
- Kernel-Sicht (Block Layer): Der CSI-Treiber (Container Storage Interface) übersetzt die Kubernetes-Anforderung (
VolumeSnapshotCRD) in einen spezifischen API-Aufruf für das zugrunde liegende Speichersystem. Auf Linux-Ebene wird der Snapshot typischerweise vom Storage-Provider selbst durchgeführt, nicht vom Linux-Kernel (im Gegensatz zu LVM-Snapshots). Die Datenintegrität auf Host-Ebene wird durch das Quiescing sichergestellt, das den Applikations-Buffer leert.
# 2. Installation & Grundkonfiguration (Praxis)
Wir richten Velero für einen AWS EKS Cluster ein, wobei wir S3 für die Speicherung der Metadaten und CSI-Snapshots für die Speicherung der Volumes nutzen.
# Voraussetzungen
- K8s Cluster: Version 1.17+ (für Volume Snapshot API v1).
- Object Storage: Ein S3-Bucket (mit Versioning aktiviert – dringend empfohlen).
- CSI Treiber: Der entsprechende Treiber muss installiert sein (z.B. AWS EBS CSI Driver).
- RBAC: Ein IAM Role/Service Account, das Lese-/Schreibzugriff auf S3 und die Berechtigung zum Erstellen von EBS Snapshots hat.
# Schritt-für-Schritt Setup (Der “Production Ready Path”)
# 2.1. Installation des CSI Snapshot Controllers
Wir benötigen die Komponenten, die die CSI CRDs verwalten:
# Installiere die VolumeSnapshot CRDs
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
# Installiere den externen Snapshot Controller (muss im Cluster laufen)
# Dies ist die Komponente, die auf die VolumeSnapshot CRDs reagiert.
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml
# 2.2. Installation von Velero
Wir verwenden das Velero CLI für die Erstinstallation, da es die benötigten IAM-Policies automatisch generiert (oder wir nutzen Helm für eine sauberere IaC-Integration).
# 1. Konfiguriere das S3 Bucket und das IAM Role
BUCKET_NAME="my-prod-k8s-backups-401"
AWS_REGION="eu-central-1"
# Wichtig: Spezifiziere den 'provider' (aws) und den 'plugin' für CSI.
# Wir nutzen '--use-volume-snapshots' um die CSI Snapshot API zu aktivieren.
velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.7.1,velero/csi-plugin:v0.4.0 \
--bucket $BUCKET_NAME \
--secret-file ./velero_aws_credentials \
--backup-location-config region=$AWS_REGION \
--use-volume-snapshots \
--snapshot-location-config region=$AWS_REGION,insecureSkipTLSVerify=true \
--wait
# 2.3. Erstellen einer VolumeSnapshotClass
Velero benötigt eine VolumeSnapshotClass (VSC), die dem CSI-Treiber sagt, wie der Snapshot erstellt werden soll.
# vs-ebs.yaml
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: ebs-csi-snapshot-class
driver: ebs.csi.aws.com # Wichtig: Muss dem installierten CSI-Treiber entsprechen!
deletionPolicy: Retain # Oder Delete, je nach DR-Strategie
parameters:
# Optional: Spezifische Parameter, z.B. für Tags
csi.storage.k8s.io/snapshotter-secret-name: ""
csi.storage.k8s.io/snapshotter-secret-namespace: ""
# Anwendung
kubectl apply -f vs-ebs.yaml
# Konfiguriere Velero, diese VSC zu nutzen
velero snapshot-location create default-ebs-location \
--provider aws \
--config region=$AWS_REGION,snapshotLocation=ebs-csi-snapshot-class
Erfahrungstipp: Die
VolumeSnapshotClassmuss in derBackupStorageLocationvon Velero referenziert werden. Ist die Klasse falsch, schlägt der Volume-Teil des Backups still fehl, während die Metadaten gesichert werden. Dies ist eine häufige Fehlerquelle!
# 3. Deep Dive: Konfiguration für Profis
# Application Consistency (Pre/Post Hooks)
Um eine Datenbank (z.B. MySQL) sauber zu sichern, muss der I/O gestoppt oder ein konsistentes Dump erstellt werden. Hierfür nutzen wir Velero’s PreBackupHooks.
Wir definieren, dass vor dem Snapshot ein Befehl im Datenbank-Container ausgeführt wird (fsfreeze oder FLUSH TABLES WITH READ LOCK).
apiVersion: velero.io/v1
kind: Backup
metadata:
name: mysql-consistent-daily
namespace: velero
spec:
# Wähle die zu sichernden Ressourcen und Namespaces
includedNamespaces:
- database-ns
# Definiere die Hooks (Aktionsskripte)
hooks:
# 1. Quiescing Phase (VOR dem Snapshot)
# Die Hook target-referenziert den Container, in dem der Befehl ausgeführt werden soll.
pre:
- exec:
container: mysql-server # Containername im Pod
command:
- /bin/sh
- -c
- "mysql -uroot -p$MYSQL_ROOT_PASSWORD -e 'FLUSH TABLES WITH READ LOCK;'"
# Velero hält den Backup-Prozess an, bis dieser Befehl erfolgreich ist.
onError: Fail
# Wartezeit vor Timeout
timeout: 5m
# 2. Resume Phase (NACH dem Snapshot)
post:
- exec:
container: mysql-server
command:
- /bin/sh
- -c
- "mysql -uroot -p$MYSQL_ROOT_PASSWORD -e 'UNLOCK TABLES;'"
onError: Continue # Wenn das Entsperren fehlschlägt, ist das Backup dennoch gültig.
# Performance Tuning & Skalierung
- Parallelität: Velero kann mehrere Backups gleichzeitig verarbeiten. Standardmäßig werden Backups seriell ausgeführt. Bei großen Clustern mit vielen PVs sollte die Einstellung zur Parallelität (oder die Aufteilung in kleinere Backup-Schedules pro Namespace) geprüft werden.
- Datentransfer-Methode (Restic vs. CSI):
- CSI Snapshot: (Bevorzugt) Block-basiert, extrem schnell, entlastet den Cluster, da die Arbeit vom Storage-Backend erledigt wird.
- Restic: File-System-basiert, nutzt einen Sidecar-Container, um Daten von der Applikation über das Netzwerk in S3 zu streamen. Ist zwingend notwendig, wenn der zugrundeliegende Speicher keinen CSI-Treiber oder kein Snapshot-Feature unterstützt (z.B. NFS). Restic ist langsamer und I/O-intensiver für die Worker Nodes.
# Hardening & Security
Velero benötigt weitreichende Berechtigungen (cluster-admin level), um alle Ressourcen im Cluster sichern zu können. Dies macht es zu einem primären Ziel:
- Scope-Limitation: Wenn möglich, Velero auf einen oder wenige Namespaces beschränken (
includedNamespacesundincludedResources). - Sicherheitsrichtlinien: Die Credentials (S3 Access Key) sollten nur Lese-/Schreibzugriff auf diesen einen Backup-Bucket haben. Nutzen Sie, wo möglich, Cloud-Provider-spezifische Authentifizierung (z.B. AWS IRSA/IAM Roles for Service Accounts) anstelle von statischen Keys.
- Verschlüsselung: Object Storage (S3) sollte immer mit Server-Side Encryption (SSE-KMS) konfiguriert werden, um die Vertraulichkeit der gesicherten YAML-Metadaten und der Restic-Daten zu gewährleisten.
# 4. Day-2 Operations: Wartung & Alltag
# Typische Tasks
# Erstellen eines geplanten Backups (Schedule)
Statt manueller Backup-Ressourcen definieren wir Schedule CRDs:
# Erstellt einen täglichen Backup-Schedule um 03:00 UTC
velero create schedule daily-full \
--schedule "0 3 * * *" \
--include-namespaces prod-app,prod-db \
--ttl 720h0m0s \
--use-volume-snapshots
# Wiederherstellung (Restore)
Das Restore-Prozedere muss regelmäßig getestet werden (Failover-Drill!).
# 1. Sicherstellen, dass das Backup existiert
velero get backups
# 2. Restore starten (Wiederherstellung aller gesicherten Ressourcen)
velero restore create restore-20230515 --from-backup daily-full-20230515123456
# Spezifischer Restore: Nur eine bestimmte Ressource wiederherstellen
# Sehr nützlich, wenn nur eine ConfigMap aus Versehen gelöscht wurde.
velero restore create restore-configmap-only \
--from-backup daily-full-20230515123456 \
--include-resources configmaps \
--include-namespaces dev-tools
# Migration auf neue Hardware (Cluster Migration)
Velero ist das ideale Tool für Cluster-Migrationen (Blau/Grün). Sichern Sie den Zustand des alten Clusters (Source), installieren Sie Velero auf dem neuen Cluster (Target) und stellen Sie das Backup wieder her. Achtung: PVs (EBS, Azure Disks) sind oft zonal oder regional gebunden. Bei einem Wechsel der Cloud-Region müssen Sie die StorageClass und VolumeSnapshotClass entsprechend anpassen.
# Automatisierung (Ansible/Terraform)
Wir verwenden Terraform, um die Velero-Komponenten (S3 Bucket, IAM Role) und die K8s-Ressourcen (Installation über Helm) idempotenterweise zu verwalten.
# Terraform / Helm Provider Beispiel (Auszug)
resource "helm_release" "velero" {
name = "velero"
repository = "https://vmware-tanzu.github.io/helm-charts"
chart = "velero"
namespace = "velero"
version = "2.31.0"
values = [
templatefile("${path.module}/velero-values.yaml", {
bucket_name = aws_s3_bucket.backup_bucket.id
aws_region = var.aws_region
})
]
}
# In velero-values.yaml würden die AWS Secret Configs und Plugins definiert.
resource "kubernetes_custom_resource" "velero_schedule" {
# Definiert den täglichen Backup-Schedule als IaC
api_version = "velero.io/v1"
kind = "Schedule"
metadata {
name = "daily-prod-schedule"
namespace = "velero"
}
# ... spec definition ...
}
# 5. Troubleshooting & “War Stories”
Die goldene Regel: Die Zeit, die Sie für das Testen eines Restores aufwenden, ist nie verschwendet. Ein Backup ist wertlos, wenn der Restore fehlschlägt.
# Top 3 Fehlerbilder
# 1. Symptom A: Backup hängt in PartiallyFailed oder New
- Fehlermeldung: Im
velero backup describe <backup-name>sehen Sie Fehler imVolumeSnapshotBereich. - Ursache: Häufigste Ursache ist eine falsch konfigurierte
VolumeSnapshotClassoder unzureichende Berechtigungen des CSI-Treibers auf dem Host/Cloud-Provider (z.B. Velero/CSI kann keinen EBS-Snapshot erstellen). Auch Pre-Backup Hooks, die fehlschlagen, verursachen einenPartiallyFailedStatus. - Lösung: Prüfen Sie die Velero-Controller-Logs (
kubectl logs -n velero deploy/velero) und die Logs des CSI Snapshot Controller. Stellen Sie sicher, dass die IAM/RBAC-Rolle Snapshots erstellen und löschen darf.
# 2. Symptom B: Restore schlägt fehl, weil PVCs nicht gebunden werden
- Fehlermeldung: Pods bleiben im Status
Pending, PVCs bleiben im StatusPendingoderFailedBinding. - Ursache: Beim Restore wird versucht, den gesicherten
VolumeSnapshotContentwieder an einen PVC zu binden. Dies schlägt oft fehl, wenn die Speicherklasse des Ziel-Clusters nicht exakt mit der gesicherten übereinstimmt, oder wenn die Zone nicht verfügbar ist (bei zonal gebundenen PVs). - Lösung: Nutzen Sie
velero restore create --restore-volumes=falseund erstellen Sie die PVCs manuell mit der korrekten Ziel-StorageClass, bevor Sie den Restore der Pods starten. Alternativ verwenden Sie Restoresresource_modifierum die StorageClass on-the-fly zu ändern.
# 3. Symptom C: Hohe CPU-Last auf Worker Nodes während des Backups
- Symptom: Performance-Einbruch im Cluster, Latenz steigt.
- Analyse: Prüfen Sie, ob Sie Restic für die Volumes nutzen. Restic ist CPU-intensiv, da es die Daten dedupliziert, komprimiert und verschlüsselt.
- Lösung: Priorisieren Sie, wo immer möglich, CSI Volume Snapshots. Wenn Restic unvermeidbar ist, planen Sie die Backups in Zeiten geringer Last und prüfen Sie die Restic-Parallelitätseinstellungen.
# Recovery Szenarien
# Wiederherstellung nach Metadaten-Corruption (ETCD-Ausfall)
Wenn der K8s-Cluster vollständig ausfällt (z.B. ETCD-Corruption), ist das Velero Backup in S3 der letzte Rettungsanker.
- Neuen Cluster aufsetzen: Installieren Sie ein leeres K8s-Cluster der gleichen Version.
- Velero installieren: Installieren Sie Velero mit den gleichen Credentials und S3-Bucket-Informationen.
- Metadaten-Sync: Velero liest automatisch alle gesicherten Metadaten aus dem S3-Bucket ein.
- Restore: Führen Sie den Restore des letzten gültigen Backups durch. Velero erstellt alle Deployments, Services und PVCs neu und bindet die CSI-Snapshots als neue PVs ein.
# 6. Monitoring & Alerting
Ein Backup, das im Stillen fehlschlägt, ist das größte DR-Risiko. Die Überwachung von Velero ist kritisch.
# Metriken (KPIs)
Velero stellt einen Prometheus-Exporter bereit. Die wichtigsten zu überwachenden Kennzahlen sind:
velero_backup_attempt_total&velero_backup_success_total: Zur Berechnung der Erfolgsrate.velero_backup_last_successful_timestamp: Wie alt ist das letzte erfolgreiche Backup?velero_backup_restore_last_success_timestamp: Verfolgt erfolgreiche Restore-Tests.velero_restic_repository_status_total: Zeigt den Status der Restic-Repositories (wichtig für File-System Backups).
# Alerting-Regeln (Prometheus/Alertmanager)
| Regel | Abfrage (PromQL) | Schweregrad | Beschreibung |
|---|---|---|---|
| Backup Failed | velero_backup_attempt_total{status="Failed"} - velero_backup_success_total{status="Succeeded"} > 0 |
CRITICAL | Ein Backup ist fehlgeschlagen (muss sofort untersucht werden). |
| Stale Backup | time() - velero_backup_last_successful_timestamp{schedule="daily-full"} > 28h |
HIGH | Das letzte erfolgreiche Backup ist älter als die definierte RPO (z.B. 24h + Puffer). |
| Restore Failure | velero_restore_attempt_total{status="Failed"} > 0 |
CRITICAL | Ein Test-Restore oder ein Produktiv-Restore ist fehlgeschlagen. |
| Repository Pending | sum(velero_restic_repository_status_total{status="NotReady"}) > 0 |
WARNING | Ein Restic Repository konnte sich nicht initialisieren (betrifft File-System-Backups). |
# 7. Fazit & Empfehlung
Velero ist für die meisten Kubernetes-Setups die robusteste und flexibelste Lösung, da es sowohl den Cluster-Zustand als auch die Anwendungskonsistenz über Hooks abdeckt.
Wann würde ich es nicht einsetzen?
- Extrem große Datensätze (Petabytes): Wenn Sie extrem große, hochfrequente Datenbanken haben, ist ein dedizierter, Streaming-fähiger Datenbank-Operator (z.B. PostgreSQL Operator mit WAL Archiving) oft effizienter und liefert ein besseres RPO als das blockbasierte CSI-Snapshot-Modell.
- Legacy-Umgebungen ohne CSI: Wenn Sie nur NFS-Mounts ohne CSI-Treiber oder Snapshot-Funktionalität verwenden, müssen Sie Restic nutzen, was zu hohem I/O-Overhead führt. Hier kann ein einfacher, extern orchestrierter
rsyncauf dem NFS-Server manchmal performanter sein.
Ausblick: Der Trend geht zu immer engerer Integration. Künftige Versionen werden wahrscheinlich noch stärker auf das VolumeSnapshot CRD setzen, und möglicherweise sehen wir eine native Integration von ETCD-Backup-Strategien, die von Cloud-Providern verwaltet werden. Unabhängig davon bleibt die Notwendigkeit der Anwendungs-Konsistenz durch Hooks die Verantwortung des SysAdmins.
# Anhang: Cheatsheet (Velero)
| Befehl | Zweck | Beispiel |
|---|---|---|
velero install |
Velero-Deployment initialisieren. | velero install --provider aws --bucket mybucket ... |
velero get backups |
Status aller Backups anzeigen. | velero get backups --details |
velero describe backup |
Detaillierte Log-Analyse eines Backups. | velero describe backup prod-daily-001 |
velero create backup |
Manuelles Ad-Hoc Backup starten. | velero create backup manual-test --include-namespaces db-ns |
velero create schedule |
Geplante Sicherung definieren. | velero create schedule hourly --schedule "@every 1h" |
velero restore create |
Wiederherstellung starten. | velero restore create r-test --from-backup last-good |
velero get restores |
Status aller Wiederherstellungen. | velero get restores |
velero logs |
Logs des Velero Controllers ausgeben. | velero logs --follow |
velero create restore |
Einzelne Ressource wiederherstellen. | velero create restore r-cm --include-resources configmaps |
kubectl get vs |
CSI VolumeSnapshots prüfen. | kubectl get volumesnapshots -A |
# Referenzen
- Velero Upstream Documentation
- Kubernetes CSI Volume Snapshot Documentation
- Velero Restic Integration Deep Dive
- AWS EBS CSI Driver GitHub Repository (Für spezifische Treiber-Konfigurationen)