3. 声明式配置与期望状态:K8s 声明式 API 原理、期望状态 vs 实际状态、控制器循环

在 Kubernetes 发布流水线中,声明式配置是自动化运维的基石。与传统的“命令式”操作不同,声明式模型要求用户只描述“系统最终应该是什么样子”,而将“如何达到这个状态”的复杂逻辑交给平台自身完成。本章将深入剖析 K8s 声明式 API 的核心原理、期望状态与实际状态的差异,以及控制器循环的工作机制。

3.1 声明式 API 原理

Kubernetes 的 API 设计遵循声明式范式。用户通过 YAML 或 JSON 文件定义资源的期望状态(Desired State),并将其提交到 API Server。系统内部通过一系列控制器持续协调,确保集群的实际状态与期望状态保持一致。

核心特征: 用户只关心“做什么”(What),不关心“怎么做”(How)。系统自动处理差异检测与修复。

3.1.1 声明式 vs 命令式

维度 声明式(Declarative) 命令式(Imperative)
操作方式 提交最终状态文件(YAML) 执行具体指令(kubectl run/scale)
幂等性 天然幂等,重复执行结果一致 非幂等,需人工跟踪状态
漂移检测 自动对比期望与实际,持续修复 无自动检测,依赖人工审计
回滚能力 通过版本化配置快速恢复 需手动逆向操作,易出错
适用场景 CI/CD 流水线、生产环境 临时调试、快速验证

3.1.2 声明式 API 的工作流程

  1. 用户定义期望状态:编写 Deployment、Service 等资源的 YAML 清单。
  2. 提交到 API Server:通过 kubectl apply 或 GitOps 工具推送。
  3. 存储到 etcd:API Server 将期望状态持久化到 etcd 集群。
  4. 控制器检测差异:对应的控制器(如 Deployment Controller)通过 List-Watch 机制获取期望状态。
  5. 执行协调循环:控制器对比实际状态,执行创建、更新或删除操作。
  6. 反馈状态:控制器将实际状态写回资源对象的 status 字段。
最佳实践: 在 CI/CD 流水线中,始终使用 kubectl apply 而非 kubectl create 或 kubectl replace,以利用声明式配置的自动合并与漂移修复能力。

3.2 期望状态 vs 实际状态

Kubernetes 资源对象通过两个核心字段来管理状态:

  • spec(期望状态):用户定义的理想配置,由 API Server 持久化存储。
  • status(实际状态):由控制器实时更新的当前集群状态。

两者之间的差距驱动着控制器的协调动作。以下是一个 Deployment 的典型状态对比:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
---
status:
  availableReplicas: 2       # 实际可用 Pod 数
  readyReplicas: 2           # 就绪 Pod 数
  replicas: 3                # 当前总 Pod 数
  updatedReplicas: 1         # 已更新到新版本的 Pod 数
  conditions:
  - type: Available
    status: "False"
    reason: MinimumReplicasUnavailable
    message: "Deployment does not have minimum availability."
注意: 当 status 与 spec 不一致时,控制器会立即启动修复。例如上例中 availableReplicas: 2 小于 spec.replicas: 3,控制器会尝试创建或恢复 Pod。

3.3 控制器循环(Reconciliation Loop)

控制器循环是 Kubernetes 实现声明式自愈的核心机制。每个控制器(如 Deployment Controller、ReplicaSet Controller)都运行着一个无限循环,持续执行以下步骤:

  1. Watch:监听 API Server 上资源对象的变化事件(Add/Update/Delete)。
  2. Read:读取当前资源的 spec(期望状态)和 status(实际状态)。
  3. Diff:对比期望状态与实际状态,计算差异列表。
  4. Act:执行必要的操作(创建 Pod、更新 Service、删除旧资源等)。
  5. Update Status:将协调后的实际状态写回 status 字段。
  6. Re-queue:将资源重新加入工作队列,等待下一次循环。
关键特性: 控制器循环是事件驱动 + 定时同步的混合模型。除了响应事件,控制器还会定期(默认 10 小时)重新同步所有资源,确保即使事件丢失也能最终一致。

3.3.1 控制器循环流程图

K8s 控制器循环(Reconciliation Loop) 用户提交期望状态 etcd 持久化存储 控制器 Watch 事件 对比期望状态 vs 实际状态 状态一致,无需操作 执行修复操作 重新入队(Re-queue)

3.4 配置漂移与控制器修复

配置漂移是指集群的实际状态因外部因素(如手动修改、节点故障、资源抢占)偏离了期望状态。控制器循环通过持续对比自动检测并修复漂移。

3.4.1 常见漂移场景

漂移类型 触发原因 控制器修复行为
Pod 数量漂移 手动删除 Pod、节点资源不足导致驱逐 ReplicaSet 控制器重新创建 Pod
镜像版本漂移 手动修改 Pod 镜像标签 Deployment 控制器回滚到 spec 定义的版本
配置漂移 手动修改 ConfigMap 或 Secret Pod 需重建才能生效(需手动触发滚动更新)
网络策略漂移 手动修改 NetworkPolicy 规则 NetworkPolicy 控制器立即同步规则
流水线建议: 在 CI/CD 流水线中,每次部署后应执行 kubectl diff 或使用 kubectl apply --server-side 强制同步期望状态,避免手动操作导致的漂移累积。

3.5 声明式配置在流水线中的价值

在 K8s 发布流水线中,声明式配置提供了以下关键能力:

  • 版本化配置:所有 YAML 文件存储在 Git 仓库中,支持审计、回滚和协作。
  • 自动漂移修复:控制器持续运行,确保集群始终与 Git 中的期望状态一致。
  • 幂等部署:重复执行 kubectl apply 不会产生副作用,适合自动化流水线。
  • 渐进式交付:结合 Deployment 的滚动更新策略,实现零停机发布。
核心结论: 声明式配置 + 控制器循环 = K8s 自愈能力的基石。在流水线中,我们只需维护 Git 仓库中的期望状态,K8s 会自动处理所有差异修复与状态收敛。

3.6 本章小结

  • K8s 声明式 API 要求用户只定义期望状态,系统自动协调实际状态。
  • 期望状态存储在 spec 字段,实际状态由控制器更新到 status 字段。
  • 控制器循环通过 Watch → Read → Diff → Act → Update Status → Re-queue 的闭环实现持续协调。
  • 配置漂移是常态,控制器循环是自动修复的核心保障。
  • 在 CI/CD 流水线中,声明式配置提供了版本化、幂等性和自愈能力,是自动化发布的基础。