K8s-Deployment滚动更新流程
Deployment 滚动更新流程
本文档描述 Kubernetes Deployment 如何通过 ReplicaSet Controller 管理滚动更新的完整流程。
概述
Deployment 滚动更新涉及以下核心组件:
- Deployment Controller:管理 Deployment 生命周期
- ReplicaSet Controller:管理 Pod 副本数
- API Server:存储和分发资源状态
flowchart TD
subgraph User["用户操作"]
A["kubectl apply -f deployment.yaml"]
end
subgraph APIServer["API Server"]
B["Deployment 资源"]
C["ReplicaSet 资源"]
D["Pod 资源"]
end
subgraph DeploymentController["Deployment Controller"]
E["Watch Deployment"]
F["创建/更新 ReplicaSet"]
G["计算期望副本数"]
end
subgraph ReplicaSetController["ReplicaSet Controller"]
H["Watch ReplicaSet"]
I["创建/删除 Pod"]
J["维护期望副本数"]
end
A --> B
B -->|触发| E
E --> F
F --> C
C -->|触发| H
H --> I
I --> D
G -->|控制| F
J -->|控制| I
style A fill:#e1f5fe
style E fill:#c8e6c9
style H fill:#fff9c4
流程详解
1. Deployment Controller 架构
代码路径: pkg/controller/deployment/deployment_controller.go
1 | type DeploymentController struct { |
2. 滚动更新触发流程
sequenceDiagram
participant User as 用户
participant API as API Server
participant DC as Deployment Controller
participant RC as ReplicaSet Controller
participant Pod as Pod
User->>API: 更新 Deployment (修改镜像版本)
API->>DC: Watch 事件触发
DC->>DC: syncDeployment()
Note over DC: 获取所有关联的 ReplicaSet
DC->>API: List ReplicaSets by label selector
Note over DC: 计算新旧 ReplicaSet 副本数
DC->>DC: getAllReplicaSetsAndSyncRevision()
alt 滚动更新策略
DC->>API: 创建新 ReplicaSet (replicas=0)
DC->>API: 逐步调整新旧 RS 副本数
else 重建策略
DC->>API: 删除旧 ReplicaSet
DC->>API: 创建新 ReplicaSet
end
API->>RC: ReplicaSet 变更事件
RC->>Pod: 创建/删除 Pod
Pod->>API: 更新 Pod 状态
API->>DC: 状态变更事件
DC->>API: 更新 Deployment Status
3. syncDeployment 核心逻辑
代码路径: pkg/controller/deployment/deployment_controller.go:585
1 | func (dc *DeploymentController) syncDeployment(ctx context.Context, key string) error { |
4. 滚动更新策略
4.1 RollingUpdate 策略
1 | spec: |
计算逻辑:
1 | 期望副本数: desiredReplicas = deployment.spec.replicas |
代码路径: pkg/controller/deployment/rolling.go
1 | func (dc *DeploymentController) rolloutRolling(ctx context.Context, deployment *apps.Deployment, rsList []*apps.ReplicaSet) error { |
4.2 Recreate 策略
1 | spec: |
Recreate 策略会先删除所有旧 Pod,再创建新 Pod:
flowchart LR
A["旧 RS (3副本)"] -->|删除所有 Pod| B["旧 RS (0副本)"]
B -->|创建新 RS| C["新 RS (3副本)"]
5. ReplicaSet Controller 角色
代码路径: pkg/controller/replicaset/replica_set.go
1 | type ReplicaSetController struct { |
核心同步逻辑:
1 | func (rsc *ReplicaSetController) syncReplicaSet(ctx context.Context, key string) error { |
6. 滚动更新状态追踪
代码路径: pkg/controller/deployment/sync.go:476
1 | func (dc *DeploymentController) syncDeploymentStatus(ctx context.Context, allRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet, d *apps.Deployment) error { |
关键代码锚点
| 功能 | 文件路径 |
|---|---|
| Deployment Controller 结构 | pkg/controller/deployment/deployment_controller.go:66 |
| syncDeployment 入口 | pkg/controller/deployment/deployment_controller.go:585 |
| RollingUpdate 逻辑 | pkg/controller/deployment/rolling.go |
| Recreate 逻辑 | pkg/controller/deployment/recreate.go |
| 状态计算 | pkg/controller/deployment/sync.go:476 |
| ReplicaSet Controller | pkg/controller/replicaset/replica_set.go:81 |
滚动更新示例
假设 Deployment 期望 10 副本,maxSurge=25%,maxUnavailable=25%:
1 | 初始状态: |
回滚机制
1 | # 查看历史版本 |
回滚通过保留旧 ReplicaSet 的 revision annotation 实现:
1 | metadata: |
高频面试题
Q1: Deployment 滚动更新的流程是怎样的?
参考答案:
- 用户更新 Deployment(如修改镜像版本)
- Deployment Controller 监听到变化,执行
syncDeployment() - 获取所有关联的 ReplicaSet,计算新旧 RS
- 创建新 ReplicaSet(如果不存在)
- 按照 RollingUpdate 策略逐步调整副本数:
- 扩容新 RS(受 maxSurge 限制)
- 缩容旧 RS(受 maxUnavailable 限制)
- ReplicaSet Controller 监听 RS 变化,创建/删除 Pod
- 更新 Deployment Status,直到所有副本更新完成
Q2: maxSurge 和 maxUnavailable 是如何工作的?
参考答案:
1 | spec: |
假设 replicas=10:
maxSurge=25%→ 最多 10+3=13 个 Pod 同时运行maxUnavailable=25%→ 最少保持 10-3=7 个可用 Pod
计算逻辑:
1 | maxAvailable = ceil(desiredReplicas * (1 - maxUnavailable)) |
示例(10副本,25%/25%):
1 | 初始: 旧RS=10 |
Q3: RollingUpdate 和 Recreate 策略有什么区别?
参考答案:
| 特性 | RollingUpdate | Recreate |
|---|---|---|
| 服务中断 | 无(渐进式替换) | 有(先删后建) |
| 资源占用 | 可能超出期望副本数 | 不会超出 |
| 更新速度 | 较慢 | 较快 |
| 回滚能力 | 保留历史 RS | 保留历史 RS |
| 适用场景 | 生产环境、需要高可用 | 开发环境、单副本应用 |
Recreate 流程:
- 缩容所有旧 RS 到 0
- 等待所有旧 Pod 终止
- 创建新 RS 并扩容到目标副本数
Q4: Deployment 如何实现回滚?
参考答案:
1 | # 查看历史版本 |
原理:
- 每个 ReplicaSet 都有
deployment.kubernetes.io/revisionannotation - 回滚时,Deployment Controller 找到目标 revision 的 RS
- 将该 RS 的 PodTemplate 复制到 Deployment
- 触发正常的滚动更新流程
保留历史版本数量:
1 | spec: |
Q5: ReplicaSet Controller 是如何工作的?
参考答案:
- Watch ReplicaSet 和 Pod 变化
- 计算期望差值:
diff = 当前Pod数 - 期望副本数 - 创建 Pod(diff < 0):
- 使用
slowStartBatch批量创建,避免一次创建过多 - 受
burstReplicas限制(默认 500)
- 使用
- 删除 Pod(diff > 0):
- 优先删除不健康的 Pod(Pending、Unknown、NotReady)
- 按优先级排序后删除
- Expectations 机制:
- 记录期望创建/删除的 Pod
- 只有
SatisfiedExpectations()返回 true 才执行同步 - 避免在 Pod 创建/删除过程中重复操作
Q6: 如何排查 Deployment 更新卡住的问题?
参考答案:
1 | # 1. 查看 Deployment 状态 |
延伸阅读
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Joohwan!
评论

