2. K8s 发布基础回顾:Deployment、StatefulSet、DaemonSet、Job/CronJob 的核心发布机制
在构建自动化回滚与配置漂移修复流水线之前,必须深入理解 Kubernetes 中各类工作负载(Workload)的发布机制。不同控制器(Controller)对 Pod 的更新策略、滚动方式、回滚能力存在本质差异,直接决定了流水线的设计边界。
2.1 核心工作负载概览
Kubernetes 提供四种主要的内建工作负载 API,分别对应无状态服务、有状态服务、节点代理、以及批处理任务。下表从发布视角对比其核心差异:
| 工作负载类型 | Pod 标识 | 更新策略 | 回滚支持 | 存储关联 | 典型场景 |
|---|---|---|---|---|---|
| Deployment | 随机名称(无状态) | RollingUpdate / Recreate | 原生支持(Revision 历史) | 通常不绑定或使用 ReadWriteMany | Web 服务、API 网关、微服务 |
| StatefulSet | 有序且稳定(如 web-0) | RollingUpdate / OnDelete / 分区更新 | 原生支持(Revision 历史) | 每个 Pod 绑定独立 PVC | 数据库、消息队列、ZooKeeper |
| DaemonSet | 每个 Node 一个 Pod | RollingUpdate / OnDelete | 原生支持(Revision 历史) | 通常使用 hostPath 或 emptyDir | 日志采集、监控 Agent、CNI 插件 |
| Job / CronJob | 随机名称(一次性) | 无滚动更新(重新创建) | 不支持回滚(可重跑) | 通常不绑定 | 数据迁移、批处理、定时任务 |
2.2 Deployment:无状态服务的滚动发布与回滚
Deployment 是生产环境中使用最频繁的工作负载。其核心发布机制围绕 ReplicaSet 的版本管理展开。
2.2.1 发布流程
- 用户修改 Deployment 的 Pod template(如镜像版本)。
- Deployment Controller 创建一个新的 ReplicaSet,并设置期望副本数。
- 新 ReplicaSet 开始启动新版本 Pod;旧 ReplicaSet 的 Pod 按
maxSurge和maxUnavailable参数逐步缩容。 - 当新 ReplicaSet 的所有 Pod 达到 Ready 状态后,旧 ReplicaSet 缩容至 0。
- 每次 template 变更都会生成一个新的 Revision,存储在
.metadata.annotations中。
2.2.2 回滚机制
Deployment 通过 kubectl rollout undo 命令或 API 触发回滚。回滚本质上是将当前 ReplicaSet 的 Pod template 替换为指定 Revision 的 template,然后重新触发一次滚动更新。
# 查看发布历史
kubectl rollout history deployment/nginx-deploy
# 回滚到上一个版本
kubectl rollout undo deployment/nginx-deploy
# 回滚到指定版本
kubectl rollout undo deployment/nginx-deploy --to-revision=3
replicas 或 resources 等非 template 字段,这些修改不会被回滚覆盖,导致配置漂移。流水线应强制使用 kubectl apply --server-side 并配合字段管理(Field Management)来避免此问题。
2.3 StatefulSet:有状态服务的有序发布与回滚
StatefulSet 为每个 Pod 提供稳定的网络标识和持久化存储。其发布机制必须保证有序性和数据安全。
2.3.1 有序更新策略
- RollingUpdate(默认): 从序号最大的 Pod 开始,逐个更新。每个 Pod 更新完成后,必须进入 Ready 状态,才会更新下一个。
- 分区更新(Partition): 通过
.spec.updateStrategy.rollingUpdate.partition控制。序号大于等于 partition 的 Pod 会被更新,小于 partition 的 Pod 保持不变。常用于金丝雀发布或灰度升级。 - OnDelete: 不自动更新,需要手动删除 Pod 才会触发重建。
2.3.2 回滚注意事项
StatefulSet 的回滚同样基于 Revision 历史。但由于每个 Pod 绑定独立的 PVC,回滚时需要注意:
- 回滚不会自动删除或重建 PVC。如果新版本修改了数据格式,回滚到旧版本可能导致数据不兼容。
- 回滚时 Pod 的更新顺序与发布时相反:从序号最大的 Pod 开始逐个回滚。
# 分区更新示例:只更新序号 >= 2 的 Pod
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":2}}}}'
READINESS_PROBE 来检测数据版本,避免回滚后启动失败。
2.4 DaemonSet:节点代理的平滑更新
DaemonSet 确保每个 Node 上运行一个 Pod 副本。其发布机制需要兼顾节点级别的滚动,避免影响集群整体稳定性。
2.4.1 更新策略
- RollingUpdate(默认): 通过
maxSurge和maxUnavailable控制。DaemonSet 的滚动更新是逐节点进行的,一个节点上的旧 Pod 被删除后,新 Pod 在该节点上启动并 Ready,才会继续下一个节点。 - OnDelete: 需要手动删除每个节点上的 Pod 来触发更新。
2.4.2 回滚特性
DaemonSet 的回滚与 Deployment 类似,支持 kubectl rollout undo。回滚时,DaemonSet Controller 会按照当前节点的顺序,逐个将 Pod 替换为旧版本 template。
# 查看 DaemonSet 更新状态
kubectl rollout status daemonset/fluentd-elasticsearch
# 回滚 DaemonSet
kubectl rollout undo daemonset/fluentd-elasticsearch
2.5 Job / CronJob:批处理与定时任务
Job 和 CronJob 的设计目标是一次性执行或按计划执行,不提供滚动更新和回滚机制。
2.5.1 Job 的发布行为
- 修改 Job 的 template 后,无法直接更新正在运行的 Job。必须删除旧 Job 并重新创建。
- Job 的
completions和parallelism参数控制并发执行数量。 - Job 完成后,Pod 默认保留一段时间(
ttlSecondsAfterFinished)用于日志查看。
2.5.2 CronJob 的发布行为
- CronJob 每次调度时,根据当前 template 创建一个新的 Job 对象。
- 修改 CronJob 的 template 后,下一次调度将使用新配置。正在运行的 Job 不受影响。
- CronJob 支持
startingDeadlineSeconds和concurrencyPolicy(Allow/Forbid/Replace)来控制调度行为。
kubectl delete job 步骤来清理旧任务,避免资源堆积。
2.6 核心发布机制对比图
下图从 Pod 标识、更新顺序、回滚粒度三个维度,对比四种工作负载的发布机制差异:
2.7 发布机制对回滚流水线的影响
基于上述分析,在设计自动化回滚流水线时,必须针对不同工作负载采取差异化策略:
| 工作负载 | 回滚触发方式 | 回滚前检查项 | 回滚后验证 | 配置漂移防护 |
|---|---|---|---|---|
| Deployment | kubectl rollout undo |
检查旧 Revision 的 template 是否完整 | Pod Ready + 健康检查 | 禁止手动 edit,强制 GitOps |
| StatefulSet | kubectl rollout undo |
数据格式兼容性 + PVC 状态 | 有序 Ready + 数据校验 | 禁止修改 PVC 模板 |
| DaemonSet | kubectl rollout undo |
节点数量 + 资源预留 | 所有节点 Ready | 禁止修改 nodeSelector |
| Job/CronJob | 删除旧 Job + 重新创建 | 幂等性校验 + 清理残留 | Job 成功完成 | 禁止修改 concurrencyPolicy |
kubectl rollout status 来等待更新完成,并设置超时时间(如 5 分钟)。对于 StatefulSet 和 DaemonSet,建议在回滚前执行 kubectl rollout pause 来暂停自动更新,避免回滚过程中被其他控制器干扰。