在 3 节点 Master 的 etcd 集群(Raft 共识集群)中,数据恢复需区分集群部分节点故障 和集群全量故障 两种场景,核心原则是:优先通过健康节点自动恢复,仅当多数节点(≥2)数据损坏 / 丢失时,才从快照全量恢复(3 节点 etcd 集群需至少 2 个节点达成共识,因此全量恢复需先重置集群再重建)。
一、前提准备
-
确认 etcd 集群状态 :
# 任选一个Master节点,检查etcd集群成员和健康状态 ETCDCTL_API=3 etcdctl \ --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 \ member list # 查看集群成员(正常应显示3个节点) ETCDCTL_API=3 etcdctl \ --endpoints="https://master1:2379,https://master2:2379,https://master3:2379" \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key \ endpoint health # 检查所有节点健康状态 -
准备有效快照 :确保有最新的 etcd 快照(推荐每小时备份,快照命名格式:
etcd-snapshot-202512061000.db),快照路径建议统一存放至所有 Master 节点的/var/lib/etcd/snapshots/目录。
二、场景 1:单节点 etcd 数据损坏(多数节点健康)
3 节点 etcd 集群中,若仅 1 个节点数据损坏(如 IO 故障导致),无需全量恢复,只需重置该节点 etcd 并重新加入集群(利用 Raft 共识自动同步数据)。
步骤 1:停止故障节点的 etcd 服务
# 在故障Master节点(如master2)停止etcd静态Pod(kubelet会自动重建,需先删除静态Pod文件)
mv /etc/kubernetes/manifests/etcd.yaml /etc/kubernetes/manifests/etcd.yaml.bak
# 等待etcd Pod停止
kubectl -n kube-system get pods | grep etcd
步骤 2:清理故障节点的 etcd 数据目录
# 备份旧数据(可选)
mv /var/lib/etcd /var/lib/etcd.bak
# 创建空数据目录
mkdir -p /var/lib/etcd && chown -R root:root /var/lib/etcd
步骤 3:重新加入 etcd 集群
方式 1:通过 kubeadm 重置节点后重新加入(推荐)
# 在故障节点执行重置(保留etcd证书)
kubeadm reset --keep-certs
# 从健康Master节点(如master1)获取加入控制平面的命令(master1上执行)
kubeadm token create --print-join-command --certificate-key $(kubeadm init phase upload-certs --upload-certs | grep -v 'Certificate key' | tail -1)
# 示例输出:kubeadm join vip:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx --control-plane --certificate-key xxx
# 在故障节点执行上述join命令,重新加入集群
kubeadm join vip:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx --control-plane --certificate-key xxx
方式 2:手动添加 etcd 成员(适用于 kubeadm 外置 etcd 场景)
# 在健康节点(如master1)添加故障节点到etcd集群
ETCDCTL_API=3 etcdctl \
--endpoints=https://master1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member add etcd-master2 --peer-urls=https://master2:2380
# 在故障节点恢复etcd静态Pod文件
mv /etc/kubernetes/manifests/etcd.yaml.bak /etc/kubernetes/manifests/etcd.yaml
# kubelet会自动重建etcd Pod,并从集群同步数据
步骤 4:验证节点恢复
# 检查etcd集群成员状态(健康节点执行)
ETCDCTL_API=3 etcdctl \
--endpoints=https://master1:2379,https://master2:2379,https://master3:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member list
# 检查所有etcd节点健康状态
ETCDCTL_API=3 etcdctl endpoint health --endpoints=https://master1:2379,https://master2:2379,https://master3:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
三、场景 2:多数节点(≥2)数据损坏 / 全集群故障
当 2 个及以上节点 etcd 数据损坏,或集群完全无法启动时,需从快照全量恢复 etcd 集群,步骤如下:
步骤 1:停止所有 Master 节点的 etcd 服务
# 在所有Master节点(master1、master2、master3)执行
mv /etc/kubernetes/manifests/etcd.yaml /etc/kubernetes/manifests/etcd.yaml.bak
# 等待所有etcd Pod停止
kubectl -n kube-system get pods | grep etcd
步骤 2:选择一个节点作为恢复主节点(如 master1)
# 在master1清理旧数据
mv /var/lib/etcd /var/lib/etcd.bak
# 从快照恢复etcd数据(指定新的集群名称和初始集群配置)
ETCDCTL_API=3 etcdctl snapshot restore \
/var/lib/etcd/snapshots/etcd-snapshot-202512061000.db \
--data-dir=/var/lib/etcd \
--name=etcd-master1 \
--initial-cluster=etcd-master1=https://master1:2380,etcd-master2=https://master2:2380,etcd-master3=https://master3:2380 \
--initial-cluster-token=etcd-cluster-token \
--initial-advertise-peer-urls=https://master1:2380
# 修复数据目录权限
chown -R root:root /var/lib/etcd
步骤 3:启动主节点 etcd 服务
# 在master1恢复etcd静态Pod文件
mv /etc/kubernetes/manifests/etcd.yaml.bak /etc/kubernetes/manifests/etcd.yaml
# 等待etcd Pod启动
kubectl -n kube-system get pods | grep etcd-master1
步骤 4:将其他节点加入恢复后的 etcd 集群
(1)清理 master2、master3 的 etcd 数据
# 在master2、master3执行
mv /var/lib/etcd /var/lib/etcd.bak
mkdir -p /var/lib/etcd && chown -R root:root /var/lib/etcd
(2)在 master1 添加 master2、master3 为 etcd 成员
# 在master1执行:添加master2
ETCDCTL_API=3 etcdctl \
--endpoints=https://master1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member add etcd-master2 --peer-urls=https://master2:2380
# 添加master3
ETCDCTL_API=3 etcdctl \
--endpoints=https://master1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member add etcd-master3 --peer-urls=https://master3:2380
(3)启动 master2、master3 的 etcd 服务
# 在master2、master3执行
mv /etc/kubernetes/manifests/etcd.yaml.bak /etc/kubernetes/manifests/etcd.yaml
# 等待etcd Pod启动并同步数据
kubectl -n kube-system get pods | grep etcd
步骤 5:验证集群恢复
# 检查etcd集群成员和健康状态
ETCDCTL_API=3 etcdctl \
--endpoints=https://master1:2379,https://master2:2379,https://master3:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member list
ETCDCTL_API=3 etcdctl endpoint health --endpoints=https://master1:2379,https://master2:2379,https://master3:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
# 验证K8s集群功能
kubectl get nodes
kubectl get pods -n kube-system
kubectl create ns test-ns && kubectl delete ns test-ns # 测试元数据写入
四、关键注意事项
- 快照时效性:恢复用的快照必须是集群故障前的有效快照,建议快照备份至独立存储(如 NFS、对象存储),避免与 etcd 数据同盘丢失;
- 证书一致性 :恢复过程中需确保所有节点的 etcd 证书(
/etc/kubernetes/pki/etcd/)一致,否则节点无法加入集群; - 静态 Pod 配置 :kubeadm 部署的 etcd 为静态 Pod,修改
/etc/kubernetes/manifests/etcd.yaml后,kubelet 会自动重建 Pod,无需手动启动; - 网络连通性:恢复过程中确保 3 个 Master 节点之间的 2379(客户端端口)、2380(Peer 端口)互通,否则 etcd 无法同步数据;
- 数据一致性:全量恢复后,集群元数据会回滚至快照时间点,需确认快照时间点后的操作(如新建 Pod、Service)需重新执行。
五、优化建议(避免集群级 etcd 故障)
- 快照自动化:通过 crontab 或 K8s CronJob 定期备份 etcd,快照同时同步至异地存储;
- 监控强化 :监控 etcd 集群的
etcd_server_quota_backend_bytes_used(存储使用率)、etcd_raft_is_leader(Leader 状态)、etcd_disk_wal_fsync_duration_seconds(IO 耗时),提前预警; - 存储隔离:每个 Master 节点的 etcd 数据目录使用独立 SSD/NVMe 磁盘,避免 IO 资源竞争;
- 集群容灾:生产环境建议部署 5 节点 etcd 集群(容忍 2 个节点故障),进一步提升可用性。