etcd sichern und wiederherstellen
Warum etcd
etcd speichert den vollständigen Zustand eines Kubernetes-Clusters. Alle API-Objekte, Secrets und ConfigMaps liegen dort.
Ein konsistenter Snapshot von etcd ist die Grundlage für Disaster Recovery. Geht etcd verloren, ist das Cluster ohne Snapshot nicht rekonstruierbar.
Voraussetzung für eine Wiederherstellung: etcd und die Control-Plane-Pods müssen gestoppt sein, und die Zertifikate auf dem Zielsystem müssen zum Snapshot passen.
Snapshot und Wiederherstellung
Zwei Werkzeuge sind beteiligt. etcdctl spricht mit einer laufenden etcd-Instanz und erstellt den Snapshot. etcdutl arbeitet offline auf einer Snapshot-Datei und stellt das Datenverzeichnis wieder her.
ETCDCTL_API=3 etcdctl ... snapshot save snapshot.db
etcdutl snapshot restore snapshot.db ...
Konvention: ETCDCTL_API=3 setzt die v3-API für etcdctl. Der Restore läuft mit etcdutl ohne laufenden Server.
Single-Node: Wiederherstellung
Vorgehen für eine Control Plane mit einem einzelnen etcd-Member.
Snapshot erstellen
ETCDCTL_API=3 etcdctl \
--endpoints https://127.0.0.1:2379 \
--cacert /etc/ssl/etcd/ssl/ca.pem \
--cert /etc/ssl/etcd/ssl/admin-node1.pem \
--key /etc/ssl/etcd/ssl/admin-node1-key.pem \
snapshot save snapshot.db
Der Snapshot wird gegen den lokalen etcd-Endpoint erstellt. Die TLS-Flags --cacert, --cert und --key authentisieren den Client gegenüber etcd.
Snapshot sichern
scp <node1>:snapshot.db .
Die Snapshot-Datei wird vom Knoten kopiert und außerhalb des Clusters abgelegt.
etcd-Zertifikate sichern
rsync -avz root@<node1-ip>:/etc/ssl/etcd .
Die Zertifikate liegen unter /etc/ssl/etcd/ssl/. Sie werden mitgesichert, weil der wiederhergestellte etcd-Zustand zu ihnen passen muss.
Zielcluster provisionieren
Voraussetzung: Ein neues Cluster ist provisioniert, mit installiertem etcd und gleicher Topologie. Der Restore überschreibt anschließend dessen etcd-Datenverzeichnis.
Control-Plane-Pods stoppen
mv /etc/kubernetes/manifests ~
Das Verzeichnis der statischen Pod-Manifeste wird beiseitegeschoben. Das Kubelet stoppt daraufhin kube-apiserver, kube-controller-manager und kube-scheduler.
etcd stoppen
systemctl stop etcd
etcd muss gestoppt sein, bevor das Datenverzeichnis verändert wird.
Aktuelles Datenverzeichnis beiseiteschieben
mv /var/lib/etcd/member /var/lib/etcd/member_bak
Das bestehende member-Verzeichnis wird umbenannt statt gelöscht. So bleibt der alte Zustand bei Bedarf erhalten.
Snapshot wiederherstellen
etcdutl snapshot restore snapshot.db \
--name etcd1 \
--initial-cluster etcd1=https://<node1-ip>:2380 \
--initial-cluster-token k8s_etcd \
--initial-advertise-peer-urls https://<node1-ip>:2380 \
--data-dir /var/lib/etcd/
etcdutl schreibt ein neues member-Verzeichnis aus dem Snapshot. --name und --initial-advertise-peer-urls beschreiben das Member, --initial-cluster die Cluster-Topologie.
Zertifikate zurückspielen
rsync -avz ./etcd root@<node1-ip>:/etc/ssl/
Die gesicherten Zertifikate werden auf dem Zielknoten wiederhergestellt.
etcd starten und Manifeste zurücklegen
systemctl start etcd
mv ~/manifests /etc/kubernetes/
etcd startet mit dem wiederhergestellten Datenverzeichnis. Danach legt das Kubelet die Control-Plane-Pods aus den Manifesten neu an.
Status prüfen
kubectl get po -A
systemctl status etcd
journalctl -xeu etcd
kubectl get po -A zeigt, ob die API erreichbar ist und die Pods laufen. systemctl status und journalctl zeigen den etcd-Dienst und seine Logs.
Multi-Node: Wiederherstellung
Vorgehen für eine Control Plane mit drei etcd-Membern. Der Snapshot stammt aus einem der Member und wird auf alle drei Knoten verteilt.
Snapshot erstellen
ETCDCTL_API=3 etcdctl \
--endpoints https://127.0.0.1:2379 \
--cacert /etc/ssl/etcd/ssl/ca.pem \
--cert /etc/ssl/etcd/ssl/admin-node1.pem \
--key /etc/ssl/etcd/ssl/admin-node1-key.pem \
snapshot save snapshot.db
Ein einzelner Snapshot von einem Member genügt, da alle Member denselben replizierten Zustand halten.
Snapshot sichern
scp <node1>:snapshot.db .
etcd-Zertifikate sichern
rsync -avz root@<node1-ip>:/etc/ssl/etcd .
Die Zertifikate liegen unter /etc/ssl/etcd/ssl/.
Zielcluster provisionieren
Voraussetzung: Ein neues Cluster mit drei Control-Plane-Knoten ist provisioniert, mit installiertem etcd auf jedem Knoten.
Snapshot an alle Control-Plane-Knoten verteilen
scp snapshot.db <node1>:.
scp snapshot.db <node2>:.
scp snapshot.db <node3>:.
Jeder Knoten stellt sein eigenes Member aus derselben Snapshot-Datei wieder her.
Control-Plane-Pods auf allen Knoten stoppen
mv /etc/kubernetes/manifests ~
Der Schritt wird auf jedem der drei Knoten ausgeführt.
etcd auf allen Knoten stoppen
systemctl stop etcd
Aktuelles Datenverzeichnis auf allen Knoten beiseiteschieben
mv /var/lib/etcd/member ~
Snapshot auf jedem Knoten wiederherstellen
Pro Member ein eigener etcdutl-Aufruf. --name und --initial-advertise-peer-urls unterscheiden sich je Knoten, --initial-cluster und --initial-cluster-token sind identisch.
# auf <node1>
etcdutl snapshot restore snapshot.db \
--name etcd1 \
--initial-cluster etcd1=https://<node1-ip>:2380,etcd2=https://<node2-ip>:2380,etcd3=https://<node3-ip>:2380 \
--initial-cluster-token k8s_etcd \
--initial-advertise-peer-urls https://<node1-ip>:2380 \
--data-dir /var/lib/etcd/
# auf <node2>
etcdutl snapshot restore snapshot.db \
--name etcd2 \
--initial-cluster etcd1=https://<node1-ip>:2380,etcd2=https://<node2-ip>:2380,etcd3=https://<node3-ip>:2380 \
--initial-cluster-token k8s_etcd \
--initial-advertise-peer-urls https://<node2-ip>:2380 \
--data-dir /var/lib/etcd/
# auf <node3>
etcdutl snapshot restore snapshot.db \
--name etcd3 \
--initial-cluster etcd1=https://<node1-ip>:2380,etcd2=https://<node2-ip>:2380,etcd3=https://<node3-ip>:2380 \
--initial-cluster-token k8s_etcd \
--initial-advertise-peer-urls https://<node3-ip>:2380 \
--data-dir /var/lib/etcd/
Das identische --initial-cluster und --initial-cluster-token binden die drei Member zu einem Cluster zusammen. Ein abweichender Token oder eine abweichende Topologie verhindert den Zusammenschluss.
Zertifikate auf allen Knoten zurückspielen
rsync -avz ./etcd root@<node1>:/etc/ssl/
rsync -avz ./etcd root@<node2>:/etc/ssl/
rsync -avz ./etcd root@<node3>:/etc/ssl/
etcd auf allen Knoten starten
systemctl start etcd
Die Member starten und bilden anhand der --initial-cluster-Angabe das Quorum.
Control-Plane-Pods auf allen Knoten zurücklegen
mv ~/manifests /etc/kubernetes/
Status prüfen
kubectl get po -A
systemctl status etcd
journalctl -xeu etcd
Quorum und Downtime
Ein etcd-Cluster mit drei Membern toleriert den Ausfall eines Members. Schreibzugriffe benötigen die Mehrheit, also zwei der drei Member.
Während des Restores sind alle Member gestoppt. Das Cluster ist in dieser Phase nicht verfügbar; die Downtime umfasst den gesamten Ablauf bis zum erneuten Erreichen des Quorums.
Konvention: Die Member erst starten, wenn alle drei Datenverzeichnisse aus demselben Snapshot wiederhergestellt sind. Andernfalls entsteht kein konsistentes Quorum.
Zusammenfassung
- etcd hält den gesamten Cluster-Zustand; ohne Snapshot ist keine Wiederherstellung möglich
etcdctlerstellt den Snapshot online,etcdutlstellt ihn offline wieder herETCDCTL_API=3und die TLS-Flags--cacert,--cert,--keysind beim Snapshot erforderlich- Vor dem Restore Control-Plane-Manifeste beiseiteschieben und etcd stoppen
- Das bestehende
member-Verzeichnis umbenennen, nicht löschen - Zertifikate müssen zum wiederhergestellten Zustand passen
- Single-Node: ein
etcdutl-Aufruf; Multi-Node: ein Aufruf pro Member - Multi-Node teilt sich
--initial-clusterund--initial-cluster-token, unterscheidet--nameund--initial-advertise-peer-urls - Drei Member tolerieren einen Ausfall; das Quorum sind zwei Member
- Während des Restores ist das Cluster nicht verfügbar