引言
Kubernetes(K8s)已经事实上成为云原生时代的操作系统。当我们执行一条 kubectl apply 命令时,背后涉及的组件交互远比表面看起来复杂得多。本文将深入剖析 K8s 控制平面的架构演化路径,从其设计哲学出发,逐一拆解 API Server、Controller Manager、Scheduler 以及 etcd 等核心组件的协同机制,帮助读者建立对分布式系统编排的全局认知。
1. 控制平面的职责边界
Kubernetes 采用声明式 API 模型——用户描述期望状态(Desired State),控制平面负责将当前状态(Current State)向期望状态收敛。这一过程涉及四个核心问题的回答:
- 接收:谁来接收用户的声明式请求?→ kube-apiserver
- 存储:期望状态和当前状态如何持久化?→ etcd
- 观察:如何感知状态偏差?→ informer/listener 机制
- 执行:谁来驱动状态收敛?→ Controller 循环
这四个问题构成了理解 K8s 控制平面的基本框架。
2. kube-apiserver:统一入口的设计哲学
API Server 是 K8s 控制平面中唯一直接与 etcd 交互的组件,这种"单写入点"设计极大地简化了一致性保障。所有其他组件(Controller Manager、Scheduler、kubelet)都作为 API Server 的客户端运行,通过 Watch 机制监听资源变更。
API Server 的架构分层:
- 认证层(Authentication):支持 X.509 客户端证书、Bearer Token、ServiceAccount Token、OIDC 等多种身份认证方式
- 鉴权层(Authorization):RBAC、ABAC、Node、Webhook 等多种策略模式
- 准入控制层(Admission):MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 允许用户在持久化前后拦截和修改请求
- Registry 层:资源路由与 REST Storage 实现
值得注意的是,API Server 本身不执行任何业务逻辑——它是一个纯粹的 RESTful CRUD 中介。这种"瘦服务器"设计使得控制平面的可扩展性大幅提升:新增资源类型只需实现对应的 REST Storage 接口。
3. etcd:分布式一致性的基石
etcd 是 K8s 集群的"唯一事实源(Single Source of Truth)",基于 Raft 共识算法实现强一致性。理解 etcd 的工作机制对排查集群性能瓶颈至关重要。
3.1 Raft 协议核心机制
Raft 通过选举一个 Leader 来处理所有客户端写入请求。其核心流程:
- Leader 选举:节点超时未收到心跳则发起 RequestVote,获得多数票成为 Leader
- 日志复制:Leader 追加日志条目后向 Follower 发送 AppendEntries,多数节点确认后提交
- 安全性保证:已提交的日志条目不会丢失;所有节点最终看到相同的日志序列
3.2 etcd 在 K8s 中的存储布局
K8s 所有资源以键值对形式存储在 etcd 中,键的命名遵循层级结构:
/registry/pods/<namespace>/<pod-name>
/registry/deployments/<namespace>/<deployment-name>
/registry/services/<namespace>/<service-name>
/registry/configmaps/<namespace>/<configmap-name>
3.3 性能优化实践
生产环境中 etcd 往往是 K8s 集群的性能瓶颈。常见优化手段包括:
- 使用高性能 SSD(etcd 对 I/O 延迟极其敏感)
- etcd 独立部署,避免与计算密集型工作负载共享磁盘
- 合理设置
--quota-backend-bytes并启用自动压缩 - 大集群考虑使用 etcd 分片(将事件类资源与核心资源分开存储)
4. Controller 模式:状态收敛的核心引擎
K8s 的设计精髓在于其 Controller 模式——每个 Controller 都是一个控制循环,持续观察集群状态并执行调谐(Reconcile)操作。
4.1 控制循环模型
for {
desired = getDesiredState()
current = getCurrentState()
if desired != current {
reconcile(desired, current)
}
}
这一简单模型蕴含着深刻的分布式系统智慧:
- 幂等性:Reconcile 函数可以安全地多次执行
- 自愈能力:即使中间过程出错,最终状态仍然会收敛
- 无状态:Controller 不需要保存历史状态,etcd 是唯一的持久化存储
4.2 Informer 机制:高效的状态观察
Informer 是 Client-go 提供的核心抽象,它替代原始的 Watch API,解决了以下问题:
- 本地缓存:减少 API Server 压力,读取操作直接命中本地内存
- 断线重连:使用 ResourceVersion 机制在断连后从正确位置恢复Watch
- 事件去重:Add/Update/Delete 事件通过 DeltaFIFO 队列去重合并
5. Scheduler:从优先级到 Framework 的演进
K8s Scheduler 负责将待调度的 Pod 绑定到合适的 Node 上。其架构经历了从"一次性打分"到"调度框架(Scheduling Framework)"的演变。
5.1 调度流程
一次完整的调度过程分为两个阶段:
- 过滤(Filtering/Predicates):排除不满足条件的 Node(如资源不足、亲和性冲突、污点容忍失败等)
- 打分(Scoring/Priorities):对通过过滤的 Node 进行加权评分,选择得分最高者
5.2 Scheduling Framework 扩展点
K8s 1.16 引入的 Scheduling Framework 通过插件化架构允许用户在调度周期的多个扩展点注入自定义逻辑:
- QueueSort:自定义 Pod 排队策略
- PreFilter/Filter:前置检查和节点过滤
- PreScore/Score:前置评分和节点评分
- Reserve/PreBind/Bind:资源预留和节点绑定
- PostBind/Unreserve:绑定后和资源释放处理
6. 控制平面的高可用设计
生产级 K8s 集群控制平面必须支持高可用(HA),主要涉及以下组件的冗余部署:
- API Server:多副本 + 负载均衡(通常前置 nginx/haproxy)
- etcd:奇数节点集群(3/5/7),Raft 多数派写入保证一致性
- Controller Manager:通过 Leader Election(基于 etcd/Endpoint 锁)实现主备切换
- Scheduler:同样基于 Leader Election 实现 Active-Standby 模式
值得一提的是,Controller Manager 和 Scheduler 的 Leader Election 机制本身也依赖 API Server 和 etcd —— 这是一个自举(Bootstrapping)的过程。
7. 未来展望:从中心化到分布式调度
随着集群规模持续扩大(5000+ 节点),传统中心化控制平面面临越来越大的挑战。社区正在探索的方向包括:
- K8s 联邦(KubeFed / Karmada):跨集群统一调度与控制
- 边缘场景精简:K3s、KubeEdge 等轻量化方案
- Serverless 容器:Knative、AWS Fargate 将调度粒度细化到请求级别
- Wasm 与 Unikernel:轻量级运行时对调度模型提出新要求
总结
Kubernetes 控制平面的设计体现了分布式系统的核心原则:通过声明式 API 简化用户心智,通过 etcd 保证强一致性,通过 Controller 模式实现自愈,通过插件化架构保持可扩展性。理解这些底层机制,不仅能帮助我们在生产环境中更高效地排查问题,也为构建自己的 Operator 和控制器奠定了坚实基础。在云原生的宏大叙事中,K8s 控制平面只是起点,而非终点。

发表评论 取消回复