TL;DR — Résumé Rapide
Sauvegarde et restauration etcd pour Kubernetes : snapshots, vérification, restauration multi-nœud, certificats kubeadm et surveillance en production.
etcd est le cœur de tout cluster Kubernetes : un magasin clé-valeur distribué et fortement cohérent qui conserve l’état complet — désiré et observé — de votre cluster. Lorsqu’etcd fonctionne correctement, les commandes kubectl répondent en millisecondes et les contrôleurs réconcillient en continu. Lorsqu’etcd est perdu sans sauvegarde, votre cluster disparaît — chaque définition de Deployment, chaque Secret, chaque politique RBAC, chaque CRD et chaque ConfigMap s’évaporent. Ce guide couvre tout ce dont vous avez besoin pour construire une stratégie de sauvegarde et de restauration etcd de niveau production.
Prérequis
- Un cluster Kubernetes géré avec kubeadm (v1.22+) ou accès aux certificats etcd
etcdctlinstallé sur le nœud du plan de contrôle (la version doit correspondre à celle d’etcd)- Accès root ou sudo sur le nœud du plan de contrôle
kubectlconfiguré avec des permissions cluster-admin- Familiarité de base avec les composants du plan de contrôle Kubernetes
- Pour les sauvegardes automatisées : accès à S3, GCS ou un stockage externe équivalent
Le Rôle d’etcd dans Kubernetes
Chaque fois que vous exécutez kubectl apply, le serveur API Kubernetes valide la requête et écrit l’objet résultant dans etcd. Tous les contrôleurs observent etcd via le mécanisme de watch du serveur API et réconcillient le cluster en conséquence. etcd est le seul composant avec état dans le plan de contrôle — tous les autres composants sont sans état et peuvent être redémarrés depuis zéro tant qu’etcd est intact.
Ce qui réside dans etcd :
- Toutes les définitions d’objets API : Pods, Deployments, StatefulSets, DaemonSets, Services, Ingresses
- Secrets et ConfigMaps
- RBAC : Roles, ClusterRoles, RoleBindings, ClusterRoleBindings
- Custom Resource Definitions et toutes les instances de ressources personnalisées
- Définitions de Namespaces, ResourceQuotas, LimitRanges
- ServiceAccounts et tokens associés
- Enregistrements de nœuds et objets de lease
- Enregistrements d’élection de leader pour kube-controller-manager et kube-scheduler
Ce qui ne réside pas dans etcd : les données réelles stockées dans les PersistentVolumes. etcd ne stocke que les objets PVC et PV (métadonnées et liaison), pas les octets sur disque.
Architecture etcd : Raft, WAL et Snapshots
etcd utilise l’algorithme de consensus Raft pour répliquer l’état sur un cluster de membres en nombre impair (typiquement 3 ou 5). Raft élit un leader qui traite toutes les écritures ; les suiveurs répliquent le journal du leader. Le cluster tolère (n-1)/2 défaillances de membres — un cluster à 3 nœuds survit à 1 défaillance, un à 5 nœuds survit à 2.
Les écritures sont d’abord ajoutées au Write-Ahead Log (WAL) sur disque, puis appliquées à un B-tree en mémoire (bbolt). Périodiquement, etcd prend un snapshot interne du B-tree sur disque et tronque le WAL pour éviter une croissance illimitée.
La commande etcdctl snapshot save déclenche un snapshot de l’état actuel du B-tree. Ce snapshot est une sauvegarde complète et autonome de toutes les données etcd au moment où il a été pris.
Méthodes de Sauvegarde
Méthode 1 : etcdctl snapshot save (Recommandée)
La méthode canonique de sauvegarde. Sur un cluster kubeadm, etcd tourne comme pod statique avec TLS. Les certificats se trouvent dans /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
Méthode 2 : CronJob Automatisé
Déployez un CronJob Kubernetes sur le plan de contrôle qui monte les certificats etcd de l’hôte et écrit les snapshots dans un PVC ou un stockage cloud :
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
Comparatif des Outils de Sauvegarde
| Outil | État etcd | Données PV | Granularité de Restauration | Complexité |
|---|---|---|---|---|
| etcdctl snapshot | Oui | Non | Cluster complet | Faible |
| Velero + plugin etcd | Oui | Oui | Namespace ou complet | Moyenne |
| etcd-backup-operator | Oui | Non | Cluster complet | Moyenne |
| kube-backup | Oui | Non | Cluster complet | Faible |
| CronJob manuel | Oui | Non | Cluster complet | Faible |
Vérification du Snapshot
Ne faites jamais confiance à une sauvegarde que vous n’avez pas vérifiée. Après chaque snapshot :
ETCDCTL_API=3 etcdctl snapshot status /backup/etcd-snapshot.db \
--write-out=table
Si TOTAL KEYS est 0 ou si le hash est malformé, le snapshot est corrompu. Intégrez la vérification dans votre CronJob de sauvegarde et configurez des alertes en cas d’échec.
Procédures de Restauration
Cluster kubeadm à Nœud Unique
Étape 1 : Arrêter le serveur API et etcd
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
Étape 2 : Sauvegarder le répertoire de données existant
mv /var/lib/etcd /var/lib/etcd.bak
Étape 3 : Restaurer le snapshot
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
Étape 4 : Restaurer les manifests et vérifier
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
Cluster kubeadm Multi-Nœuds
Pour un cluster à 3 nœuds du plan de contrôle (HA), vous devez restaurer sur tous les membres etcd simultanément avec des valeurs cohérentes pour --initial-cluster et --initial-cluster-token :
# Sur chaque nœud du plan de contrôle, exécutez la restauration avec le MÊME snapshot et token
# mais avec le --name et --initial-advertise-peer-urls corrects pour ce nœud
# Nœud 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
Utilisez un --initial-cluster-token unique et différent de l’original pour éviter que le cluster restauré ne rejoigne accidentellement l’ancien cluster dégradé.
Considérations pour Kubernetes Managé
EKS, GKE, AKS — Le fournisseur cloud gère etcd en interne. Vous ne pouvez pas accéder directement à etcd. Utilisez les mécanismes natifs du fournisseur :
- EKS: Velero avec S3 ; AWS n’expose pas etcd directement
- GKE: Velero ; Google gère etcd avec des sauvegardes automatiques sur Autopilot
- AKS: Velero + Azure Blob ; Microsoft gère etcd pour les node pools managés
Surveillance de la Santé d’etcd
# Vérifier la santé du point de terminaison
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
# Vérifier le leader et l'état des membres
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
Alertes Prometheus recommandées pour etcd :
etcd_server_has_leader == 0— aucun leader élu (critique)etcd_disk_wal_fsync_duration_seconds{quantile="0.99"} > 0.01— écritures WAL lentesetcd_server_proposals_failed_total > 0— échecs de consensusetcd_mvcc_db_total_size_in_bytes > 8589934592— BD approchant la limite de 8 Go
Compaction et Défragmentation
etcd conserve un historique de toutes les révisions de clés. Avec le temps, cela consomme un espace disque significatif. Activez la compaction automatique :
--auto-compaction-mode=periodic
--auto-compaction-retention=1h
Exécutez la défragmentation périodiquement pendant les heures creuses :
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
Réglage des Performances
etcd est extrêmement sensible à la latence disque. Recommandations :
- SSD dédié: Ne partagez jamais le disque de données etcd avec des charges de travail applicatives. Utilisez un NVMe ou SSD avec des IOPS d’écriture aléatoire soutenue > 2000.
- Timeouts de heartbeat et d’élection: Le
heartbeat-intervalpar défaut est 100ms et leelection-timeoutest 1000ms. Dans des environnements à latence élevée, augmentez à 250ms / 1250ms. - Quota de BD: La valeur par défaut est 2 Go. Augmentez à 8 Go pour les grands clusters :
--quota-backend-bytes=8589934592
Script de Sauvegarde de Production avec Alertes
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/opt/etcd-backups"
RETENTION_COUNT=24
S3_BUCKET="s3://mon-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"
alerte() {
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
alerte "CRITIQUE : etcd snapshot save a ÉCHOUÉ sur $(hostname) à ${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
alerte "AVERTISSEMENT : le snapshot n'a que ${KEYS} clés — snapshot vide ou corrompu possible"
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 "Sauvegarde terminée : ${SNAPSHOT_FILE} (${KEYS} clés)"
Scénarios de Reprise après Sinistre
Scénario 1 : Défaillance d’un membre (quorum intact) — Le cluster continue de fonctionner. Remplacez le membre défaillant avec etcdctl member remove + etcdctl member add sans restauration.
Scénario 2 : Perte de quorum (majorité des membres hors ligne) — Le cluster devient en lecture seule. Si les données sont intactes, rétablissez la connectivité. Si les données sont perdues, restaurez depuis un snapshot sur tous les membres.
Scénario 3 : Restauration complète du cluster — Arrêtez tous les composants du plan de contrôle, restaurez le snapshot sur chaque nœud avec un --initial-cluster-token cohérent, redémarrez dans l’ordre : etcd d’abord, puis kube-apiserver, puis kube-controller-manager et kube-scheduler.
Pièges et Cas Particuliers
Incompatibilité de version etcdctl — Définissez toujours ETCDCTL_API=3. Vérifiez que la version du client correspond à celle du serveur. Les incompatibilités causent des échecs silencieux ou des restaurations corrompues.
La restauration écrase le répertoire de données — etcdctl snapshot restore écrit dans --data-dir. Si le répertoire existe déjà, la restauration échoue. Déplacez toujours le répertoire existant au préalable.
Décalage d’horloge entre membres — Les certificats TLS des pairs etcd sont sensibles au temps. Assurez-vous que NTP est configuré et synchronisé sur tous les nœuds du plan de contrôle.
Résumé
- etcd stocke tout l’état du cluster Kubernetes ; le perdre sans sauvegarde signifie reconstruire de zéro
- Utilisez
etcdctl snapshot saveavec les flags TLS pointant vers/etc/kubernetes/pki/etcd/pour les clusters kubeadm - Exécutez toujours
etcdctl snapshot statuspour vérifier les snapshots après leur création - La restauration nécessite d’arrêter le serveur API et etcd, d’exécuter
etcdctl snapshot restoreet de redémarrer le plan de contrôle - La restauration multi-nœuds nécessite un
--initial-cluster-tokencohérent et des--initial-advertise-peer-urlscorrects par nœud - Activez la compaction automatique et exécutez
etcdctl defragmensuellement - Dédiez un SSD à faible latence aux données etcd ; surveillez la latence WAL fsync avec Prometheus
- Stockez les snapshots hors site (S3/GCS) avec au moins 24h de rétention ; automatisez avec un CronJob + script d’alertes