二十、Kubernetes基础-82-Deployment完全指南
Kubernetes Deployment 完全指南:从原理到实战
技术标签: Kubernetes | Deployment | 滚动更新 | 回滚 | 云原生 | 应用部署
难度级别: 进阶
阅读时间: 30分钟
适用人群: DevOps工程师、云原生架构师、Kubernetes用户
📖 文章导读
Deployment 是 Kubernetes 中最常用的工作负载控制器,它封装了 ReplicaSet 并提供声明式更新、回滚、扩缩容等高级功能。本文将从底层原理到生产实践,全面解析 Deployment 的核心机制。
你将学到什么?
- ✅ Deployment 的架构设计与工作原理
- ✅ 滚动更新策略详解(RollingUpdate vs Recreate)
- ✅ 版本管理与回滚机制
- ✅ 生产环境最佳实践
- ✅ 常见问题排查指南
一、Deployment 的定位与演进
1.1 为什么需要 Deployment?
在 Kubernetes 早期,用户直接使用 ReplicaSet 管理 Pod,但面临以下痛点:
痛点1:更新需要手动操作
旧版本:kubectl delete rs old && kubectl create rs new
痛点2:无法保证更新过程的安全性
如果新版本有问题,旧版本已经被删除
痛点3:缺少版本历史和回滚能力
更新后发现问题,不知道之前是什么配置
Deployment 的解决方案:
# 声明式:只需更新期望状态
kubectl set image deployment/myapp nginx=nginx:1.22
# Kubernetes 自动完成:
# 1. 创建新 ReplicaSet
# 2. 逐步扩容新 RS,缩容旧 RS
# 3. 记录版本历史
# 4. 支持一键回滚
1.2 Deployment 与 ReplicaSet 的关系
核心关系:
- Deployment:声明式管理层,负责更新策略、版本管理
- ReplicaSet:执行层,负责维持指定数量的 Pod 副本
- Pod:实际运行的容器实例
二、Deployment 核心架构深度解析
2.1 Deployment Controller 工作流程
// 简化的 DeploymentController Reconcile 逻辑
func (dc *DeploymentController) Reconcile(key string) error {
// 1. 获取 Deployment 对象
deployment := getDeployment(key)
// 2. 查找所有关联的 ReplicaSet
rsList := getReplicaSets(deployment)
// 3. 获取最新的 ReplicaSet
newRS := getNewReplicaSet(deployment, rsList)
// 4. 执行滚动更新
if isRollingUpdate(deployment) {
dc.rollingUpdate(deployment, newRS, rsList)
}
// 5. 清理过旧的 ReplicaSet(保留历史版本)
dc.cleanupDeployment(deployment, rsList)
// 6. 更新 Deployment 状态
updateDeploymentStatus(deployment)
return nil
}
2.2 滚动更新算法详解
算法核心:渐进式替换
初始状态:
RS-v1 (3 replicas): [Pod-1, Pod-2, Pod-3]
第1轮迭代:
RS-v1 (2 replicas): [Pod-1, Pod-2]
RS-v2 (1 replica): [Pod-4]
第2轮迭代:
RS-v1 (1 replica): [Pod-1]
RS-v2 (2 replicas): [Pod-4, Pod-5]
第3轮迭代:
RS-v1 (0 replicas): []
RS-v2 (3 replicas): [Pod-4, Pod-5, Pod-6]
关键参数控制
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 最多超出期望副本数1个
maxUnavailable: 0 # 最多允许0个不可用(保证零宕机)
参数计算示例:
期望副本数:3
maxSurge: 1
maxUnavailable: 0
第1轮:
允许最大Pod数 = 3 + 1 = 4
允许最小可用Pod数 = 3 - 0 = 3
所以:缩容1个旧Pod → 扩容1个新Pod
第2轮:
当前:旧2个,新1个(总共3个)
允许最大Pod数 = 4
允许最小可用Pod数 = 3
所以:再缩容1个旧Pod → 扩容1个新Pod
2.3 状态机设计
Deployment 通过 Conditions 维护状态:
type DeploymentCondition struct {
Type DeploymentConditionType `json:"type"`
Status ConditionStatus `json:"status"`
LastUpdateTime metav1.Time `json:"lastUpdateTime"`
LastTransitionTime metav1.Time `json:"lastTransitionTime"`
Reason string `json:"reason"`
Message string `json:"message"`
}
type DeploymentConditionType string
const (
DeploymentAvailable DeploymentConditionType = "Available"
DeploymentProgressing DeploymentConditionType = "Progressing"
DeploymentReplicaFailure DeploymentConditionType = "ReplicaFailure"
)
典型状态流转:
Progressing=True, Available=False → 正在部署
Progressing=True, Available=True → 部署成功
Progressing=False, Available=True → 部署完成
Progressing=False, Available=False → 部署失败
三、滚动更新策略深度对比
3.1 RollingUpdate(滚动更新)
策略详解
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2 # 20% 超出
maxUnavailable: 1 # 10% 不可用
template:
spec:
containers:
- name: app
image: myapp:v2.0
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
更新过程可视化
时间线:
T0: [v1,v1,v1,v1,v1,v1,v1,v1,v1,v1] ← 初始状态(10个v1)
T1: [v1,v1,v1,v1,v1,v1,v1,v1,v1,v2] ← 添加1个v2(maxUnavailable=1)
T2: [v1,v1,v1,v1,v1,v1,v1,v1,v2,v2] ← 再添加1个v2
T3: [v1,v1,v1,v1,v1,v1,v1,v2,v2,v2] ← 同时移除1个v1(maxSurge=2)
T4: [v1,v1,v1,v1,v1,v1,v2,v2,v2,v2]
T5: [v1,v1,v1,v1,v1,v2,v2,v2,v2,v2]
T6: [v1,v1,v1,v1,v2,v2,v2,v2,v2,v2]
T7: [v1,v1,v1,v2,v2,v2,v2,v2,v2,v2]
T8: [v1,v1,v2,v2,v2,v2,v2,v2,v2,v2]
T9: [v1,v2,v2,v2,v2,v2,v2,v2,v2,v2]
T10:[v2,v2,v2,v2,v2,v2,v2,v2,v2,v2] ← 更新完成
关键依赖:ReadinessProbe 确保新 Pod 就绪后才继续更新
适用场景
✅ 适合:
- Web 服务(需要持续可用)
- API 服务(零宕机要求)
- 微服务(支持灰度发布)
❌ 不适合:
- 需要同时切换所有实例的场景
- 新版本与旧版本不兼容的情况
3.2 Recreate(重建更新)
策略详解
apiVersion: apps/v1
kind: Deployment
metadata:
name: batch-processor
spec:
replicas: 3
strategy:
type: Recreate # 先删除所有旧Pod,再创建新Pod
template:
spec:
containers:
- name: processor
image: myapp:v2.0
更新过程
T0: [v1,v1,v1]
T1: [] ← 全部删除(服务中断!)
T2: [v2,v2,v2] ← 全部创建
适用场景
✅ 适合:
- 数据库迁移(需要所有实例同时更新)
- 批处理任务(可以接受短暂中断)
- 版本不兼容的更新
❌ 不适合:
- 需要高可用的服务
- 用户面向的 Web 应用
3.3 策略对比矩阵
| 特性 | RollingUpdate | Recreate |
|---|---|---|
| 服务可用性 | ✅ 持续可用 | ❌ 更新期间中断 |
| 资源占用 | ️ 短暂超出(maxSurge) | ✅ 不会超出 |
| 更新速度 | ⚠️ 较慢(逐步替换) | ✅ 较快 |
| 兼容性要求 | ✅ 新旧版本需兼容 | ❌ 可以不兼容 |
| 典型场景 | Web服务、微服务 | 数据库、批处理 |
四、版本管理与回滚机制
4.1 Revision History
Deployment 通过 revisionHistoryLimit 保留历史版本:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
revisionHistoryLimit: 10 # 保留最近10个版本(默认10)
template:
spec:
containers:
- name: app
image: myapp:v1.0
版本存储机制:
Deployment/myapp
├── ReplicaSet/myapp-7d9b8c6f5 (revision=1, image=v1.0)
├── ReplicaSet/myapp-8e0c9d7g6 (revision=2, image=v1.1)
├── ReplicaSet/myapp-9f1d0e8h7 (revision=3, image=v1.2) ← 当前版本
└── ReplicaSet/myapp-0g2e1f9i8 (revision=4, image=v1.3) ← 最新版本
↑
如果 revisionHistoryLimit=3,则 revision=1 的 RS 会被清理
4.2 回滚操作详解
查看历史版本
# 查看更新历史
$ kubectl rollout history deployment/myapp
deployment.apps/myapp
REVISION CHANGE-CAUSE
1 kubectl apply --filename=deployment-v1.yaml
2 kubectl set image deployment/myapp myapp=myapp:v1.1
3 kubectl set image deployment/myapp myapp=myapp:v1.2
# 查看特定版本详情
$ kubectl rollout history deployment/myapp --revision=2
deployment.apps/myapp with revision #2
Pod Template:
Labels: app=myapp
pod-template-hash=8e0c9d7g6
Containers:
myapp:
Image: myapp:v1.1
Port: 80/TCP
执行回滚
# 回滚到上一个版本
$ kubectl rollout undo deployment/myapp
deployment.apps/myapp rolled back
# 回滚到指定版本
$ kubectl rollout undo deployment/myapp --to-revision=1
deployment.apps/myapp rolled back
# 暂停回滚(用于调试)
$ kubectl rollout pause deployment/myapp
# 恢复回滚
$ kubectl rollout resume deployment/myapp
回滚原理:
回滚到 revision=1:
1. 创建新的 ReplicaSet(revision=4),内容与 revision=1 相同
2. 将新 RS 的 replicas 设置为期望值
3. 逐步缩容当前 RS(revision=3)
4. 逐步扩容新 RS(revision=4)
5. 更新 Deployment 状态
注意:回滚本身也是一次"更新",会生成新的 revision!
4.3 自动回滚机制
配置进度超时
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
progressDeadlineSeconds: 600 # 10分钟内必须完成更新
minReadySeconds: 30 # Pod 就绪后等待30秒才认为更新成功
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
超时检测逻辑:
if (当前时间 - 更新开始时间) > progressDeadlineSeconds {
if (新RS的Ready副本数 < 期望副本数) {
// 标记更新失败
setCondition(DeploymentProgressing, False, "ProgressDeadlineExceeded")
// 自动回滚(如果配置了)
rollback()
}
}
监控与告警
# 查看更新状态
$ kubectl rollout status deployment/myapp
Waiting for deployment "myapp" rollout to finish: 2 out of 3 new replicas have been updated...
# 在 CI/CD 中使用
kubectl rollout status deployment/myapp --timeout=600s
if [ $? -ne 0 ]; then
echo "Deployment failed, rolling back..."
kubectl rollout undo deployment/myapp
exit 1
fi
五、生产环境最佳实践
5.1 零宕机发布配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: production-web
spec:
replicas: 5
minReadySeconds: 10 # 就绪后等待10秒,确保稳定
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 每次只增加1个Pod
maxUnavailable: 0 # 不允许任何Pod不可用(零宕机)
template:
metadata:
labels:
app: web
version: v2.0
spec:
# 优雅关闭配置
terminationGracePeriodSeconds: 30
containers:
- name: web
image: myapp:v2.0
ports:
- containerPort: 8080
# 就绪探针(决定是否可以接收流量)
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
successThreshold: 1
# 存活探针(决定是否需要重启)
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
failureThreshold: 3
# 优雅退出处理
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 5"] # 给5秒时间处理现有请求
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
5.2 蓝绿部署模式
虽然 Deployment 本身不支持蓝绿部署,但可以通过 Service 实现:
# 蓝色版本(当前生产)
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-blue
spec:
replicas: 3
selector:
matchLabels:
app: web
version: blue
template:
metadata:
labels:
app: web
version: blue
spec:
containers:
- name: web
image: myapp:v1.0
# 绿色版本(新版本)
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-green
spec:
replicas: 3
selector:
matchLabels:
app: web
version: green
template:
metadata:
labels:
app: web
version: green
spec:
containers:
- name: web
image: myapp:v2.0
# Service 指向蓝色版本
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
version: blue # 切换到 green 即完成蓝绿切换
ports:
- port: 80
targetPort: 8080
切换命令:
# 验证绿色版本健康
kubectl get pods -l app=web,version=green
# 切换流量到绿色版本
kubectl patch service web-service -p '{"spec":{"selector":{"version":"green"}}}'
# 验证切换
kubectl get svc web-service -o jsonpath='{.spec.selector}'
5.3 金丝雀发布(Canary)
# 主版本(90%流量)
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-canary
spec:
replicas: 9
selector:
matchLabels:
app: web
template:
spec:
containers:
- name: web
image: myapp:v1.0
# 金丝雀版本(10%流量)
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-canary
spec:
replicas: 1
selector:
matchLabels:
app: web
canary: "true"
template:
spec:
containers:
- name: web
image: myapp:v2.0
流量切分:通过 Service 的 label selector 权重分配(需要 Istio 或 Nginx Ingress 支持)
六、常见问题排查指南
6.1 更新卡住不动
现象
$ kubectl rollout status deployment/myapp
Waiting for deployment "myapp" rollout to finish: 1 old replicas are pending termination...
排查步骤
# 1. 检查 Pod 状态
kubectl get pods -l app=myapp
kubectl describe pod <pod-name>
# 2. 检查是否有 Pod 卡在 Terminating
kubectl get pods | grep Terminating
# 3. 查看 Pod 事件
kubectl describe pod <pod-name> | grep -A 10 Events
# 4. 检查 Finalizer
kubectl get pod <pod-name> -o jsonpath='{.metadata.finalizers}'
# 5. 强制删除(慎用)
kubectl delete pod <pod-name> --grace-period=0 --force
常见原因:
- 容器进程未响应 SIGTERM 信号
- Volume 卸载失败(如 NFS 网络问题)
- Finalizer 阻塞删除
6.2 回滚失败
现象
$ kubectl rollout undo deployment/myapp --to-revision=1
error: unable to rollout deployment "myapp": revision 1 not found
解决方案
# 1. 查看可用版本
kubectl rollout history deployment/myapp
# 2. 如果 revisionHistoryLimit 太小导致历史版本被清理
# 修改 Deployment 增加保留数量
kubectl patch deployment myapp -p '{"spec":{"revisionHistoryLimit":20}}'
# 3. 手动回滚(重新应用旧配置)
kubectl apply -f deployment-v1.yaml
6.3 Pod 无法就绪导致更新阻塞
问题根因
新 Pod 创建 → ReadinessProbe 检查 → 失败 → 无法接收流量
→ Deployment 等待 Pod Ready → 超时 → 更新卡住
排查命令
# 检查 ReadinessProbe 配置
kubectl get deployment myapp -o jsonpath='{.spec.template.spec.containers[0].readinessProbe}'
# 查看 Pod 就绪状态
kubectl get pods -l app=myapp -o wide
# 检查 Pod 日志
kubectl logs <pod-name>
# 进入 Pod 调试
kubectl exec -it <pod-name> -- /bin/sh
修复示例:
# 增加 initialDelaySeconds,给应用更多启动时间
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30 # 从5秒增加到30秒
periodSeconds: 5
failureThreshold: 5 # 允许更多失败次数
6.4 资源不足导致更新失败
现象
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 1m default-scheduler 0/3 nodes are available: 3 Insufficient cpu.
解决方案
# 1. 检查节点资源
kubectl top nodes
# 2. 临时降低 replicas 完成更新
kubectl scale deployment myapp --replicas=2
# 3. 更新完成后恢复
kubectl scale deployment myapp --replicas=5
# 4. 或者调整资源请求
kubectl set resources deployment myapp -c myapp --requests=cpu=50m,memory=64Mi
七、高级技巧与扩展
7.1 使用 kubectl 快速操作
# 设置镜像
kubectl set image deployment/myapp nginx=nginx:1.22
# 设置环境变量
kubectl set env deployment/myapp APP_ENV=production
# 设置资源限制
kubectl set resources deployment/myapp -c app --limits=cpu=500m,memory=256Mi
# 暴露端口
kubectl expose deployment/myapp --port=80 --target-port=8080 --type=LoadBalancer
# 自动扩缩容
kubectl autoscale deployment/myapp --min=3 --max=10 --cpu-percent=80
7.2 与 ConfigMap/Secret 集成
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: app
image: myapp:v2.0
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: app-secret
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config
配置更新自动重启:
# 添加 annotation 触发重启
spec:
template:
metadata:
annotations:
checksum/config: "sha256sum-of-configmap" # 配置变化时更新此值
7.3 与 HPA(水平自动扩缩容)集成
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
八、总结
8.1 核心要点回顾
| 概念 | 要点 |
|---|---|
| 滚动更新 | 通过 maxSurge 和 maxUnavailable 控制更新节奏 |
| 版本管理 | 通过 ReplicaSet 保留历史,revisionHistoryLimit 控制数量 |
| 回滚机制 | 支持手动和自动回滚,回滚本身也生成新版本 |
| 探针配置 | ReadinessProbe 决定流量,LivenessProbe 决定重启 |
| 零宕机 | maxUnavailable=0 + ReadinessProbe 保证 |
8.2 设计原则
✅ DO:
- 始终配置 ReadinessProbe 和 LivenessProbe
- 设置合理的 progressDeadlineSeconds
- 保留足够的 revisionHistoryLimit
- 使用 RollingUpdate 策略实现零宕机
- 配置 terminationGracePeriodSeconds 优雅关闭
❌ DON’T:
- 不要在生产环境使用 Recreate 策略(除非必要)
- 不要将 maxUnavailable 设置为大于0(如需零宕机)
- 不要忘记配置 resource limits
- 不要忽略 Pod 的优雅退出处理
8.3 下一步学习
-
深入理解:
-
实战演练:
- 配置 GitOps 流水线(ArgoCD/Flux)
- 实现蓝绿/金丝雀发布
- 集成监控系统(Prometheus + Grafana)
-
高级主题:
- 自定义 Deployment Controller
- 多集群部署策略
- Service Mesh 流量管理
参考资料
-
官方文档
-
源码
-
最佳实践
版权声明:本文为原创技术文档,转载请保留原文链接。
联系方式:如有疑问或建议,欢迎在评论区交流讨论。
⭐ 如果觉得本文有帮助,请点赞支持!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)