Skip to content

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 的请求都必须通过三道严密防线:
    1. 认证(Authentication):验证你是谁(X509 客户端证书、ServiceAccount Token、OIDC)。
    2. 授权(Authorization):验证你能做什么(RBAC 角色绑定、ABAC)。
    3. 准入控制(Admission Control):变更或校验资源配置(Mutating Webhook 注入 sidecar,Validating Webhook 校验资源是否合规)。
  • 水平伸缩与无状态:API Server 本身不保存任何持久状态,所有数据持久化全交由 etcd,因此可在负载均衡器(Load Balancer)后横向扩展任意数量节点。

2.2 etcd:高可用强一致性分布式存储

  • Raft 算法保证共识:保存了整个集群所有的配置、秘钥、资源对象状态。
  • Quorum 仲裁法定人数:集群规模通常为奇数个(3 或 5 节点)。一个 3 节点的 etcd 集群允许 1 台容灾;5 节点集群允许 2 台故障。Quorum=N/2+1
  • 高效的 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。调度流程分为严密的两个阶段:

  1. 预选阶段(Filtering / Predicates)
    • 资源是否充足(NodeResourcesFit):CPU/内存 requests 必须小于节点可分配余量。
    • 节点标签匹配(NodeSelector / NodeAffinity)。
    • 节点污点检测(Taints & Tolerations):节点有污点且 Pod 无对应容忍度则淘汰。
  2. 优选阶段(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 NamespaceIPC Namespace。随后的业务容器和 Sidecar 容器均通过 docker run --net=container:pause 方式加入该网络空间。因此:
    • 同一个 Pod 内的多个容器可以通过 localhost 互相极速通信。
    • 同一个 Pod 内的多个容器共享相同的 IP 地址和虚拟网卡。
    • 同一个 Pod 内的容器可以通过挂载相同的本地卷(Volume)共享文件。

4.2 Pod 生命周期三大探针(Probes)

没有探针的容器在生产环境中犹如盲盒运行。Kubernetes 提供了三种职能截然不同的探针:

三大探针职责与生产设计准则

  1. startupProbe(启动探针)
    • 适用场景:针对冷启动较慢的大型应用(如 Java Spring Boot 需要加载大量 Bean 耗时 40 秒)。
    • 核心价值:在 startupProbe 成功前,系统不会执行 livenessProbe。避免了慢启动应用在还没完全就绪时,就被急躁的存活探针误判为死锁而不断触发 Kill 重启。
  2. livenessProbe(存活探针)
    • 适用场景:检测死锁、死循环等进程处于运行中但已无法响应业务逻辑的状态。
    • ⚠️ 生产高危避坑绝对不要在 livenessProbe 中去请求下游数据库(MySQL)或外部缓存(Redis)! 一旦外部数据库出现短暂网络抖动,所有 Pod 的存活检测同时超时,导致全集群所有业务副本同时被杀崩溃,引发灾难性级联雪崩。
  3. readinessProbe(就绪探针)
    • 适用场景:判断容器是否准备好处理请求。例如:缓存预热完成、数据连接池已建立。
    • 触发动作:仅调整网络路由(从 Service 的 Endpoint 列表剔除),不会杀掉容器

4.3 动态交互仿真:Kubernetes Pod 三大探针生命周期时序

为了让读者直观理解三大探针在容器冷启动、服务就绪、业务死锁自愈过程中的严格时序联动,请操作下方内置仿真器:

🩺Kubernetes 三大探针 (Startup / Readiness / Liveness) 时序仿真器
1. StartupProbe (启动探针)
初始化防抖保护,未成功前禁用存活检查
未触发
2. ReadinessProbe (就绪探针)
决定 Pod 是否加入 Service Endpoints 转发池
未触发
3. LivenessProbe (存活探针)
持续周期探测,失败超阈值触发 Kubelet 容器杀毁重拉
未触发
当前 Pod 阶段: PendingService 流量状态: ○ 流量切断 (Isolated)重启计数 (RestartCount): 0
点击上方「模拟冷启动上线」观察 Kubelet 如何通过三探针精细控制容器生命周期...
💡 避坑黄金法则:对于 Java 等慢启动应用,切忌单靠设置超长 `initialDelaySeconds`,而应配置 `startupProbe: failureThreshold: 30, periodSeconds: 10`。在保证冷启动不被误杀的同时,又能实现就绪后秒级流量介入。

💡 探针仿真器实战操作指南

  1. 测试用例 1:模拟慢应用冷启动上线
    • 点击 「▶ 模拟冷启动上线」 按钮。
    • 观察阶段状态由 Pending 变为 Running。在初期阶段,StartupProbe 处于高优先级探测拦截保护中,此时 LivenessReadiness 探针处于屏蔽挂起状态。
    • 当启动初始化完成,StartupProbe 变成 Success,系统立即交接给 Readiness 探针。就绪检查通过后,Service 流量状态瞬间切入 「● 接收生产流量 (In Service)」
  2. 测试用例 2:模拟死锁故障注入与 kubelet 自动自愈
    • 在 Pod 正常服务状态下,点击 「⚡ 注入死锁故障 (触发自愈)」 按钮。
    • 观察 LivenessProbe 探针立刻检测到异常并报红失败。
    • 一旦存活探针连续失败达到 failureThreshold 阈值,kubelet 立即执行杀毁并拉起新容器,同时重启计数 RestartCount 自增,演示了 K8s 无人值守的终态自愈能力。

4.4 Pod 优雅停机与流量注销时序

在版本迭代时,强行切断正在执行的请求会导致用户端出现大量 HTTP 502/504 错误。K8s 的平滑下线机制如下:


5. Deployment 零宕机滚动更新实战

5.1 RollingUpdate 核心数学参数

Deployment 通过管理下层的 ReplicaSet 实现无损发布。控制滚动更新步长有两个核心参数:

yaml
strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 25%        # 允许超出期望副本数的最大上限 (向上取整)
    maxUnavailable: 0     # 允许处于不可用状态的最大副本数 (生产推荐设为 0,确保容量不降级)

假设我们有 replicas: 4,配置 maxSurge: 1maxUnavailable: 0

  1. 第 1 步:集群副本数允许最多为 4+1=5 个。K8s 创建 1 个新版本 Pod。此时旧 Pod 为 4,新 Pod 为 1。
  2. 第 2 步:新 Pod 启动并通过 readinessProbe 验证后,正式接收流量。
  3. 第 3 步:销毁 1 个旧 Pod,总数恢复为 4 个(3 旧 + 1 新)。
  4. 第 4 步:重复上述过程,直到所有 4 个副本全部平滑过渡为新版本。发布全程处理容量始终 100%

5.2 工业级生产 Deployment 黄金模版

yaml
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: 2

5.3 Kubernetes Pod 生产常见异常状态排障决策树

当面对生产报警、Pod 无法提供服务时,最忌讳盲目重启。以下决策树梳理了一线大厂面对常见 Pod 异常状态的标准化处置闭环:

高频生产 Pod 诊断排查指令速查表

诊断目标推荐执行命令核心关注点
查看调度与生命周期事件kubectl describe pod <pod-name> -n <ns>重点看底部的 Events 区域,关注 FailedSchedulingBackOffUnhealthy
查看容器崩溃前现场日志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. 本章小结

  1. 控制平面中枢:API Server 是唯一交互入口,etcd 依赖 Raft 确保强一致性,Scheduler 分过滤与打分二阶段完成精准投放,Controller Manager 是驱动状态自愈的协调引擎。
  2. Pod 原子模型:依托 Pause 容器建立共享的 Network 与 IPC 空间,实现高效进程级协同。
  3. 探针防线startupProbe 阻挡启动冷杀,livenessProbe 防范僵死,readinessProbe 精准截流。
  4. 零宕机发布:结合 maxUnavailable: 0preStop 延迟停机与 readinessProbe,构建无感知无断流的平滑滚动更新。

在下一章中,我们将进入集群内的网络深水区,探讨跨节点容器互联、Service 四层负载与 Ingress 七层路由:03. 服务发现与 Ingress 路由 (含仿真)

学思并济 · 躬行求索 | Released under MIT License