Kubernetes 控制平面由哪些组件组成?它们如何协同工作?
Kubernetes 控制平面是集群的决策层,负责接收请求、保存状态、做调度决策,并不断把实际状态拉回到期望状态。它通常由 kube-apiserver、etcd、kube-scheduler、kube-controller-manager 和 cloud-controller-manager 组成。简单说,API Server 是入口,etcd 是账本,Scheduler 负责把 Pod 放到合适节点,Controller Manager 负责持续纠偏,Cloud Controller Manager 负责和云厂商资源打交道。真正排障时,不要把它们看成一组静态组件,而要看一次资源变更如何流过这些组件。
控制平面的核心组件
kube-apiserver
kube-apiserver 是所有请求的统一入口,kubectl、控制器、调度器、Webhook 和外部系统都通过它读写集群资源。它负责认证、授权、准入控制、对象校验和 API 聚合,最后再把合法状态写入 etcd。API Server 本身是无状态组件,所以可以部署多个副本放在负载均衡器后面。边界是:它不直接创建容器,也不负责调度,只负责让状态变更有统一入口。
bashkubectl get --raw='/readyz?verbose' kubectl get pods -n kube-system -l component=kube-apiserver
etcd
etcd 保存 Kubernetes 的全部关键状态,包括 Pod、Deployment、Service、Secret、ConfigMap、Node 状态和 Lease。它基于 Raft 保证一致性,常见生产部署是 3 或 5 个成员。取舍很明确:etcd 强一致带来可靠状态,但对磁盘延迟、网络抖动非常敏感。踩坑最多的是只备份了业务数据,忘了备份 etcd;一旦控制平面故障,集群对象就很难恢复。
bashETCDCTL_API=3 etcdctl snapshot save /backup/etcd.db \ --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
kube-scheduler
kube-scheduler 监听还没有绑定节点的 Pod,先过滤掉不满足资源、亲和性、污点容忍、端口、卷拓扑等条件的节点,再给剩余节点打分,最后把绑定结果写回 API Server。它不会启动 Pod,真正启动容器的是工作节点上的 kubelet。一个常见误区是以为 Pod Pending 一定是调度器坏了,实际更多是 CPU/内存 request 太高、PVC 未绑定、节点污点没容忍或亲和性规则写得过硬。
kube-controller-manager
kube-controller-manager 运行一组控制器,例如 Deployment、ReplicaSet、Node、Job、CronJob、EndpointSlice、ServiceAccount 等控制器。控制器的模式是 watch 资源变化,比较期望状态和实际状态,然后发起下一步变更。比如 Deployment 期望 3 个副本,实际只有 2 个,ReplicaSet 控制器会补一个 Pod;Node 长时间失联,Node Controller 会更新状态并触发后续驱逐。它的价值在“持续调和”,不是执行一次就结束。
cloud-controller-manager
cloud-controller-manager 把云厂商相关逻辑从 Kubernetes 核心里拆出来,负责云节点生命周期、LoadBalancer、路由和云盘等资源。自建裸金属集群可能没有它,云上集群通常离不开它。边界要分清:Service type=LoadBalancer 创建不出外部负载均衡时,问题经常不在 kube-proxy,而在云控制器权限、配额、子网标签或安全组配置。
yamlapiVersion: v1 kind: Service metadata: name: web spec: type: LoadBalancer selector: app: web ports: - port: 80 targetPort: 8080
一次创建 Pod 会发生什么
用户执行 kubectl apply 后,请求先到 API Server,经过认证、授权和准入控制,再写入 etcd。Scheduler 看到这个 Pod 没有 spec.nodeName,开始选择节点并写入绑定结果。目标节点上的 kubelet watch 到属于自己的 Pod 后,通过容器运行时拉镜像、创建容器、挂载卷并上报状态。控制器同时观察这些状态,如果副本数不足、节点异常或对象被删除,就继续发起新的调和动作。
bashkubectl apply -f pod.yaml kubectl get pod demo -o wide kubectl describe pod demo kubectl get events --sort-by=.metadata.creationTimestamp
追问
API Server 为什么要设计成无状态?
无状态的好处是可以水平扩展,多个 API Server 实例后面挂一个负载均衡器即可提升可用性。状态统一放在 etcd,避免每个 API Server 各自保存一份数据导致一致性问题。取舍是 API Server 对 etcd 的依赖非常强,etcd 慢了,整个集群的读写都会跟着慢。生产环境里经常把 API Server 扩了很多副本,却忽略了 etcd 磁盘延迟,这类扩容收益很有限。
etcd 为什么通常部署奇数个节点?
etcd 使用 Raft,多数派可用才能提交写入,所以 3 节点能容忍 1 个故障,5 节点能容忍 2 个故障。偶数节点并不会提高多数派容错能力,比如 4 节点仍只能容忍 1 个故障,反而增加同步成本。边界是成员越多写入延迟越高,不是越多越安全。小中型集群用 3 个 etcd 成员通常比盲目堆到 7 个更稳。
Scheduler 和 Controller Manager 都在“控制状态”,区别是什么?
Scheduler 只解决“这个未调度 Pod 放到哪个 Node”这个决策问题,核心输出是绑定关系。Controller Manager 负责更广的持续调和,比如副本数、节点状态、EndpointSlice、Job 完成情况等。踩坑点是排查 Pending Pod 时先看调度事件,排查副本补不齐时再看控制器和 ReplicaSet 事件。把两者混在一起,容易误判问题方向。
控制平面高可用是不是只要多部署几个 master?
不是。高可用至少要考虑 API Server 多副本、etcd 多成员、Controller Manager 和 Scheduler 的 leader election、前置负载均衡器以及证书和备份。只加 master 节点但 etcd 仍是单点,故障时集群状态照样不可写。另一个边界是多副本不等于无限可用,错误的准入 Webhook、过期证书或慢 etcd 仍可能让整个控制面卡住。
控制平面异常时应该先看什么?
先看 API Server 的 readyz、etcd 健康和 kube-system 里控制平面 Pod 日志,再看事件和证书有效期。不要一上来重启所有组件,尤其是 etcd 抖动时,频繁重启会放大选主和恢复时间。命令层面可以从 kubectl get --raw=/readyz?verbose、kubectl get componentstatuses(旧集群可用)和 journalctl -u kubelet 开始。能访问节点但访问不了 API Server 时,还要检查负载均衡器、6443 端口和控制平面证书。