当 kubeadm 部署的三 master 节点 K8s 集群中 etcd 数据库发生故障时,需结合 etcd 的备份文件(快照)进行恢复。
一、前提条件
-
存在有效的 etcd 快照备份 :需提前通过
etcdctl snapshot save生成的快照文件(如etcd-snapshot-20251208.db),且备份时间点的数据完整。若未手动备份,可检查 etcd 数据目录(默认/var/lib/etcd)是否有残留的快照文件(如自动备份的member/snap/db),但该文件为 etcd 内部快照,恢复风险较高,优先使用手动备份。 -
确认 etcd 故障类型:
- 单节点 etcd 故障:仅某一 master 节点的 etcd 实例损坏,集群仍可用(etcd 集群需至少 1 个健康节点);
- 多节点 / 全集群 etcd 故障:etcd 集群多数节点损坏(如 2/3 节点故障),集群不可用,需重建 etcd 集群并恢复数据
二、环境准备
-
停止故障节点的 control-plane 组件:若 etcd 与 control-plane 共节点(stacked 模式),需先停止 kubelet 管理的静态 Pod(etcd、kube-apiserver、kube-controller-manager、kube-scheduler):
docker ps | grep -E "etcd|kube-apiserver" #使用docker运行时 或者 crictl ps | grep -E "etcd|kube-apiserver" #使用containerd运行时2.备份故障节点的 etcd 数据目录:避免数据覆盖,先备份现有 etcd 数据(若有残留):
mv /var/lib/etcd /var/lib/etcd.bak-$(date +%Y%m%d%H%M%S)
mkdir -p /var/lib/etcd
三、单节点 etcd 故障恢复(集群仍可用)
若 etcd 集群仅单节点故障,可通过etcd 集群成员重新加入 + 数据恢复完成修复:
1. 从 etcd 集群中移除故障节点(在健康 master 节点执行)
# 1. 获取etcd集群成员列表,找到故障节点的ID/名称
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
# 2. 移除故障节点(替换<故障节点ID>)
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 remove <故障节点ID>
2. 恢复 etcd 快照到故障节点
# 1. 从快照恢复etcd数据(替换<快照文件路径>)
etcdctl snapshot restore <快照文件路径> \
--data-dir=/var/lib/etcd \
--name=master-03 \ # 故障节点的etcd名称(需与原集群一致)
--initial-cluster=master-01=https://192.168.1.10:2380,master-02=https://192.168.1.11:2380,master-03=https://192.168.1.12:2380 \ # 全集群成员地址
--initial-cluster-token=etcd-cluster-token \ # 原集群token(可从健康节点/etc/kubernetes/manifests/etcd.yaml中获取)
--initial-advertise-peer-urls=https://192.168.1.12:2380 # 故障节点的etcd peer地址(与原集群一致)
# 2. 修复etcd数据目录权限
chown -R root:root /var/lib/etcd
chmod 700 /var/lib/etcd
3. 重新加入 etcd 集群(在健康 master 节点执行)
# 添加故障节点到etcd集群(替换<故障节点IP>和<节点名称>)
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 add <节点名称> --peer-urls=https://<故障节点IP>:2380
4. 恢复故障节点的静态 Pod 配置
# 移回静态Pod配置文件,kubelet会自动重启etcd和control-plane组件
mv /tmp/* /etc/kubernetes/manifests/
# 验证etcd集群状态(故障节点应重新加入,集群健康)
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 \
endpoint health --cluster
四、全集群 etcd 故障恢复(集群不可用)
若 etcd 集群全节点故障,需重建 etcd 集群 + 恢复快照,再重建 control-plane 组件:
1. 停止所有 master 节点的 control-plane 组件
在所有 master 节点执行:
mv /etc/kubernetes/manifests/* /tmp/
rm -rf /var/lib/etcd/*
2. 从快照恢复 etcd 集群(选择一个 master 节点作为第一个节点)
# 1. 恢复etcd快照到第一个节点(替换参数为实际值)
etcdctl snapshot restore <快照文件路径> \
--data-dir=/var/lib/etcd \
--name=master-01 \
--initial-cluster=master-01=https://192.168.1.10:2380,master-02=https://192.168.1.11:2380,master-03=https://192.168.1.12:2380 \
--initial-cluster-token=etcd-cluster-token \
--initial-advertise-peer-urls=https://192.168.1.10:2380
# 2. 修复权限
chown -R root:root /var/lib/etcd
chmod 700 /var/lib/etcd
3. 启动第一个节点的 etcd 静态 Pod
编辑第一个节点的/etc/kubernetes/manifests/etcd.yaml,确保command中的参数与恢复时的initial-cluster、name等一致,然后启动 etcd:
# 复制etcd.yaml到manifests目录(若已移走)
cp /tmp/etcd.yaml /etc/kubernetes/manifests/
# 验证etcd单节点启动成功
etcdctl --endpoints=https://192.168.1.10:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
endpoint health
4. 加入其他 etcd 节点到集群
在第一个节点执行:
# 添加master-02节点(替换参数)
etcdctl --endpoints=https://192.168.1.10:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member add master-02 --peer-urls=https://192.168.1.11:2380
# 添加master-03节点(替换参数)
etcdctl --endpoints=https://192.168.1.10:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member add master-03 --peer-urls=https://192.168.1.12:2380
在 master-02 和 master-03 节点执行快照恢复(步骤同 2,但initial-advertise-peer-urls为对应节点 IP),然后启动 etcd 静态 Pod。
5. 重建 control-plane 组件
在所有 master 节点恢复/etc/kubernetes/manifests/下的所有静态 Pod 配置文件(kube-apiserver、kube-controller-manager、kube-scheduler),kubelet 会自动重启组件:
mv /tmp/* /etc/kubernetes/manifests/
# 验证control-plane组件启动成功
kubectl get pods -n kube-system | grep -E "apiserver|controller-manager|scheduler"
恢复完成后,需验证:
- etcd 集群健康:
etcdctl endpoint health --cluster; - K8s 集群资源正常:
kubectl get nodes、kubectl get pods -A; - 服务可用性:验证 Pod 调度、Service 访问等核心功能。
参考消息
kubeadm 1.21 及以上版本提供了etcd 快照的自动化备份与恢复工具(没有测试过,感兴趣的可以验证一下)
# 1. 备份etcd快照(kubeadm方式)
kubeadm alpha etcd snapshot save /backup/etcd-snapshot-$(date +%Y%m%d).db
# 2. 恢复etcd快照(kubeadm方式,需停止control-plane组件)
kubeadm alpha etcd snapshot restore /backup/etcd-snapshot-20251208.db \
--data-dir=/var/lib/etcd \
--kubeconfig=/etc/kubernetes/admin.conf \
--cert-dir=/etc/kubernetes/pki