TL;DR — Kurzzusammenfassung
etcd Backup und Wiederherstellung für Kubernetes: Snapshot-Methoden, Verifikation, Multi-Node-Restore, kubeadm-Zertifikate, Monitoring und Produktionsskript.
etcd ist das Herzstück jedes Kubernetes-Clusters: ein stark konsistenter, verteilter Schlüssel-Wert-Speicher, der den vollständigen — gewünschten und beobachteten — Zustand Ihres Clusters enthält. Wenn etcd ordnungsgemäß funktioniert, antworten kubectl-Befehle in Millisekunden und Controller reconcilieren kontinuierlich. Wenn etcd ohne Backup verloren geht, ist Ihr Cluster weg — jede Deployment-Definition, jedes Secret, jede RBAC-Richtlinie, jede CRD und jede ConfigMap verschwindet. Dieser Leitfaden behandelt alles, was Sie benötigen, um eine produktionsreife etcd-Backup-und-Wiederherstellungsstrategie aufzubauen.
Voraussetzungen
- Ein mit kubeadm (v1.22+) verwalteter Kubernetes-Cluster oder Zugriff auf etcd-Zertifikate
etcdctlauf dem Control-Plane-Node installiert (Version muss zur etcd-Version passen)- Root- oder sudo-Zugriff auf dem Control-Plane-Node
kubectlmit cluster-admin-Berechtigungen konfiguriert- Grundlegende Kenntnisse der Kubernetes-Control-Plane-Komponenten
- Für automatisierte Backups: Zugriff auf S3, GCS oder entsprechenden externen Speicher
Die Rolle von etcd in Kubernetes
Jedes Mal, wenn Sie kubectl apply ausführen, validiert der Kubernetes-API-Server die Anfrage und schreibt das resultierende Objekt in etcd. Alle Controller beobachten etcd über den Watch-Mechanismus des API-Servers und reconcilieren den Cluster entsprechend. etcd ist die einzige zustandsbehaftete Komponente in der Control Plane — alle anderen Komponenten sind zustandslos und können von Grund auf neu gestartet werden, solange etcd intakt ist.
Was in etcd gespeichert wird:
- Alle API-Objektdefinitionen: Pods, Deployments, StatefulSets, DaemonSets, Services, Ingresses
- Secrets und ConfigMaps
- RBAC: Roles, ClusterRoles, RoleBindings, ClusterRoleBindings
- Custom Resource Definitions und alle Custom-Resource-Instanzen
- Namespace-Definitionen, ResourceQuotas, LimitRanges
- ServiceAccounts und zugehörige Tokens
- Node-Registrierungen und Lease-Objekte
- Leader-Election-Einträge für kube-controller-manager und kube-scheduler
Was nicht in etcd gespeichert wird: die tatsächlichen Daten in PersistentVolumes. etcd speichert nur die PVC- und PV-API-Objekte (Metadaten und Bindung), nicht die Bytes auf der Festplatte.
etcd-Architektur: Raft, WAL und Snapshots
etcd verwendet den Raft-Konsensalgorithmus, um den Zustand über einen Cluster mit ungerader Anzahl von Mitgliedern (typischerweise 3 oder 5) zu replizieren. Raft wählt einen Leader, der alle Schreibvorgänge verarbeitet; Follower replizieren das Journal des Leaders. Der Cluster toleriert (n-1)/2 Memberausfälle — ein 3-Node-Cluster überlebt 1 Ausfall, ein 5-Node-Cluster überlebt 2.
Schreibvorgänge werden zunächst an das Write-Ahead Log (WAL) auf der Festplatte angehängt und dann auf einen B-Baum im Speicher (bbolt) angewendet. Periodisch erstellt etcd einen internen Snapshot des B-Baums auf der Festplatte und kürzt das WAL, um unbegrenztes Wachstum zu verhindern.
Der Befehl etcdctl snapshot save löst einen On-Demand-Snapshot des aktuellen B-Baum-Zustands aus. Dieser Snapshot ist ein vollständiges, eigenständiges Backup aller etcd-Daten zum Zeitpunkt seiner Erstellung.
Backup-Methoden
Methode 1: etcdctl snapshot save (Empfohlen)
Die kanonische Backup-Methode. In einem kubeadm-Cluster läuft etcd als statischer Pod mit TLS. Zertifikate befinden sich in /etc/kubernetes/pki/etcd/.
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-$(date +%Y%m%d-%H%M%S).db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
Methode 2: Automatisierter CronJob
Stellen Sie einen Kubernetes-CronJob auf der Control Plane bereit, der die etcd-Zertifikate des Hosts einhängt und Snapshots in ein PVC oder Cloud-Speicher schreibt:
apiVersion: batch/v1
kind: CronJob
metadata:
name: etcd-backup
namespace: kube-system
spec:
schedule: "0 * * * *"
jobTemplate:
spec:
template:
spec:
hostNetwork: true
containers:
- name: etcd-backup
image: bitnami/etcd:3.5
command:
- /bin/sh
- -c
- |
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-$(date +%Y%m%d-%H%M%S).db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
volumeMounts:
- name: etcd-certs
mountPath: /etc/kubernetes/pki/etcd
readOnly: true
- name: backup-dir
mountPath: /backup
volumes:
- name: etcd-certs
hostPath:
path: /etc/kubernetes/pki/etcd
- name: backup-dir
persistentVolumeClaim:
claimName: etcd-backup-pvc
restartPolicy: OnFailure
nodeSelector:
node-role.kubernetes.io/control-plane: ""
tolerations:
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
Vergleich der Backup-Tools
| Tool | etcd-Zustand | PV-Daten | Wiederherstellungsgranularität | Komplexität |
|---|---|---|---|---|
| etcdctl snapshot | Ja | Nein | Gesamter Cluster | Gering |
| Velero + etcd-Plugin | Ja | Ja | Namespace oder vollständig | Mittel |
| etcd-backup-operator | Ja | Nein | Gesamter Cluster | Mittel |
| kube-backup | Ja | Nein | Gesamter Cluster | Gering |
| Manueller CronJob | Ja | Nein | Gesamter Cluster | Gering |
Snapshot-Verifizierung
Vertrauen Sie niemals einem Backup, das Sie nicht verifiziert haben. Nach jedem Snapshot:
ETCDCTL_API=3 etcdctl snapshot status /backup/etcd-snapshot.db \
--write-out=table
Wenn TOTAL KEYS 0 ist oder der Hash fehlerhaft ist, ist der Snapshot beschädigt. Integrieren Sie die Verifizierung in Ihren Backup-CronJob und konfigurieren Sie Alarme bei Fehlern.
Wiederherstellungsverfahren
Einknoteniger kubeadm-Cluster
Schritt 1: API-Server und etcd stoppen
mkdir -p /tmp/k8s-manifests-backup
mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/k8s-manifests-backup/
mv /etc/kubernetes/manifests/etcd.yaml /tmp/k8s-manifests-backup/
sleep 10
ps aux | grep etcd
Schritt 2: Vorhandenes Datenverzeichnis sichern
mv /var/lib/etcd /var/lib/etcd.bak
Schritt 3: Snapshot wiederherstellen
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db \
--data-dir=/var/lib/etcd \
--initial-cluster=default=https://127.0.0.1:2380 \
--initial-cluster-token=etcd-cluster-1 \
--initial-advertise-peer-urls=https://127.0.0.1:2380
Schritt 4: Manifests wiederherstellen und verifizieren
mv /tmp/k8s-manifests-backup/etcd.yaml /etc/kubernetes/manifests/
mv /tmp/k8s-manifests-backup/kube-apiserver.yaml /etc/kubernetes/manifests/
sleep 30
kubectl get nodes
Mehrknotiger kubeadm-Cluster
Für einen 3-Node-Control-Plane-Cluster (HA) müssen Sie auf allen etcd-Membern gleichzeitig wiederherstellen, mit konsistenten Werten für --initial-cluster und --initial-cluster-token:
# Auf jedem Control-Plane-Node die Wiederherstellung mit DEMSELBEN Snapshot und Token ausführen
# aber mit dem korrekten --name und --initial-advertise-peer-urls für diesen Node
# Node 1
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db \
--name=etcd-cp1 \
--data-dir=/var/lib/etcd \
--initial-cluster=etcd-cp1=https://10.0.0.1:2380,etcd-cp2=https://10.0.0.2:2380,etcd-cp3=https://10.0.0.3:2380 \
--initial-cluster-token=etcd-restore-token-$(date +%s) \
--initial-advertise-peer-urls=https://10.0.0.1:2380
Verwenden Sie ein eindeutiges --initial-cluster-token, das sich vom Original unterscheidet, um zu verhindern, dass der wiederhergestellte Cluster versehentlich dem alten (degradierten) Cluster beitritt.
Überlegungen zu verwaltetem Kubernetes
EKS, GKE, AKS — Der Cloud-Anbieter verwaltet etcd intern. Sie können nicht direkt auf etcd zugreifen. Verwenden Sie anbieternative Backup-Mechanismen:
- EKS: Velero mit S3; AWS stellt etcd nicht direkt bereit
- GKE: Velero; Google verwaltet etcd mit automatischen Backups auf Autopilot
- AKS: Velero + Azure Blob; Microsoft verwaltet etcd für verwaltete Node Pools
etcd-Gesundheitsüberwachung
# Endpunkt-Gesundheit prüfen
ETCDCTL_API=3 etcdctl endpoint health \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
# Leader- und Member-Status prüfen
ETCDCTL_API=3 etcdctl endpoint status --write-out=table \
--endpoints=https://10.0.0.1:2379,https://10.0.0.2:2379,https://10.0.0.3:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
Empfohlene Prometheus-Alarme für etcd:
etcd_server_has_leader == 0— kein Leader gewählt (kritisch)etcd_disk_wal_fsync_duration_seconds{quantile="0.99"} > 0.01— langsame WAL-Schreibvorgängeetcd_server_proposals_failed_total > 0— Konsensausfälleetcd_mvcc_db_total_size_in_bytes > 8589934592— DB nähert sich dem 8-GB-Limit
Komprimierung und Defragmentierung
etcd hält eine Historie aller Schlüsselrevisionen. Mit der Zeit verbraucht dies erheblichen Festplattenplatz. Aktivieren Sie die automatische Komprimierung:
--auto-compaction-mode=periodic
--auto-compaction-retention=1h
Führen Sie die Defragmentierung periodisch während Nebenzeiten durch:
ETCDCTL_API=3 etcdctl defrag \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
Performance-Tuning
etcd ist extrem empfindlich gegenüber Festplattenlatenz. Empfehlungen:
- Dedizierte SSD: Teilen Sie die etcd-Datenfestplatte niemals mit Anwendungsworkloads. Verwenden Sie eine dedizierte NVMe oder SSD mit über 2000 IOPS für zufällige Schreibvorgänge.
- Heartbeat- und Election-Timeouts: Der Standard-
heartbeat-intervalist 100ms und derelection-timeoutist 1000ms. In latenzreichen Umgebungen erhöhen Sie auf 250ms / 1250ms. - DB-Quota: Der Standardwert ist 2 GB. Erhöhen Sie auf 8 GB für große Cluster:
--quota-backend-bytes=8589934592
Produktions-Backup-Skript mit Alarmierung
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/opt/etcd-backups"
RETENTION_COUNT=24
S3_BUCKET="s3://mein-cluster-etcd-backups"
SLACK_WEBHOOK="https://hooks.slack.com/services/xxx/yyy/zzz"
ETCD_ENDPOINTS="https://127.0.0.1:2379"
CACERT="/etc/kubernetes/pki/etcd/ca.crt"
CERT="/etc/kubernetes/pki/etcd/server.crt"
KEY="/etc/kubernetes/pki/etcd/server.key"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
SNAPSHOT_FILE="${BACKUP_DIR}/etcd-${TIMESTAMP}.db"
alarm() {
local msg="$1"
curl -s -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"[etcd-backup] ${msg}\"}" "${SLACK_WEBHOOK}" || true
}
mkdir -p "${BACKUP_DIR}"
if ! ETCDCTL_API=3 etcdctl snapshot save "${SNAPSHOT_FILE}" \
--endpoints="${ETCD_ENDPOINTS}" \
--cacert="${CACERT}" --cert="${CERT}" --key="${KEY}"; then
alarm "KRITISCH: etcd snapshot save FEHLGESCHLAGEN auf $(hostname) um ${TIMESTAMP}"
exit 1
fi
KEYS=$(ETCDCTL_API=3 etcdctl snapshot status "${SNAPSHOT_FILE}" \
--write-out=json | python3 -c "import sys,json; print(json.load(sys.stdin)['totalKey'])")
if [ "${KEYS}" -lt 100 ]; then
alarm "WARNUNG: Snapshot hat nur ${KEYS} Schlüssel — möglicherweise leerer oder beschädigter Snapshot"
exit 1
fi
aws s3 cp "${SNAPSHOT_FILE}" "${S3_BUCKET}/$(basename ${SNAPSHOT_FILE})" \
--storage-class STANDARD_IA
ls -t "${BACKUP_DIR}"/etcd-*.db | tail -n +$((RETENTION_COUNT + 1)) | xargs -r rm -f
echo "Backup abgeschlossen: ${SNAPSHOT_FILE} (${KEYS} Schlüssel)"
Disaster-Recovery-Szenarien
Szenario 1: Ausfall eines Members (Quorum intakt) — Der Cluster arbeitet weiter. Ersetzen Sie das ausgefallene Member mit etcdctl member remove + etcdctl member add ohne Wiederherstellung.
Szenario 2: Quorumverlust (Mehrheit der Member ausgefallen) — Der Cluster wird schreibgeschützt. Wenn die Daten intakt sind, stellen Sie die Konnektivität wieder her. Wenn Daten verloren gegangen sind, stellen Sie von einem Snapshot auf allen Membern wieder her.
Szenario 3: Vollständige Cluster-Wiederherstellung — Stoppen Sie alle Control-Plane-Komponenten, stellen Sie den Snapshot auf jedem Node mit konsistentem --initial-cluster-token wieder her, starten Sie in der Reihenfolge neu: zuerst etcd, dann kube-apiserver, dann kube-controller-manager und kube-scheduler.
Fallstricke und Randfälle
etcdctl-Versionskonflikt — Setzen Sie immer ETCDCTL_API=3. Überprüfen Sie, ob die Client-Version mit der Server-Version übereinstimmt. Konflikte verursachen stille Fehler oder beschädigte Wiederherstellungen.
Wiederherstellung überschreibt das Datenverzeichnis — etcdctl snapshot restore schreibt in --data-dir. Wenn das Verzeichnis bereits existiert, schlägt die Wiederherstellung fehl. Verschieben Sie immer zuerst das vorhandene Verzeichnis.
Uhrabweichung zwischen Membern — etcd-Peer-TLS-Zertifikate sind zeitkritisch. Stellen Sie sicher, dass NTP auf allen Control-Plane-Nodes konfiguriert und synchronisiert ist.
Überraschungen bei verwalteten Clustern — Auf GKE oder EKS wird der Versuch, in den etcd-Pod zu wechseln, fehlschlagen oder blockiert werden. Verwenden Sie bei verwalteten Clustern sofort Velero.
Zusammenfassung
- etcd speichert den gesamten Kubernetes-Cluster-Zustand; ihn ohne Backup zu verlieren bedeutet, von vorne anzufangen
- Verwenden Sie
etcdctl snapshot savemit TLS-Flags, die auf/etc/kubernetes/pki/etcd/zeigen, für kubeadm-Cluster - Führen Sie immer
etcdctl snapshot statusaus, um Snapshots nach der Erstellung zu verifizieren - Die Wiederherstellung erfordert das Stoppen von API-Server und etcd, die Ausführung von
etcdctl snapshot restoreund den Neustart der Control Plane - Die Multi-Node-Wiederherstellung erfordert konsistentes
--initial-cluster-tokenund korrekte--initial-advertise-peer-urlspro Node - Aktivieren Sie die automatische Komprimierung und führen Sie
etcdctl defragmonatlich aus - Dedizieren Sie eine SSD mit geringer Latenz für etcd-Daten; überwachen Sie die WAL-fsync-Latenz mit Prometheus
- Speichern Sie Snapshots extern (S3/GCS) mit mindestens 24 Stunden Aufbewahrungszeit; automatisieren Sie mit CronJob + Alarmierungsskript