前几天有个现场,使用了新华三超融合云的3台虚拟机做了3 master 节点的 K8s 集群,部署节点master1系统崩溃,云厂家运维使用master2镜像克隆恢复master1,导致集群彻底崩溃,亟待修复。那么如何一步步恢复?本文记录了一次的真实恢复过程,涵盖 etcd 成员清理、HAProxy 修复、kubeadm-config 重建、节点 NotReady 排查、本地存储 PVC 重建等 6 个关键阶段。

1 背景
生产环境 K8s 集群基本信息:
| 项目 | 配置 |
|---|---|
| 部署工具 | KubeKey 2.x |
| K8s 版本 | v1.22.12 |
| Master 节点 | 3 台(master1/2/3,172.16.198.201/202/203) |
| etcd | 外置 systemd 服务,3 副本 |
| 高可用方案 | 内置 HAProxy(lb.kubesphere.local → 127.0.0.1:6443) |
| 存储方案 | Rook-Ceph + local-path |
| 监控 | KubeSphere 自带 Prometheus |
本文记录了恢复过程,希望给遇到类似情况的同学一份可操作的参考。
2 恢复流程总览
当前状态: master1 已重装(空机器), master2/3 正常, etcd 有 quorum
Phase 0: 安全备份 etcd 快照
↓
Phase 1: 清理死节点 —— 移除 etcd 死成员 + 删除 k8s node
↓
Phase 2: 执行 kk add nodes —— 遭遇 HAProxy 连接拒绝
↓
Phase 3: 修复 HAProxy + 重建 kubeadm-config.yaml (缺少 ClusterConfiguration)
↓
Phase 4: master1 加入集群 —— 遭遇 NotReady + Pod 全部 Pending
↓
Phase 5: 修复 Prometheus PVC (local 存储丢失)
↓
恢复完成: 3 节点 Ready, 所有 Pod Running
3 恢复创建集群配置文件
从当前已创建的集群恢复配置文件
./kk create config --from-cluster

恢复了一半,我们使用离线部署还需要继续修改
手动修改配置文件


3 备份etcd数据
master2执行
export ETCDCTL_API=3
ETCDCTL=$(command -v etcdctl || echo /usr/local/bin/etcdctl)
ETCDUTL=$(command -v etcdutl || echo /usr/local/bin/etcdutl)
HOSTNAME=$(hostname)
BACKUP_DIR=/root/etcd-backup-$(date +%F-%H%M%S)
mkdir -p "$BACKUP_DIR"
ls /etc/ssl/etcd/ssl/

export ETCDCTL_API=3
CACERT=/etc/ssl/etcd/ssl/ca.pem
CERT=/etc/ssl/etcd/ssl/admin-master2.pem
KEY=/etc/ssl/etcd/ssl/admin-master2-key.pem
ENDPOINT=https://127.0.0.1:2379
# 检测 etcd 健康
$ETCDCTL \
--endpoints="$ENDPOINT" \
--cacert="$CACERT" \
--cert="$CERT" \
--key="$KEY" \
endpoint health

备份
SNAPSHOT="$BACKUP_DIR/etcd-snapshot.db"
$ETCDCTL \
--endpoints="$ENDPOINT" \
--cacert="$CACERT" \
--cert="$CERT" \
--key="$KEY" \
snapshot save "$SNAPSHOT"

验证
$ETCDCTL snapshot status "$SNAPSHOT" -w table

备份证书
cp -a /etc/ssl/etcd/ssl /root/etcd-backup-2026-07-04-112311/etcd-ssl
4 剔除master1成员
./kk delete node master1 -f config-sample.yaml

由于master1系统已重装,数据也全部丢失,执行失败,改为手动剔除
检查 etcd 成员状态
export ETCDCTL_API=3
CACERT=/etc/ssl/etcd/ssl/ca.pem
CERT=/etc/ssl/etcd/ssl/admin-master2.pem
KEY=/etc/ssl/etcd/ssl/admin-master2-key.pem
ENDPOINT=https://127.0.0.1:2379
etcd集群状态

移除 etcd 死成员
查看etcd成员情况
$ETCDCTL \
--endpoints="$ENDPOINT" \
--cacert="$CACERT" \
--cert="$CERT" \
--key="$KEY" \
member list -w table

