Kubernetes 集群心脏揭秘
本篇文章不聊 Deploy、STS、DS 的内容,只介绍维持 Kubernetes 系统运行的核心组件。
我一向认为 k8s 是非常稳定的,Pod 挂了通过 ReplicaSet 的上层控制以及各种调谐,使系统重新回到 yaml 所期望的状态。那么对于 k8s 集群本身,其架构是如何设计的呢?
集群架构
k8s 中的集群节点有2类,分别是 control plane node 和 worker node 即控制平面节点(master)和工作节点(node)。
1 2 3 4 5 6 7 8 9 10
| [root@k8s-master-01 ~]# k get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME k8s-master-01 Ready control-plane 490d v1.37.0 192.168.41.81 <none> Rocky Linux 8.10 (Green Obsidian) 5.4.293-1.el8.elrepo.x86_64 (amd64) containerd://2.0.12 k8s-master-02 Ready control-plane 296d v1.37.0 192.168.41.82 <none> Rocky Linux 8.10 (Green Obsidian) 5.4.293-1.el8.elrepo.x86_64 (amd64) containerd://2.0.12 k8s-master-03 Ready control-plane 38d v1.37.0 192.168.41.83 <none> Rocky Linux 8.10 (Green Obsidian) 5.4.293-1.el8.elrepo.x86_64 (amd64) containerd://2.0.12 k8s-node-01 Ready <none> 462d v1.37.0 192.168.41.87 <none> Rocky Linux 8.10 (Green Obsidian) 5.4.293-1.el8.elrepo.x86_64 (amd64) containerd://2.0.12 k8s-node-02 Ready <none> 676d v1.37.0 192.168.41.88 <none> Rocky Linux 8.10 (Green Obsidian) 5.4.293-1.el8.elrepo.x86_64 (amd64) containerd://2.0.12 k8s-node-03 Ready <none> 676d v1.37.0 192.168.41.89 <none> Rocky Linux 8.10 (Green Obsidian) 5.4.293-1.el8.elrepo.x86_64 (amd64) containerd://2.0.12 k8s-node-04 Ready <none> 571d v1.37.0 192.168.41.52 <none> Rocky Linux 8.10 (Green Obsidian) 5.4.293-1.el8.elrepo.x86_64 (amd64) containerd://2.0.12 k8s-node-05 Ready <none> 571d v1.37.0 192.168.41.53 <none> Rocky Linux 8.10 (Green Obsidian) 5.4.293-1.el8.elrepo.x86_64 (amd64) containerd://2.0.12
|
可以通过 ROLES 字段区分。
系统组件
在理解了节点角色分工之后,我们真正需要关心的是:这些节点上到底运行着什么,才能让集群”活”起来?
Kubernetes 将自己最核心的基础设施全部收纳在 kube-system 这个特殊的命名空间中,当初始化一个新的 k8s 集群时会自动创建。它像是飞机的驾驶舱仪表盘——平时你可能不会刻意去看它,但一旦它出问题,整个系统就会陷入混乱。
接下来的部分,将逐一拆解这些组件的职责、部署方式以及它们之间如何协作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| [root@k8s-master-01 ~]# k -n kube-system get pods NAME READY STATUS RESTARTS AGE calico-kube-controllers-698c9b466c-qqz6p 1/1 Running 2 (2d ago) 3d20h calico-node-54hxr 1/1 Running 0 2d calico-node-cvs8p 1/1 Running 0 2d calico-node-dtfkj 1/1 Running 0 2d calico-node-k7kgh 1/1 Running 0 2d calico-node-nc9nn 1/1 Running 0 2d calico-node-p8nd2 1/1 Running 0 2d calico-node-qvq4d 1/1 Running 0 2d calico-node-w8q7x 1/1 Running 0 2d coredns-566bd48f4c-czqz8 1/1 Running 0 2d coredns-566bd48f4c-sl7z5 1/1 Running 0 2d coredns-566bd48f4c-wbvdd 1/1 Running 0 2d etcd-k8s-master-01 1/1 Running 0 2d etcd-k8s-master-02 1/1 Running 0 2d etcd-k8s-master-03 1/1 Running 0 2d kube-apiserver-k8s-master-01 1/1 Running 8 (2d1h ago) 10d kube-apiserver-k8s-master-02 1/1 Running 7 (12h ago) 10d kube-apiserver-k8s-master-03 1/1 Running 4 (13h ago) 10d kube-controller-manager-k8s-master-01 1/1 Running 1 (11h ago) 10d kube-controller-manager-k8s-master-02 1/1 Running 1 (12h ago) 10d kube-controller-manager-k8s-master-03 1/1 Running 1 (11h ago) 10d kube-proxy-5qmbk 1/1 Running 1 (3d20h ago) 10d kube-proxy-7dmvx 1/1 Running 1 (2d1h ago) 10d kube-proxy-8dv8p 1/1 Running 1 (3d21h ago) 10d kube-proxy-gp2rv 1/1 Running 1 (3d20h ago) 10d kube-proxy-nkxfl 1/1 Running 1 (3d21h ago) 10d kube-proxy-t968r 1/1 Running 1 (3d21h ago) 10d kube-proxy-xqrvj 1/1 Running 3 (2d ago) 10d kube-proxy-zbqjd 1/1 Running 1 (3d20h ago) 10d kube-scheduler-k8s-master-01 1/1 Running 1 (11h ago) 2d2h kube-scheduler-k8s-master-02 1/1 Running 1 (13h ago) 10d kube-scheduler-k8s-master-03 1/1 Running 1 (12h ago) 10d
|
控制平面组件(Control Plane Components)
控制平面组件可以在集群中的任何节点上运行,不过为了简单起见,控制平面组件一般都会在 master 节点上启动,并且不会在这些节点上运行用户容器。包括示例中的:kube-apiserver、etcd、kube-scheduler、kube-controller-manager:
kube-apiserver
API server 是 Kubernetes 控制平面的前端,负责暴露 Kubernetes API,处理任何其它工具发出的任何请求(validate request & update cluster state in etcd)。
kube-apiserver 设计上考虑了水平扩缩,可通过部署多个实例来进行扩缩。可以运行 kube-apiserver 的多个实例,并在这些实例之间平衡流量。
一个请求的起点
无论你使用 kubectl、API 客户端还是 CI/CD 系统发起的任何操作,最终都会落到 API Server 上。它不仅是”入口”,更是”守门员”——负责认证(Authentication)、鉴权(Authorization)、准入控制(Admission Control)和校验(Validation),只有全部通过后,才会将变更持久化到 etcd 中。可以说,API Server 是控制平面的”唯一信源”,其他所有组件都通过它来 Watch 集群状态的变化。
etcd
一致且高可用的分布式键值存储,用作 Kubernetes 的所有集群数据和状态的后台数据库,存储着集群的全部期望状态和实际状态,包括 Pod、Service、ConfigMap、Secret 等所有资源对象。一旦 etcd 数据损坏或丢失,整个集群将无法恢复原有状态。
kube-scheduler
负责根据资源的可用性(cpu、memory、亲和性)选择节点来让新创建的 Pod 在上面运行。调度决策考虑的因素包括单个 Pod 及 Pods 集合的资源需求、软硬件及策略约束、亲和性及反亲和性规范、数据位置、工作负载间的干扰及最后时限。
kube-controller-manager
负责运行控制器进程来调节集群的状态。每种资源(Deployment/ReplicaSet/Node/Endpoint/Job…)都有一个 controller 不断 reconcile “期望状态” vs “实际状态”。
调谐循环(Reconciliation Loop)
Controller Manager 内部运行着数十个独立的控制器,每个控制器都在执行一个简单的死循环:
观察当前状态 → 对比期望状态 → 执行调整 → 再次观察。
这正是 Kubernetes 声明式 API 的核心魅力所在——你只需声明”要什么”,控制器负责”怎么做到”。而 Scheduler 则在这个循环中承担了”选址”的职责,两者配合,完成了从”API 收到请求”到”Pod 真正运行在节点上”的闭环。
这四个都是 static pod(由 master 节点上的 kubelet 直接读 /etc/kubernetes/manifests/*.yaml 拉起,不通过 Deploy 类似的控制器),所以即便 apiserver 全挂,kubelet 也能保活它们。
从集群状态也可以看出来,这些组件都只启动了3个副本,恰好对应本生产环境的 3 master 架构。
节点组件(Node Components)
介绍完了控制平面组件,接下来是节点组件,k8s 集群的每个节点上都会运行。如示例中的:kube-proxy,还有一些不是以 pod 的方式运行的,像 kubelet 和 Container Runtime。
kubelet
kubelet 会在集群中每个节点(node)上运行。它保证容器(containers)都运行在 Pods 中。
kubelet 接收一组通过各类机制提供给它的 PodSpecs,确保这些 PodSpecs 中描述的容器处于运行状态且健康。kubelet 不会管理不是由 Kubernetes 创建的容器。
kube-proxy
kube-proxy 是集群中每个节点(node)上所运行的网络代理,实现 Kubernetes 服务(Service)概念的一部分。
kube-proxy 维护节点上的一些网络规则,这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。
如果操作系统提供了可用的数据包过滤层,则 kube-proxy 会通过它来实现网络规则。否则,kube-proxy 仅做流量转发。
容器运行时(Container Runtime)
容器运行环境是负责运行容器的软件。
Kubernetes 支持许多容器运行环境,例如 containerd、CRI-O、Docker 以及 Kubernetes CRI 的其他任何实现。
插件组件(Add-ons)
示例中还有3个组件没有介绍,包括 calico-kube-controllers、calico 和 core-dns:
CoreDNS
集群 DNS,Pod 之间靠它进行 service name 解析。可以任意数量运行在任意节点。
1 2 3 4
| [root@k8s-master-01 ~]# k -n kube-system get pods -o wide | grep dns coredns-566bd48f4c-czqz8 1/1 Running 0 2d 10.244.16.181 k8s-node-05 <none> <none> coredns-566bd48f4c-sl7z5 1/1 Running 0 2d 10.244.45.2 k8s-node-02 <none> <none> coredns-566bd48f4c-wbvdd 1/1 Running 0 2d1h 10.244.151.142 k8s-master-01 <none> <none>
|
Calico(CNI)
Calico 是 CNI 组件,某种程度上也可以认为是节点级组件,在每台 node 上配 veth/路由,实现 Pod 网络互通。
Calico 特有的优势在于其丰富的 NetworkPolicy 能力,可以实现细粒度的网络访问控制。
calico-kube-controllers
Calico 的集群级 controller(管 IPAM、策略状态等)。
Calico 只是 Kubernetes 支持的网络方案之一(其他常见的有 Flannel、Cilium、Weave 等)。无论选择哪种 CNI,它们的核心目标都是一致的:为每个 Pod 分配唯一的集群内 IP,并保证 Pod 之间、Pod 与 Service 之间的网络连通性。
Leader Election
到这里 k8s 生产环境的基本运行组件介绍完了,但思考一个场景:3 master 集群有 3 个 kube-scheduler,新建一个 pod 时谁来决定到底在哪个 node 运行?
k8s 中有一个叫 Lease 的资源类型:
1 2 3 4 5 6 7
| [root@k8s-master-01 ~]# k get lease -n kube-system NAME HOLDER AGE apiserver-diis2xnf65zvyaf6hktjvqdqee apiserver-diis2xnf65zvyaf6hktjvqdqee_56c5d21e-c2a5-4af6-a557-bbd9174359eb 14h apiserver-i5s3kydaxcybcmw5e4zwn5q6qa apiserver-i5s3kydaxcybcmw5e4zwn5q6qa_bd9ee040-1a7e-411b-8294-d4f857e52bd5 12h apiserver-n5rqfbqvzhlrni7fhvncysbm4q apiserver-n5rqfbqvzhlrni7fhvncysbm4q_7bb6bf9c-3f90-490c-9096-7102201aa3e2 2d1h kube-controller-manager k8s-master-02_6e036f2f-0d64-4753-8ce4-553285c673c5 676d kube-scheduler k8s-master-02_a8d350dc-2029-47c6-8a0d-8251c7501a83 676d
|
scheduler 和 kube-controller-manager 在生产集群以多副本部署,但同一时刻只能有一个真正”干活”,否则会:
- 多个 scheduler 同时给同一个 Pod 选节点,产生双写冲突
- 多个 controller-manager 重复 reconcile,产生脑裂
所以它们用 Leader Election(领导者选举):所有副本都跑、都参与选举,但只有 leader 真正执行调度/调和逻辑,其它副本 standby。
选举过程走 apiserver 的 Lease 资源:
- 每个副本启动时去 apiserver 抢/续 Lease(
kube-scheduler / kube-controller-manager 两个固定名字);
- 谁先成功 PUT 谁就是 leader;
- Leader 必须周期性(默认 2s)更新
renewTime,超过 leaseDurationSeconds(默认 15s)未续约则视为失联,其它副本接管;
- 失去 leader 身份的副本只能读、不能写。
解释下 lease 里的字段和含义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| [root@k8s-master-01 ~]# k -n kube-system describe lease kube-scheduler Name: kube-scheduler Namespace: kube-system Labels: <none> Annotations: <none> API Version: coordination.k8s.io/v1 Kind: Lease Metadata: Creation Timestamp: 2024-11-01T12:42:02Z Resource Version: 323068962 UID: 2bac72c9-ee60-47f9-9a11-acd2dd010ce8 Spec: Acquire Time: 2026-09-08T19:15:24.260752Z Holder Identity: k8s-master-02_a8d350dc-2029-47c6-8a0d-8251c7501a83 Lease Duration Seconds: 15 Lease Transitions: 3 Renew Time: 2026-09-09T07:39:27.080804Z Events: <none>
|
- Acquire Time:当前 Lease 持有者成功获取到租约的时间戳;
- Holder Identity:持有者身份,nodeName + 每次创建时生成的 uuid;
- Lease Duration Seconds:持有者在失去租约前可以”宣称”自己仍是 leader 的时间(秒);
- Lease Transitions:此 Lease 从创建以来,切换持有者的总次数;
- Renew Time:续租时间,当前持有者最后一次成功续租的时间。
如果 Lease Transitions 的值很大(频繁切换),k8s 集群很可能有问题!
小结
回过头来看,Kubernetes 控制平面的设计体现了一种”共识优先、职责分离”的分布式系统思想:
- API Server 作为唯一入口,统一收敛所有变更;
- etcd 作为唯一存储,保证数据的一致性和可观测性;
- Scheduler 和 Controller Manager 通过 Leader Election 避免脑裂;
- kubelet 在每台节点上独立工作,不依赖中心控制平面的实时可用性。
这种分层解耦、各司其职的架构,正是 Kubernetes 能在云原生时代成为”操作系统级”基础设施的根本原因。而通过 Lease 资源观察 Leader 切换频率,也成了我们运维集群时一个简单却有效的”健康晴雨表”。