LabHub
学习 学习路径 课程

CKA — Kubernetes 管理员

控制平面为什么被拆成四块

在 LabHub 中继续学习

一句话总结

Kubernetes 控制平面分为 etcd、kube-apiserver、kube-controller-manager、kube-scheduler 四个进程,其中只有 apiserver 与 etcd 对话。这一句话解释了 CKA 故障排查的一半。

概念图: 只有 apiserver 与 etcd 对话 · 存储格式 · 全部绕过 · apiserver 设为唯一入口

为什么需要它

设想 scheduler 直接连接 etcd,读取 Pod 对象并写入 nodeName,会发生什么?

因此 Kubernetes 把 apiserver 设为唯一入口。apiserver 不创建状态,只负责接收、验证、授权、保存,并通知观察者。真正的判断全部由外部控制器完成。

它如何运作

控制器的 reconcile 循环如下。

  1. 通过 watch 读取声明状态(spec)
  2. 观测实际状态(status)
  3. 计算差异,只调用足以消除差异的 API
  4. 返回第 1 步

关键在于它不是执行命令,而是缩小差异。因此即使漏掉一个事件,也会在下次 resync 时收敛;控制器重启后,也会从头重新对齐。Deployment 控制器创建 ReplicaSet,ReplicaSet 控制器创建 Pod,各自只关注自己下面的一层。

scheduler 分两个阶段运行。

阶段 工作 结果
filter (predicate) 排除资源不足、taint 未被容忍、nodeSelector 不匹配、volume zone 不匹配的节点 可放置节点列表
score (priority) 为剩余节点打分(资源平衡、镜像本地性、拓扑分散) 得分最高的一个节点

0/3 nodes are available: 3 Insufficient cpu 这样的消息,就是 filter 阶段淘汰原因的汇总表。读懂这句话,90% 的 Pending Pod 都能当场诊断完毕。

在实际工作中会遇到的情况

案例 1——DHCP 杀死了集群。家庭实验室控制平面的 IP 曾从 10.0.0.111 变为 10.0.0.120,原因是 DHCP 租约续期。症状为 dial tcp 10.0.0.111:6443: connect: no route to host,真正原因却在证书:apiserver 证书的 SAN 只有 IP Address:10.0.0.111,没有 .120。有趣之处是各组件反应不同。etcd 与 kube-apiserver 尝试绑定不存在的 .111,陷入 CrashLoopBackOff;kube-scheduler 和 controller-manager 绑定 127.0.0.1,所以进程仍活着,却什么也做不了。只有了解四个进程各自绑定不同地址的设计,才能读懂这幅图。

**案例 2——etcd quorum 与 API 可用性是两回事。**同一家庭实验室从 3 个节点扩展到 7 个节点时,控制平面增加到了 3 台。etcdctl member list 正确列出 3 个成员,每个节点也各自运行 apiserver、scheduler 和 controller-manager,看似已经实现 HA,其实没有。

controlPlaneEndpoint: 10.0.0.120:6443     # cp-1 의 물리 IP

该值不是 VIP 或 DNS,而是第一个节点的真实 IP。因此 cp-1 死亡后,etcd quorum 仍以 2/3 正常,cp-2、cp-3 的 apiserver 也正常运行,但 kubectl 与 7 个节点的 kubelet 会全部无法连接。而且证书 SAN 没有其他控制平面 IP,直接连接 cp-2 也会因 TLS 验证失败。数据可用性和访问可用性是不同的问题。

此外,把控制平面只增加到 2 台,比 1 台还更危险。2 个成员的多数仍是 2,任意一台死亡都会丢失 quorum。推荐奇数(1、3、5)正是这个原因,所以这次扩展也必须做到 3 台。

后续实验要做什么

第一个实验将调查集群,操作 namespace、label 和 annotation,亲自创建并切换 kubeconfig context,再用 kubectl explain--dry-run=client -o yaml 生成 manifest。第二个实验会亲自编写 CustomResourceDefinition 扩展 API,目标是亲眼看到 schema 验证真正拒绝请求的瞬间。