在K8S中,Deployment 升级过程有哪些?
在 Kubernetes 中,Deployment 的升级过程(尤其是默认的 RollingUpdate
策略)是一个高度自动化且可控的过程,由 Deployment 控制器驱动,旨在实现应用版本的无缝切换。以下是详细的核心步骤和底层机制:
核心升级流程(以 RollingUpdate
策略为例)
假设您修改了 Deployment 的 Pod 模板(如更新容器镜像 .spec.template.spec.containers[].image
),触发升级。
1. 触发升级
- 用户操作:通过
kubectl apply -f deployment.yaml
或kubectl set image deployment/my-app my-container=nginx:1.25
更新 Deployment 配置。 - API Server 响应:检测到 Pod 模板(
.spec.template
)变更,Deployment 控制器开始协调状态。
2. 创建新 ReplicaSet (RS)
- 生成新 RS:控制器创建一个新的 ReplicaSet(名称包含唯一哈希值,如
my-app-5d89ddf574
),其 Pod 模板基于更新后的配置。 - 初始副本数:新 RS 的初始副本数设为 0。
3. 逐步扩容新 Pod(新版本)
- 按策略扩容:根据
RollingUpdate
参数(maxSurge
、maxUnavailable
):maxSurge
:允许超过期望副本数(spec.replicas
)的 Pod 数量(例如25%
或绝对值)。maxUnavailable
:允许不可用 Pod 的最大比例(例如0
或10%
)。
- 分批次创建:
- 控制器逐步增加新 RS 的副本数(例如每次 +1),创建新版本的 Pod。
- 新 Pod 经过调度 → 拉取镜像 → 启动容器 → 等待就绪探针(
readinessProbe
)通过。
4. 逐步缩容旧 Pod(旧版本)
- 滚动替换:每有一个新 Pod 达到
Ready
状态,控制器就将旧 RS 的副本数减少 1,终止一个旧 Pod。 - 优雅终止:旧 Pod 收到
SIGTERM
信号 → 执行preStop
钩子(如有)→ 等待优雅终止期(terminationGracePeriodSeconds
,默认 30 秒)→ 强制终止(SIGKILL
)。
5. 持续循环直至完成
- 循环条件:重复步骤 3 和 4,直到:
- 新 RS 的副本数达到
spec.replicas
。 - 旧 RS 的副本数降为 0。
- 新 RS 的副本数达到
- 最终状态:所有旧 Pod 被替换为新 Pod,旧 RS 保留(便于回滚)。
关键控制点与底层机制
1. 滚动更新的精细控制
参数 | 作用 | 示例值 | 生产建议 |
---|---|---|---|
maxSurge |
允许超过期望副本数的 Pod 数量(加速更新) | 1 、"25%" |
建议 10-25% (平衡速度与资源) |
maxUnavailable |
允许不可用 Pod 的最大数量(保证服务可用性) | 0 、"10%" |
关键服务建议 0 (零宕机) |
✅ 示例:若
replicas: 10
、maxSurge: 2
、maxUnavailable: 1
:
- 最大总 Pod 数:
10 + 2 = 12
- 最小可用 Pod 数:
10 - 1 = 9
2. 就绪探针(readinessProbe
)的核心作用
- 流量切换前提:新 Pod 必须通过
readinessProbe
才被加入 Service 的 Endpoints,接收流量。 - 避免半启动状态:若探针失败,新 Pod 不会被标记就绪,控制器暂停升级(旧 Pod 继续服务)。
3. 健康检查与自动修复
- 失败处理:若新 Pod 持续启动失败(如 CrashLoopBackOff),滚动更新自动暂停。
- 人工介入:需检查日志(
kubectl logs <pod>
)或事件(kubectl describe pod <pod>
)定位问题。
升级过程可视化
sequenceDiagram
participant User as 用户
participant K8s as Kubernetes API
participant Ctrl as Deployment 控制器
participant NewRS as 新 ReplicaSet
participant OldRS as 旧 ReplicaSet
User->>K8s: 更新 Deployment 镜像
K8s->>Ctrl: 检测到 Pod 模板变更
Ctrl->>NewRS: 创建新 ReplicaSet (副本数=0)
loop 滚动更新循环
Ctrl->>NewRS: 扩容 +1 副本
NewRS->>NewRS: 创建新 Pod
Note over NewRS: 等待新 Pod 通过 readinessProbe
Ctrl->>OldRS: 缩容 -1 副本
OldRS->>OldRS: 终止旧 Pod(优雅退出)
end
Ctrl->>OldRS: 设置副本数=0
Ctrl->>K8s: 更新状态(升级完成)
回滚机制(快速恢复)
- 查看历史版本:
kubectl rollout history deployment/my-app
- 回滚到上一版本:
kubectl rollout undo deployment/my-app
- 指定历史版本回滚:
kubectl rollout undo deployment/my-app --to-revision=2
- 底层操作:Deployment 控制器将旧 RS 的副本数恢复,并缩容新 RS(逆向滚动更新)。
两种策略对比总结
策略 | 过程 | 可用性 | 适用场景 |
---|---|---|---|
RollingUpdate |
新/旧 Pod 逐步交替(分批替换) | ✅ 高可用 | 生产环境(Web/API 服务等) |
Recreate |
先删光旧 Pod → 再创建新 Pod | ❌ 服务中断 | 开发测试、非关键任务、独占式更新 |
最佳实践
- 始终配置就绪探针:确保流量只转发到完全就绪的 Pod。
- 设置保守的
maxUnavailable
:生产环境建议maxUnavailable: 0
(零宕机升级)。 - 预发验证:在非生产环境测试新版本,避免配置错误导致级联故障。
- 监控升级状态:
kubectl rollout status deployment/my-app # 实时查看进度
- 利用金丝雀发布:结合 Service Mesh 或 Ingress 控制器,实现更精细的流量灰度。
通过理解这些流程和控制点,您将能安全高效地管理 Kubernetes 中的应用生命周期。