内容有点长,可收藏后续查看。
可能的场景
凌晨三点,你被 PagerDuty 吵醒。告警面板一片飘红:kubectl get nodes返回 Unable to connect。
你的第一反应可能是:整个集群完蛋了。
但事实是——业务 Pod 依然在跑,用户流量依然在转发。
API Server 挂了,集群并没有你想的那么脆弱。
这是 「Kubernetes Cluster HA 故障演练」系列的第四篇。前几篇我们验证了单 Master 宕机、LB 节点故障、ETCD 多数派失效,这一篇我们玩个更狠的——直接停掉所有 API Server 实例,看看集群到底会怎样。
在深入实验之前,先厘清一个关键概念:"API Server 挂了"并不只有一种情况。
三 Master 高可用部署中,如果 master01上的 API Server 进程异常退出,但负载均衡器健康检查正常且其余两个实例正常,kubectl请求会自动转发到 master02或 master03——用户几乎无感知。
Kubernetes API 入口完全消失:
kubectl get nodes
# Unable to connect to the server: EOF
集群进入"失聪失明"状态。
API Server 仍在监听 6443,但与 etcd 之间链路出问题。写操作全部失败,部分只读请求可能短暂成功。这种场景更"诡异"。(EP.3 已验证)
本文重点讨论 场景二——最能帮助我们理解控制面与数据面边界的极端场景。
核心认知纠正:API Server 是集群的"控制入口",不是"运行时执行者"。它负责认证、鉴权、写入 etcd,但不负责让容器活着。
组件 | 主要依赖 | 全宕后影响 |
|---|---|---|
kubectl | CRUD 所有资源 | 完全无法操作 |
Controller Manager | Watch 资源变化、更新状态 | 停止调谐,自愈停摆 |
Scheduler | Watch Pending Pod、写入绑定 | 新 Pod 永远 Pending |
kubelet | 获取 Pod 清单、上报状态 | 已有容器继续运行 |
kube-proxy | Watch Service/Endpoint | 转发规则仍生效 |
etcd | 被动被 API Server 访问 | 不受影响 |
实验之前,先理解每个组件的工作机制,观察现象时才能知其所以然。
Controller Manager 的设计哲学:持续观察集群当前状态,驱动至用户声明的期望状态。
它并非不断轮询 API Server,而是通过 Informer 机制建立长连接 Watch。全宕后:
各控制器的具体影响:
结论:Controller Manager 进程保持运行,但完全丧失获取新状态和修改资源的能力。已有 Pod 不会被主动删除,也不会被恢复。
Scheduler 的工作很简单:找到 spec.nodeName为空的 Pod(Pending),挑一个最优 Node,写回 Binding。
API Server 全宕后,调度决策无法写入 etcd,所有调度行为停滞。但 Scheduler 进程保持运行,持续尝试重连。
实际上,由于 kubectl 创建 Deployment 这一步就已经失败,根本不会有新 Pod 对象产生。但故障前已处于 Pending 的 Pod 会一直等下去。
结论:Scheduler 自身不崩溃,但无法获取新任务也无法写回调度结果。已运行的 Pod 不受影响。
很多人直觉认为:kubelet 失去了与集群的联络,Pod 应该会停止。
事实恰恰相反——不会停止。
kubelet 不是"远程遥控"的代理,它是运行在每个节点上的自主管理进程,拥有独立的本地状态和对容器运行时的直接控制权。
一旦某个 Pod 被调度到该节点并且 kubelet 成功启动了对应容器,这个 Pod 的运行状态就存在于一条完全的本地链路中,不再需要与 API Server 实时通信即可维持容器存活。
kubelet 内部有一个关键组件——**PLEG (Pod Lifecycle Event Generator)**。它通过定期调用 CRI 检查容器状态,只要容器运行时正常,PLEG 就能独立工作,不依赖 API Server。
API Server 全宕后,kubelet 受影响的功能:
但最关键的是:容器崩溃了,kubelet 仍然能在本地重新拉起。只要 Pod 的 restartPolicy为 Always或 OnFailure,kubelet 通过 PLEG 检测到退出事件后会在本地重新启动容器,整个过程无需 API Server 参与。
结论:API Server 故障期间,kubelet 仍能维护已运行容器,执行探针与重启策略。节点上的业务容器不会因 API Server 宕机而终止。
已刷入内核的 iptables/IPVS 规则仍然存在,Linux 内核不会主动删除。已有 Service 的流量转发不受影响。
但任何 Service/Endpoint 变化都无法同步,可能导致部分新 Pod 无法接收流量。
etcd 只与 API Server 通信,不感知上层的 Kubernetes 资源。API Server 只是 etcd 的一个客户端——API Server 宕机不会导致 etcd 停止。只要 etcd 集群满足 quorum,它就会继续运行。
etcd 的 Raft 共识和多数派机制,是整篇集群"扛住"的根本。
Pod 的删除需要经历完整的请求链路:
用户/控制器 → API Server 接收请求 → 写入 deletionTimestamp → kubelet 收到事件 → 执行清理
API Server 全宕时,删除请求根本无法被接收和处理。已在运行的 Pod 永远不会收到删除指令。
所有节点 Ready,核心组件 Running,部署 nginx 测试业务,验证访问正常。

