本文约2500字,阅读约12分钟。
前两篇演练,分别演示了Master和负载均衡器的故障,K8s集群都稳如老狗。今天,对整个集群的“命脉”——etcd下手!
将模拟一次 etcd多数派失效的灾难场景。当3个etcd节点倒下2个,K8s控制平面会经历怎样的“脑中风”?最重要的是,我们还能把它救回来吗?
本文全程实战截图!

动手之前,必须给集群拍一张“CT 照”,记录最健康的样子。
kubectl get nodes -o wide

kubectl get pods -A

sudo ETCDCTL_API=3 etcdctl endpoint health \
--endpoints=https://192.168.114.145:2379,https://192.168.114.146:2379,https://192.168.114.147:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key

我们先停掉 master01上的 etcd,看看集群会不会慌。
# 在 master01 上执行
sudo mv /etc/kubernetes/manifests/etcd.yaml /tmp/

kubectl get pods -n kube-system
输出竟然还是:
etcd-master01 1/1 Running 11 6d

为什么 ?我已经移走了 YAML 文件,为什么 Pod 还在? 赶紧用 etcdctl检查一下端口:
sudo ETCDCTL_API=3 etcdctl endpoint health \
--endpoints=https://192.168.114.145:2379,https://192.168.114.146:2379,https://192.168.114.147:2379 \
--cacert=... --cert=... --key=...
输出:

现象:静态 Pod 的 YAML 文件已经移走,kubectl却显示 Pod 还在 Running,但实际 etcd 进程早已退出了(端口不通)。
原因分析: kubelet监视 /etc/kubernetes/manifests目录,正常情况下移走文件会立即删除 Pod。但在某些情况下(例如容器运行时响应慢、kubelet 缓存未刷新),Pod 对象会残留在 API Server 中,变成一个“幽灵 Pod”。由于静态文件已不存在,kubelet 也不会再管理它,只能手动删除。
解决方案: 强制删除这个“幽灵 Pod”:
kubectl delete pod -n kube-system etcd-master01 --force --grace-period=0

再次查看:
kubectl get pods -n kube-system | grep etcd
只看到 etcd-master02和 etcd-master03,幽灵消失。

💡 小贴士: 在使用静态 Pod 进行故障模拟时,如果移走 YAML 后 Pod 没有自动消失,不要慌。直接
kubectl delete pod --force即可,因为清单文件已经不在,kubelet 不会重建。
现在集群还剩 2 个 etcd(master02 和 master03),多数派依然成立(2/3)。继续停掉 master02的 etcd。
# 在 master02 上执行
sudo mv /etc/kubernetes/manifests/etcd.yaml /tmp/
sudo systemctl restart kubelet

此时集群仅剩 etcd-master03一个节点,多数派失效(1/3 < 2)。
执行任意 kubectl命令:
kubectl get pods


均显示超时。
但已经运行的业务 Pod 呢?
登录 Master 和 Worker 节点查看容器:
sudo ctr -n k8s.io task ls


图中显示容器依然正常运行当中。
结论:
kube-apiserver拒绝写入(只读缓存可能还能读,但不保证一致性)。在 master01 & master02 执行:
sudo mv /tmp/etcd.yaml /etc/kubernetes/manifests/
sudo systemctl restart kubelet

稍等 30 秒,检查 etcd Pod:
kubectl get pods -n kube-system | grep etcd
所有三个 etcd Pod 重新变为 Running。

执行健康检查:
sudo ETCDCTL_API=3 etcdctl endpoint health \
--endpoints=https://192.168.114.145:2379,https://192.168.114.146:2379,https://192.168.114.147:2379 \
--cacert=... --cert=... --key=...

kubectl get nodes
kubectl run recovery-nginx --image=nginx

集群复活!
在恢复节点的过程中: 当我只恢复了 master01 的 etcd(将 YAML 文件移回),集群中 etcd 节点从 1 个变为 2 个(master01 + master03),多数派重新成立,
kubectl立刻恢复了正常! 为什么? Raft 协议要求存活节点数 > N/2。3 节点集群中,2 个节点存活即可满足多数派(Quorum=2),无需等待第三个节点恢复。 这就是分布式系统中“多数派”的优雅之处:部分节点恢复即可让整个集群复活。 💡 扩展思考:如果 etcd 集群是 5 个节点,最少需要恢复几个节点才能让集群重新可用?
层级 | 核心组件 | 高可用手段 | 验证结果 |
|---|---|---|---|
接入层 | VIP + LB (HAProxy) | Keepalived 主备 + HAProxy 多节点 | ✅ EP.2 已验证:VIP 漂移丝般顺滑 |
控制层 | kube-apiserver | 多副本(3 Master 轮询) | ✅ EP.1 已验证:干掉一个 Master 服务继续 |
数据层 | etcd | Raft 共识 + 多数派(3 节点) | ✅ EP.3 已验证:多数派失效 → 集群不可写,恢复即重生 |
一句话总结:
etcd 是 K8s 真正的心脏起搏器,Quorum 就是它的心律。

这次从:
一路演练下来,我最大的感受是:
而是:
尤其 etcd。
很多人知道:
etcd 很重要
但真正进入生产后你会发现:
这些问题,如果你没亲手踩过。
到真正出故障时,心理压力可能会非常大。
而这次“幽灵 Pod”的排障,也让我对 Kubernetes 有了更深的理解。
理论里:
删除 YAML
→ Pod 消失
但真实环境里:
你可能会遇到:
这些东西,文档通常只会一句带过。
但在真实生产环境里:
所以现在我越来越认同一句话:
从来不是“你会不会部署”, 而是: 你有没有真正做过故障演练。
因为:
但:
3 Master 不是重点。
真正的核心是:
Raft Quorum
你必须知道:
否则:
你的 HA 很可能只是:
“心理上的高可用”
很多人有:
etcd snapshot.db
但从没恢复过。
真实事故里:
最危险的不是:
没有备份
而是:
生产环境里最可怕的通常不是:
节点直接挂掉
而是:
因为这种状态:
也是:
这次真实的“幽灵 Pod”排障经历也告诉我: 理论是枯燥的,但实战中的每一个坑,都是你成长的阶梯。