02. Kubernetes 控制平面架构与核心工作负载
“你告诉 Kubernetes 系统你期望的终态(Desired State),控制器便会永不停歇地观察当前实际状态(Actual State),并自动消除二者之间的偏差。”
如果说 Docker 解决了单个容器的打包与环境封装,那么 Kubernetes (K8s) 则解决了成千上万个跨主机容器的高可用编排、自动恢复、弹性伸缩与流量分发。
本章将剥离表象,深入剖析 Kubernetes 控制平面的核心组件、声明式协调循环(Reconciliation Loop)运行机制、Pod 的生命周期与三大探针,以及在生产环境下实现“零宕机”(Zero-downtime)滚动更新的工程实践。
1. Kubernetes 架构全景:声明式终态哲学
传统运维多采用**命令式(Imperative)思维(例如:“在 3 台机器上启动该二进制,若某机器挂了则执行启动脚本”)。而 Kubernetes 采用的是声明式(Declarative)**思维(“我声明这个应用需要 3 个副本,且每个副本必须健康存活”)。
Kubernetes 的所有控制器都遵循经典的 协调循环(Reconciliation Loop):
集群架构全景拓扑
整个集群划分为两大部分:负责决策调度的 控制平面(Control Plane) 与承载实际业务负载的 工作节点(Worker Nodes):
2. 控制平面(Control Plane)核心组件剖析
2.1 kube-apiserver:集群的唯一中枢大脑
- 单点交互原则:集群内部的所有组件(Scheduler、Controller-Manager、Kubelet、Kube-proxy)甚至管理员
kubectl,只能与 API Server 交互。除 API Server 外,任何组件都无权直接读写 etcd。 - 三层过滤拦截:每个进入 API Server 的请求都必须通过三道严密防线:
- 认证(Authentication):验证你是谁(X509 客户端证书、ServiceAccount Token、OIDC)。
- 授权(Authorization):验证你能做什么(RBAC 角色绑定、ABAC)。
- 准入控制(Admission Control):变更或校验资源配置(Mutating Webhook 注入 sidecar,Validating Webhook 校验资源是否合规)。
- 水平伸缩与无状态:API Server 本身不保存任何持久状态,所有数据持久化全交由 etcd,因此可在负载均衡器(Load Balancer)后横向扩展任意数量节点。
2.2 etcd:高可用强一致性分布式存储
- Raft 算法保证共识:保存了整个集群所有的配置、秘钥、资源对象状态。
- Quorum 仲裁法定人数:集群规模通常为奇数个(3 或 5 节点)。一个 3 节点的 etcd 集群允许 1 台容灾;5 节点集群允许 2 台故障。
- 高效的 Watch 机制:客户端无需轮询,API Server 通过 HTTP/2 gRPC 流式 Watch 监听 etcd 的键值版本号(ResourceVersion)变更,并毫秒级下发事件给各类 Controller。
生产性能防线
etcd 对磁盘的写入延迟极其敏感。生产环境中必须将 etcd 数据目录挂载在高 IOPS 的 NVMe SSD(fsync 延迟保持在 10ms 以内),否则可能因心跳写入超时导致 Leader 频繁重新选举,引发整个集群 API 抖动。
2.3 kube-scheduler:智能调度流水线
Scheduler 负责为新建的未绑定节点的 Pod 寻觅最合适的 Worker Node。调度流程分为严密的两个阶段:
- 预选阶段(Filtering / Predicates):
- 资源是否充足(
NodeResourcesFit):CPU/内存 requests 必须小于节点可分配余量。 - 节点标签匹配(
NodeSelector/NodeAffinity)。 - 节点污点检测(
Taints & Tolerations):节点有污点且 Pod 无对应容忍度则淘汰。
- 资源是否充足(
- 优选阶段(Scoring / Priorities):
- 资源最少浪费原则(
NodeResourcesBalancedAllocation):尽量使节点的 CPU 和内存利用率比例相近。 - 拓扑打散调度(
PodTopologySpread):避免同一服务的多个副本挤在同一台物理机或同一个机房可用区。 - 镜像本地缓存优选(
ImageLocality):若目标节点已有该镜像,则优先考虑以减少网络拉取时间。
- 资源最少浪费原则(
2.4 kube-controller-manager:声明式控制器集群
一个聚合了数十个控制器的进程,内部各个控制器独立运行并共同维护终态:
- DeploymentController:监视 Deployment 变更,负责创建/更新/回滚 ReplicaSet。
- ReplicaSetController:保证某一时刻 Pod 的副本数严格等于声明的
spec.replicas。 - NodeLifecycleController:定期检查节点心跳,若节点失联超过容忍阈值(默认 5 分钟),自动驱逐其上的 Pod 并在健康节点重建。
- EndpointSliceController:监听 Pod IP 与端口变化,动态更新 Service 后端的端点切片列表。
3. 工作节点(Worker Node)运行机制
3.1 kubelet 与 CRI 容器运行时接口
- Node 代理人:kubelet 是运行在每个计算节点上的核心守护进程。它定期向 API Server 汇报本机资源与 Pod 健康状态。
- CRI (Container Runtime Interface):K8s 放弃了与特定容器引擎(早期直接绑定 Docker Engine)的强耦合,制定了标准 CRI gRPC 接口:
3.2 kube-proxy:四层服务代理
每个节点上的 kube-proxy 持续监听 API Server 中 Service 和 EndpointSlice 的变化,并在宿主机上将这些规则同步写入内核的 iptables 规则表或 IPVS (IP Virtual Server) 哈希表中,实现集群内部高效的软负载均衡。
4. Pod 拓扑与生命周期深度模型
4.1 为什么 Pod 是最小原子单元?
很多初学者疑惑:“为什么 K8s 不直接调度容器,而要在外面套一层 Pod?”
- 多进程协同与共享上下文:在分布式系统中,主业务容器常常需要辅助容器协作(如日志收集 Logstash sidecar、配置热重载 agent、Envoy 代理网关)。
- Pause 容器(Infra 容器)的魔法: 每个 Pod 启动时,K8s 都会先拉起一个极其微小的系统级容器
pause(体积仅几百 KB)。Pause 容器首先创建并占住独立的 Network Namespace 与 IPC Namespace。随后的业务容器和 Sidecar 容器均通过docker run --net=container:pause方式加入该网络空间。因此:- 同一个 Pod 内的多个容器可以通过
localhost互相极速通信。 - 同一个 Pod 内的多个容器共享相同的 IP 地址和虚拟网卡。
- 同一个 Pod 内的容器可以通过挂载相同的本地卷(Volume)共享文件。
- 同一个 Pod 内的多个容器可以通过
4.2 Pod 生命周期三大探针(Probes)
没有探针的容器在生产环境中犹如盲盒运行。Kubernetes 提供了三种职能截然不同的探针:
三大探针职责与生产设计准则
startupProbe(启动探针):- 适用场景:针对冷启动较慢的大型应用(如 Java Spring Boot 需要加载大量 Bean 耗时 40 秒)。
- 核心价值:在
startupProbe成功前,系统不会执行livenessProbe。避免了慢启动应用在还没完全就绪时,就被急躁的存活探针误判为死锁而不断触发 Kill 重启。
livenessProbe(存活探针):- 适用场景:检测死锁、死循环等进程处于运行中但已无法响应业务逻辑的状态。
- ⚠️ 生产高危避坑:绝对不要在 livenessProbe 中去请求下游数据库(MySQL)或外部缓存(Redis)! 一旦外部数据库出现短暂网络抖动,所有 Pod 的存活检测同时超时,导致全集群所有业务副本同时被杀崩溃,引发灾难性级联雪崩。
readinessProbe(就绪探针):- 适用场景:判断容器是否准备好处理请求。例如:缓存预热完成、数据连接池已建立。
- 触发动作:仅调整网络路由(从 Service 的 Endpoint 列表剔除),不会杀掉容器。
4.3 动态交互仿真:Kubernetes Pod 三大探针生命周期时序
为了让读者直观理解三大探针在容器冷启动、服务就绪、业务死锁自愈过程中的严格时序联动,请操作下方内置仿真器:
💡 探针仿真器实战操作指南
- 测试用例 1:模拟慢应用冷启动上线
- 点击 「▶ 模拟冷启动上线」 按钮。
- 观察阶段状态由
Pending变为Running。在初期阶段,StartupProbe处于高优先级探测拦截保护中,此时Liveness与Readiness探针处于屏蔽挂起状态。 - 当启动初始化完成,
StartupProbe变成Success,系统立即交接给Readiness探针。就绪检查通过后,Service 流量状态瞬间切入 「● 接收生产流量 (In Service)」!
- 测试用例 2:模拟死锁故障注入与 kubelet 自动自愈
- 在 Pod 正常服务状态下,点击 「⚡ 注入死锁故障 (触发自愈)」 按钮。
- 观察
LivenessProbe探针立刻检测到异常并报红失败。 - 一旦存活探针连续失败达到
failureThreshold阈值,kubelet 立即执行杀毁并拉起新容器,同时重启计数RestartCount自增,演示了 K8s 无人值守的终态自愈能力。
4.4 Pod 优雅停机与流量注销时序
在版本迭代时,强行切断正在执行的请求会导致用户端出现大量 HTTP 502/504 错误。K8s 的平滑下线机制如下:
5. Deployment 零宕机滚动更新实战
5.1 RollingUpdate 核心数学参数
Deployment 通过管理下层的 ReplicaSet 实现无损发布。控制滚动更新步长有两个核心参数:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # 允许超出期望副本数的最大上限 (向上取整)
maxUnavailable: 0 # 允许处于不可用状态的最大副本数 (生产推荐设为 0,确保容量不降级)假设我们有 replicas: 4,配置 maxSurge: 1,maxUnavailable: 0:
- 第 1 步:集群副本数允许最多为
个。K8s 创建 1 个新版本 Pod。此时旧 Pod 为 4,新 Pod 为 1。 - 第 2 步:新 Pod 启动并通过
readinessProbe验证后,正式接收流量。 - 第 3 步:销毁 1 个旧 Pod,总数恢复为 4 个(3 旧 + 1 新)。
- 第 4 步:重复上述过程,直到所有 4 个副本全部平滑过渡为新版本。发布全程处理容量始终
。
5.2 工业级生产 Deployment 黄金模版
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
namespace: production
labels:
app.kubernetes.io/name: user-service
app.kubernetes.io/part-of: e-commerce
spec:
replicas: 3
revisionHistoryLimit: 10 # 保留 10 个历史版本供回滚
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
terminationGracePeriodSeconds: 45 # 优雅下线总宽限时间
# 1. 拓扑打散与高可用反亲和 (避免所有副本调度到同一台母机)
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- user-service
topologyKey: kubernetes.io/hostname
# 2. 容器级安全上下文硬化
securityContext:
runAsNonRoot: true
runAsUser: 10001
fsGroup: 10001
containers:
- name: server
image: registry.example.com/apps/user-service:v1.4.2
imagePullPolicy: IfNotPresent
# 3. 严格的硬件资源配额 (避免未受控进程打崩节点)
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2000m"
memory: "1Gi"
ports:
- containerPort: 8080
name: http
# 4. 生产级生命周期钩子 (配合流量注销)
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15"]
# 5. 三层探针防御闭环
startupProbe:
httpGet:
path: /healthz/startup
port: http
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12 # 最多允许启动耗时 60s
livenessProbe:
httpGet:
path: /healthz/liveness
port: http
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /healthz/readiness
port: http
periodSeconds: 5
timeoutSeconds: 2
successThreshold: 1
failureThreshold: 25.3 Kubernetes Pod 生产常见异常状态排障决策树
当面对生产报警、Pod 无法提供服务时,最忌讳盲目重启。以下决策树梳理了一线大厂面对常见 Pod 异常状态的标准化处置闭环:
高频生产 Pod 诊断排查指令速查表
| 诊断目标 | 推荐执行命令 | 核心关注点 |
|---|---|---|
| 查看调度与生命周期事件 | kubectl describe pod <pod-name> -n <ns> | 重点看底部的 Events 区域,关注 FailedScheduling、BackOff、Unhealthy |
| 查看容器崩溃前现场日志 | kubectl logs <pod-name> -c <container> --previous -n <ns> | 查看上一次被杀灭容器遗留的致命崩溃堆栈(OOM 或 Panic) |
| 实时跟踪业务输出流 | kubectl logs -f <pod-name> --tail 200 -n <ns> | 观察服务初始化与请求处理日志 |
| 检查节点资源分配压力 | kubectl top pod -n <ns> --containers | 观察容器的实时 CPU(毫核)与内存占用,评估是否接近 limits 瓶颈 |
| 轻量级临时调试勘验 | kubectl debug -it <pod-name> --image=nicolaka/netshoot | 挂载 netshoot 瑞士军刀容器进行 DNS、网络连通性现场测试 |
6. 本章小结
- 控制平面中枢:API Server 是唯一交互入口,etcd 依赖 Raft 确保强一致性,Scheduler 分过滤与打分二阶段完成精准投放,Controller Manager 是驱动状态自愈的协调引擎。
- Pod 原子模型:依托 Pause 容器建立共享的 Network 与 IPC 空间,实现高效进程级协同。
- 探针防线:
startupProbe阻挡启动冷杀,livenessProbe防范僵死,readinessProbe精准截流。 - 零宕机发布:结合
maxUnavailable: 0、preStop延迟停机与readinessProbe,构建无感知无断流的平滑滚动更新。
在下一章中,我们将进入集群内的网络深水区,探讨跨节点容器互联、Service 四层负载与 Ingress 七层路由:03. 服务发现与 Ingress 路由 (含仿真)。