实验前集群状态

核心组件 Pod 状态

测试业务创建及访问
kubeadm 将 API Server 作为静态 Pod 运行,停止方法是将清单文件移出监控目录:
# 在所有 Master 节点上执行
mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/
kubelet 几秒内检测到文件消失,停止对应容器。验证:
kubectl get nodes --request-timeout=5s
# client rate limiter Wait returned an error:
# context deadline exceeded - error from a previous attempt: EOF
kubectl get nodes
# Unable to connect to the server: EOF
⚠️ 排障提示:看到
EOF不要误以为是网络配置问题!本实验中 kubectl 经过 HAProxy LB,后端容器停止后 TLS 握手阶段就断开了,LB 把这个 EOF 透传给 kubectl。直连或等 LB 健康检查更新后,才会看到connection refused。

kubectl 连接被拒
登录 Worker 节点直接查看容器运行时:
sudo crictl ps | grep nginx
# e6cac9a74deae nginx 41 minutes ago Running nginx-f79c7c654-kfb52
容器仍在运行,启动时间停在 41 分钟前——API Server 的消失对已运行的容器没有任何影响。

nginx 容器仍在运行
验证业务流量:
curl http://<WorkerIP>:<NodePort>
# Welcome to nginx!
已有 Service 转发规则依然有效。

curl 访问成功
Controller Manager 日志中高频出现 Leader Election 租约获取失败:
E0715 06:59:22 leaderelection.go:461] "Error retrieving lease lock"
err="dial tcp 192.168.114.145:6443: connect: connection refused"
lock="kube-system/kube-controller-manager"
...(每 2-3 秒一条,持续输出)
注意:不是 Watch 失败,而是 Lease 续约失败。当前 leader 仍会在租期内尝试履职,但所有需要访问 API Server 的操作全部失败。进程从未退出。
Scheduler 日志显示它卡在启动阶段的缓存同步:
I0715 06:22:02 shared_informer.go:402] "Waiting for caches to sync"
Informer 需要从 API Server List 全量资源完成初始缓存同步,这一步永远无法完成。Scheduler 卡在启动流程中,既没有完成缓存同步,也没有进入正常调度循环。

Scheduler 与 Controller 真实日志
尝试扩容和创建新 Pod 均失败:
kubectl scale deployment nginx --replicas=5
# Unable to connect to the server: EOF
kubectl run test-nginx --image=nginx
# Unable to connect to the server: EOF