找到 master1 那一行的 ID,然后删除它:
$ETCDCTL \
--endpoints="$ENDPOINT" \
--cacert="$CACERT" \
--cert="$CERT" \
--key="$KEY" \
member remove d1da9cc07dfdff01

删除master1节点
kubectl delete node master1

5 重新添加master1节点
./kk add nodes -f config-sample.yaml
报错:

备份
cp /etc/kubernetes/kubeadm-config.yaml /etc/kubernetes/kubeadm-config.yaml.bak
修复kubeadm-config
master2和master3执行
kubectl get configmap kubeadm-config -n kube-system -o jsonpath='{.data.ClusterConfiguration}' > /tmp/clusterconfig.yaml
echo "---" >> /etc/kubernetes/kubeadm-config.yaml
cat /tmp/clusterconfig.yaml >> /etc/kubernetes/kubeadm-config.yaml
cat /etc/kubernetes/kubeadm-config.yaml
kubeadm init phase upload-certs --upload-certs --config /etc/kubernetes/kubeadm-config.yaml
重新执行
./kk add nodes -f config-sample.yaml

6 kubelet 与 CNI 问题
报错现象
kk add nodes 成功完成后,master1 已加入集群,但状态为 NotReady,所有调度到 master1 的 Pod 全部 Pending:
kubectl get nodes
NAME STATUS ROLES AGE VERSION
master1 NotReady control-plane,master,worker 3m26s v1.22.12
master2 Ready control-plane,master,worker 3y36d v1.22.12
master3 Ready control-plane,master,worker 3y36d v1.22.12
排查方法
第一步:查看 Node Conditions
kubectl describe node master1 | grep -A5 Conditions
重点关注 Ready 和 KubeletReady 的 Message,常见两种情况:
container runtime not running→ containerd 没起来network not ready→ CNI 插件未安装
第二步:在 master1 上检查组件状态
ssh root@172.16.198.201
# 检查 kubelet 和 containerd
systemctl status kubelet
systemctl status containerd
# 查看 kubelet 日志
journalctl -u kubelet --no-pager -n 50
修复方法
根据日志中的具体错误,通常需要:
情况 A:containerd 未启动
systemctl start containerd
systemctl enable containerd
crictl info # 确认正常
systemctl restart kubelet
情况 B:CNI 插件缺失
# 检查 CNI 配置
ls /etc/cni/net.d/
# 如果为空,从 master2 拷贝
scp root@172.16.198.202:/etc/cni/net.d/* /etc/cni/net.d/
# 检查 CNI 二进制
ls /opt/cni/bin/
# 如果为空,从 master2 拷贝
scp -r root@172.16.198.202:/opt/cni/bin/* /opt/cni/bin/
systemctl restart kubelet
修复后验证
kubectl get nodes

7 重建local-pvc

删除master1上local的pvc,重建对应服务
8 经验总结
1. 引导节点的特殊性
K8s 集群中第一个 Master 节点(引导节点)拥有其他 Master 没有的配置文件——完整的 kubeadm-config.yaml(包含 InitConfiguration + ClusterConfiguration)。一旦引导节点丢失,这些配置也随之消失。
建议: 在所有 Master 节点上备份 /etc/kubernetes/kubeadm-config.yaml 和 /etc/kubernetes/pki/ 目录。或者至少记住:ClusterConfiguration 可以从 kube-system/kubeadm-config ConfigMap 中恢复。
2. etcd 死成员必须先清理
etcd 不会自动移除死掉的成员。如果不手动 etcdctl member remove,新节点加入时 peer URL 会冲突,导致添加失败。
3. HAProxy 配置变更需谨慎
KubeKey 内置 HAProxy 的 HA 方案,一旦 HAProxy 配置异常会导致整个集群失联。恢复技巧:临时修改 kubeconfig 直连某个 MasterIP,绕过 HAProxy 恢复指挥权,再修复 HAProxy 配置。
4. local 存储的 Pod 需要手动清理 PVC
使用 local-path 或 local volume 的 StatefulSet Pod,在节点重装后 PVC 会卡住。需要手动删除 PVC、PV、Pod,让 StatefulSet 重建。
5. 恢复顺序很重要
备份 etcd → 清理死成员 → 删除 node → 修复 kubeadm-config → kk add nodes → 修复 CNI → 清理 PVC
每一步都有可能遇到坑,但只要 quorum 还在(2/3 存活),数据就不会丢,集群一定能恢复。
评论区