kubelet 与 API Server 的交互远不止心跳上报,至少涉及四类请求:
# 1. Lease 续约失败(节点心跳)
E0715 15:31:14 controller.go:201] "Failed to ensure lease exists"
err="...EOF" interval="7s"
# 2. Node Status 上报失败
E0715 15:31:16 kubelet_node_status.go:479] "Error updating node status"
err="...EOF"
# 3. Webhook 认证失败
E0715 15:31:10 webhook.go:154] Failed to make webhook authenticator request
err="...EOF"
# 4. Event 写入失败
E0715 15:31:11 event.go:368] "Unable to write event"
err="...EOF"
⚠️ 关键点:由于 Node Controller 自身也无法通过 API Server 更新节点状态,所以节点不会被标记为 NotReady,基于 NotReady 触发的 Pod 驱逐也不会发生。整个集群对节点状态的观察是"冻结"的。
这是本次实验最关键的验证——手动停掉一个容器,看 kubelet 能否自行拉起。
步骤 1:查看 nginx 容器,记录 ID
sudo crictl ps | grep nginx
步骤 2:手动停止该容器
sudo crictl stop <container-id>
步骤 3:再次查看——全新容器 ID,启动时间在几秒内
sudo crictl ps | grep nginx
# 全新的容器 ID,刚刚启动

容器重启前后 ID 对比
✅ 这直接证明了:kubelet 对已调度到本节点的 Pod 拥有完整的本地自治能力。容器的存活与 API Server 无关,完全由节点上的 kubelet 和容器运行时决定。
将清单文件移回原位:
mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/
kubelet 检测到文件变化,约 30 秒至 1 分钟后 API Server 完全就绪。

API Server 容器恢复
恢复后,各组件迅速重新建立 Watch 连接:

恢复后集群状态
组件/资源 | 故障期间 | 恢复后 |
|---|---|---|
API Server | 完全不可用 | 容器重建后恢复 |
etcd | 正常运行,数据完整 | 无影响 |
Controller Manager | Watch 中断,调谐停止 | 重新同步,继续 Reconcile |
Scheduler | 无法调度新 Pod | 立即处理积压 Pending Pod |
kubelet | 本地维护容器,可重启 | 恢复上报,获取新 Pod |
已有 Pod | 正常运行,不受影响 | 无影响 |
已有 Service 流量 | 转发规则仍在内核中 | 同步最新规则变更 |
新 Pod 创建 | 完全失败 | 控制器按需创建 |
Node 状态 | 冻结,不标 NotReady | 心跳恢复,状态更新 |
这背后是四个核心设计原则的集中体现:
/healthz或 /readyz做健康检查Q:API Server 全宕后,Pod 会被杀掉吗?
A:不会。Pod 删除需要 API Server 下发 deletionTimestamp。API Server 不可用时,删除命令根本无法生成。
Q:API Server 挂了还能创建 Pod 吗?
A:不能。创建 Pod 的第一步就是访问 API Server,不可达则整个流程中断。
Q:挂多久才算危险?
A:没有绝对阈值。短期中断业务通常无感,但随着时间拉长,自动扩容、故障自愈、状态同步全部丧失。建议 5 分钟内恢复,超过 15 分钟需人工介入。
Q:恢复后数据会丢失吗?
A:不会。期望状态完整保存在 etcd 中,恢复后控制器根据 etcd 数据进行 Reconcile,使集群恢复一致。
Q:故障期间节点重启了怎么办?
A:节点重启后 kubelet 需从 API Server 获取 Pod 清单。如果 API Server 仍不可用,Pod 无法恢复,直到 API Server 恢复后由控制器在其他节点重建。
理解这些行为,也就掌握了 Kubernetes 高可用架构设计的核心思想: 控制面可以短暂"失聪失明",但只要 etcd 数据完好、数据面组件健壮,业务就能持续运行,系统终将自愈。
如果这篇文章帮你真正理解了 Kubernetes 控制面与数据面的边界,欢迎关注 「一根头发丝的宽度」。 这里不会只讲概念,而是坚持用 真实实验 + 源码原理 + 架构图解,拆开 Kubernetes 每一个容易误解的知识点。 本文完整实验过程、所有命令、日志截图、组件时序图,以及 API Server 故障实验 EP.1~EP.3 已整理到个人站点。 📖 点击「阅读原文」,查看完整版。