Deployment 与 ReplicaSet:副本管理与滚动更新

摘要:Deployment 是生产环境中最常用的工作负载控制器。本文详解 Deployment 如何通过 ReplicaSet 管理 Pod 副本,实现滚动更新、版本回滚、弹性伸缩和自愈能力,并深入分析其内部工作机制。

一、为什么不直接创建 Pod?

直接创建 Pod(裸 Pod)存在四个核心问题:Pod 终止后无法自动重建、扩容需要手动逐一创建、版本更新需要手动删旧建新且有停机风险、回滚需要手动操作且容易出错。Deployment 通过声明式管理解决了所有这些问题。
使用 Deployment
Pod 终止 → 自动重建
扩容 → 一条命令完成
更新 → 滚动更新,零停机
回滚 → 一键回滚任意版本
直接管理 Pod
Pod 终止 → 无自动重建
扩容 → 手动逐一创建
更新 → 删旧建新,有停机
回滚 → 手动操作,易出错

上图对比了直接管理 Pod 与使用 Deployment 的差异。Deployment 控制器持续监听实际状态与期望状态的差异,自动执行 Pod 的创建、删除和更新。

二、Deployment → ReplicaSet → Pod 层级关系

Kubernetes 通过三级资源层级管理应用副本:Deployment 管理 ReplicaSet,ReplicaSet 管理 Pod。用户只需操作 Deployment,底层由控制器自动协调。
Deployment
ReplicaSet
Pod 1
Pod 2
Pod 3

上图展示了 Deployment 的三级资源层级。Deployment 通过 ownerReferences 关联 ReplicaSet,ReplicaSet 同样通过 ownerReferences 关联 Pod,形成清晰的所有权链。

各层职责对比

资源 核心职责 用户是否直接操作
Deployment 管理 ReplicaSet 的创建和版本;控制滚动更新策略;支持版本回滚;记录部署历史 是(主要操作对象)
ReplicaSet 确保指定数量的 Pod 副本在运行;Pod 终止后自动创建新副本;多余 Pod 自动删除 否(由 Deployment 管理)
Pod 运行实际的应用容器 否(由 ReplicaSet 管理)

注意:不要直接创建或修改 ReplicaSet,应始终通过 Deployment 管理。直接操作 ReplicaSet 会导致 Deployment 控制器状态不一致。

ReplicaSet 控制循环

ReplicaSet 控制器持续执行以下逻辑:

  1. 通过 spec.selector 标签选择器查找匹配的 Pod
  2. 对比当前 Pod 数量与 spec.replicas 期望值
  3. Pod 数量不足 → 根据 Pod 模板创建新 Pod
  4. Pod 数量过多 → 按策略删除多余 Pod(优先删除 Pending/未调度的 Pod)

三、创建 Deployment

3.1 YAML 示例

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600
  minReadySeconds: 5
  selector:
    matchLabels:
      app: nginx
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: nginx
        version: v1
    spec:
      containers:
      - name: nginx
        image: nginx:1.24
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "250m"
            memory: "256Mi"
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 15
          periodSeconds: 10

3.2 YAML 字段详解

Deployment spec 核心字段
字段 类型 默认值 说明
spec.replicas int 1 期望的 Pod 副本数量
spec.selector object 必填 标签选择器,标识 Deployment 管理的 Pod。创建后不可修改
spec.template object 必填 Pod 模板,定义 Pod 的 spec。模板的 labels 必须与 selector 匹配
spec.strategy object RollingUpdate 更新策略,支持 RollingUpdateRecreate
spec.revisionHistoryLimit int 10 保留的历史 ReplicaSet 数量,用于回滚
spec.progressDeadlineSeconds int 600 部署进度截止时间(秒),超时则标记为 Failed
spec.minReadySeconds int 0 Pod 就绪后等待多少秒才视为 Available。用于确保新 Pod 稳定运行后再继续更新
spec.paused bool false 是否暂停 Deployment,暂停后修改不会触发滚动更新
strategy 字段
字段 说明
strategy.type RollingUpdate(默认):逐步替换,零停机;Recreate:先全部终止再创建,有停机
strategy.rollingUpdate.maxSurge 更新期间允许超出 replicas 的 Pod 数量(数字或百分比)
strategy.rollingUpdate.maxUnavailable 更新期间允许不可用的 Pod 最大数量(数字或百分比)

3.3 创建与验证

bash 复制代码
# 创建 Deployment
kubectl apply -f deployment.yaml

# 查看 Deployment 状态
kubectl get deployment nginx-deployment
# NAME               READY   UP-TO-DATE   AVAILABLE   AGE
# nginx-deployment   3/3     3            3           30s

# 查看创建的 ReplicaSet
kubectl get rs -l app=nginx
# NAME                          DESIRED   CURRENT   READY   AGE
# nginx-deployment-5d66cc795f   3         3         3       30s

# 查看 Pod
kubectl get pods -l app=nginx -o wide

3.4 资源命名规则

执行 kubectl apply 后,Deployment 控制器自动创建 ReplicaSet,ReplicaSet 再创建指定数量的 Pod:
nginx-deployment
nginx-deployment-5d66cc795f
...-5d66cc795f-abc12
...-5d66cc795f-def34
...-5d66cc795f-ghi56

上图展示了资源命名的层级关系。ReplicaSet 名称 = Deployment 名 + Pod 模板 hash(5d66cc795f);Pod 名称 = ReplicaSet 名 + 随机后缀。Pod 模板 hash 确保模板变更时创建新的 ReplicaSet。

四、滚动更新(Rolling Update)

滚动更新是 Deployment 的核心能力,通过逐步替换旧版 Pod 为新版 Pod 来实现零停机更新

4.1 滚动更新流程

当更新镜像版本(如 nginx:1.24 → nginx:1.25)时,Deployment 控制器创建新 ReplicaSet 并逐步扩容,同时缩容旧 ReplicaSet。整个过程中始终保持足够的 Pod 对外提供服务。
ReplicaSet v2 ReplicaSet v1 Deployment ReplicaSet v2 ReplicaSet v1 Deployment 初始:3 Pod (nginx:1.24) Pod 4 Ready Pod 5 Ready Pod 6 Ready 0 Pod(保留用于回滚) 3 Pod (nginx:1.25) 创建新 ReplicaSet 启动 Pod 4 缩容:终止 Pod 1 启动 Pod 5 缩容:终止 Pod 2 启动 Pod 6 缩容:终止 Pod 3

上图展示了滚动更新的完整时序:新 Pod 就绪后才缩减旧 Pod,保证服务不中断。

4.2 更新策略配置

yaml 复制代码
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

常见策略组合及适用场景:

maxSurge maxUnavailable 特点 适用场景
1 0 保守:始终保持完整服务能力,更新较慢 流量敏感的生产服务
25% 25% 默认:平衡速度和稳定性 大多数场景
50% 50% 激进:快速更新,服务能力有波动 非关键服务、测试环境
100% 0 蓝绿风格:先创建全部新 Pod,再删除旧 Pod 资源充足时快速切换

Recreate 策略:先终止所有旧 Pod,再创建新 Pod。会导致短暂停机,仅在应用不支持多版本共存(如数据库 schema 迁移)时使用。

4.3 触发更新的条件

只有 Pod 模板(.spec.template)发生变化才会触发滚动更新。以下操作不会创建新 ReplicaSet:

  • 修改 spec.replicas(仅扩缩容)
  • 修改 spec.strategy
  • 修改 metadata.labelsmetadata.annotations

触发更新的命令:

bash 复制代码
# 方式一:直接修改镜像
kubectl set image deployment/nginx-deployment nginx=nginx:1.25

# 方式二:修改环境变量等 Pod 模板字段
kubectl set env deployment/nginx-deployment APP_VERSION=v2

# 方式三:编辑 YAML
kubectl edit deployment nginx-deployment

# 方式四:修改 YAML 文件后 apply
kubectl apply -f deployment.yaml

# 查看更新状态(阻塞直到完成或超时)
kubectl rollout status deployment/nginx-deployment

4.4 Deployment 状态条件

通过 kubectl describe deployment 可以查看 Deployment 的 Conditions,用于判断部署是否健康:

Condition 含义
Progressing 正在创建新 ReplicaSet 或扩缩 Pod。超过 progressDeadlineSeconds 仍未完成则变为 False
Available Pod 达到 minReadySeconds 后标记为 Available。当可用 Pod 数 ≥ replicas - maxUnavailable 时为 True
ReplicaFailure ReplicaSet 创建 Pod 失败(如资源配额不足)

五、版本回滚

Deployment 自动保留历史 ReplicaSet(由 spec.revisionHistoryLimit 控制,默认 10),旧版本的 ReplicaSet 副本数缩为 0 但不删除,使回滚只需将旧 ReplicaSet 重新扩容。
Deployment
RS v1 nginx:1.22 → 0 Pod
RS v2 nginx:1.23 → 0 Pod
RS v3 nginx:1.24 → 0 Pod
RS v4 nginx:1.25 → 3 Pod ✓

上图展示了 Deployment 保留的 4 个 ReplicaSet 版本,仅当前版本(v4)有活跃 Pod。回滚时 Deployment 控制器将目标版本的 ReplicaSet 扩容到期望副本数,同时将当前版本缩为 0。

bash 复制代码
# 查看部署历史
kubectl rollout history deployment/nginx-deployment
# REVISION  CHANGE-CAUSE
# 1         <none>
# 2         <none>
# 3         <none>
# 4         <none>

# 记录变更原因(推荐在 apply 时添加 --record,但该参数已废弃,
# 建议改用 annotations:kubernetes.io/change-cause)
kubectl annotate deployment/nginx-deployment \
  kubernetes.io/change-cause="update to nginx:1.25"

# 查看某个版本的详情(Pod 模板内容)
kubectl rollout history deployment/nginx-deployment --revision=2

# 回滚到上一个版本
kubectl rollout undo deployment/nginx-deployment

# 回滚到指定版本
kubectl rollout undo deployment/nginx-deployment --to-revision=2

# 暂停/恢复更新(用于批量修改后一次性触发更新)
kubectl rollout pause deployment/nginx-deployment
# 执行多次修改...
kubectl rollout resume deployment/nginx-deployment

六、扩缩容

6.1 手动扩缩容

bash 复制代码
# 扩容到 5 个副本
kubectl scale deployment nginx-deployment --replicas=5

# 缩容到 2 个副本
kubectl scale deployment nginx-deployment --replicas=2

# 条件扩容(仅当前副本数为 3 时才扩到 5,避免竞争)
kubectl scale deployment nginx-deployment --replicas=5 --current-replicas=3

6.2 自动扩缩容(HPA)

HPA(Horizontal Pod Autoscaler)根据 CPU、内存等指标自动调整 Pod 副本数。HPA 控制器周期性(默认 15 秒)查询 Metrics Server 获取资源使用率,与目标阈值对比后计算期望副本数。
查询指标
调整 replicas
HPA 控制器
Metrics Server
Deployment
ReplicaSet
Pod × N

上图展示了 HPA 的工作流程:HPA 控制器从 Metrics Server 获取指标,计算期望副本数,然后修改 Deployment 的 replicas 字段。

bash 复制代码
# 快速创建 HPA
kubectl autoscale deployment nginx-deployment \
  --min=2 --max=10 --cpu-percent=70

HPA YAML 配置(支持多指标):

yaml 复制代码
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-deployment
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
    scaleUp:
      stabilizationWindowSeconds: 60

HPA 关键字段说明:

字段 说明
scaleTargetRef 指向被控制的 Deployment(或其他支持 scale 子资源的控制器)
minReplicas 最小副本数,HPA 不会缩容到此值以下
maxReplicas 最大副本数,HPA 不会扩容超过此值
metrics[].type 指标类型:Resource(CPU/内存)、Pods(自定义指标)、Object(外部对象指标)
metrics[].resource.target 目标值,Utilization 为百分比,AverageValue 为绝对值
behavior.scaleDown.stabilizationWindowSeconds 缩容稳定窗口期,防止指标波动导致频繁缩容。默认 300 秒
behavior.scaleUp.stabilizationWindowSeconds 扩容稳定窗口期,默认 0(立即扩容)
bash 复制代码
# 查看 HPA 状态
kubectl get hpa
# NAME        REFERENCE                    TARGETS   MINPODS   MAXPODS   REPLICAS
# nginx-hpa   Deployment/nginx-deployment  35%/70%   2         10        3

# 查看 HPA 详情(含事件和扩缩历史)
kubectl describe hpa nginx-hpa

前提条件 :HPA 依赖 Metrics Server 提供资源使用数据。Pod 必须设置 resources.requests,否则 HPA 无法计算利用率。

七、Deployment 常用命令速查

bash 复制代码
# ========== 创建与更新 ==========
kubectl apply -f deployment.yaml
kubectl set image deployment/nginx-deployment nginx=nginx:1.25
kubectl edit deployment nginx-deployment

# ========== 查看状态 ==========
kubectl get deployments
kubectl get deployment nginx-deployment -o yaml
kubectl describe deployment nginx-deployment
kubectl get rs -l app=nginx
kubectl get pods -l app=nginx -o wide

# ========== 滚动更新 ==========
kubectl rollout status deployment/nginx-deployment
kubectl rollout pause deployment/nginx-deployment
kubectl rollout resume deployment/nginx-deployment

# ========== 版本回滚 ==========
kubectl rollout history deployment/nginx-deployment
kubectl rollout history deployment/nginx-deployment --revision=2
kubectl rollout undo deployment/nginx-deployment
kubectl rollout undo deployment/nginx-deployment --to-revision=2

# ========== 扩缩容 ==========
kubectl scale deployment nginx-deployment --replicas=5
kubectl autoscale deployment nginx-deployment --min=2 --max=10 --cpu-percent=70

# ========== 重启(触发所有 Pod 重建) ==========
kubectl rollout restart deployment/nginx-deployment

# ========== 删除 ==========
kubectl delete deployment nginx-deployment

八、常见问题

Q1:滚动更新卡住怎么办?

排查步骤:

  1. kubectl rollout status deployment/nginx-deployment --- 查看更新进度
  2. kubectl get rs -l app=nginx --- 确认新旧 ReplicaSet 的 DESIRED/CURRENT/READY
  3. kubectl get pods -l app=nginx --- 查看新 Pod 状态(Pending / ImagePullBackOff / CrashLoopBackOff)
  4. kubectl describe pod <new-pod> --- 查看 Events 中的具体错误
  5. kubectl logs <new-pod> --- 查看应用日志

常见原因:镜像名称错误或不存在、镜像仓库认证失败、资源不足无法调度、readiness 探针配置错误导致 Pod 始终未就绪。

Q2:如何实现蓝绿部署或金丝雀发布?

Deployment 原生支持的是滚动更新。其他发布策略的实现方式:

策略 实现方式
蓝绿部署 创建两个 Deployment(blue/green),通过修改 Service 的 selector 切换流量
金丝雀发布 方式一:两个 Deployment 共用同一 Service(通过相同 label),控制副本比例(如 9:1);方式二:使用 Istio VirtualService 按权重分流;方式三:使用 Argo Rollouts

Q3:revisionHistoryLimit 设置多少合适?

默认值为 10。每个历史 ReplicaSet 副本数为 0,资源占用极低,但在 etcd 中仍有存储开销。建议:

  • 开发/测试环境:3-5
  • 生产环境:5-10
  • 频繁发布的服务:可适当调大

Q4:kubectl rollout restart 的原理是什么?

kubectl rollout restart 通过修改 Pod 模板的 annotation(kubectl.kubernetes.io/restartedAt)触发滚动更新。由于模板发生了变化,Deployment 控制器会创建新 ReplicaSet 并逐步替换所有 Pod。常用于不改代码但需重启 Pod 的场景(如刷新挂载的 ConfigMap)。

Q5:Deployment 更新超时怎么处理?

progressDeadlineSeconds(默认 600 秒)控制更新超时。超时后 Deployment 的 Progressing 条件变为 False,但不会自动回滚 。需要手动执行 kubectl rollout undo 回滚,或修复问题后重新触发更新。

九、总结

核心概念 说明
层级关系 Deployment → ReplicaSet → Pod,三级控制器链,通过 ownerReferences 关联
滚动更新 逐步替换旧 Pod 为新 Pod,通过 maxSurge / maxUnavailable 控制更新节奏
版本回滚 历史 ReplicaSet 副本缩为 0 保留,回滚时重新扩容目标版本
弹性伸缩 手动 kubectl scale 或 HPA 根据 CPU/内存等指标自动调整副本数
自愈能力 Pod 终止后 ReplicaSet 控制器自动创建新副本,维持期望状态
状态监控 通过 Conditions(Progressing / Available / ReplicaFailure)判断部署健康状态

生产建议

  • 始终使用 Deployment 而非裸 Pod
  • 设置合理的 resources.requests/limits,HPA 依赖 requests 计算利用率
  • 配置 readiness + liveness 探针,确保滚动更新能正确判断新 Pod 是否就绪
  • 设置 minReadySeconds(如 5-10 秒),避免新 Pod 刚启动就接收全部流量
  • 保留足够的 revisionHistoryLimit 用于快速回滚
  • 使用 kubectl annotate 记录每次变更原因,便于回滚时决策
相关推荐
没有bug.的程序员2 小时前
云原生安全深潜:K8s RBAC 权限模型内核、服务账户生命周期与权限最小化实战指南
安全·云原生·kubernetes·k8s·rbac·权限模型·服务账户
cllsse2 小时前
k8s 1.35学习
kubernetes
三点水-here15 小时前
05 - 大模型推理生产架构设计:混合部署与Kubernetes实战
云原生·容器·kubernetes·hpa·混合架构·gpu调度
海兰19 小时前
Elastic Stack 技术栈与无服务器架构核心指南
云原生·架构·serverless
别多香了19 小时前
Kubernetes Pod 管理
容器·kubernetes
认真的薛薛21 小时前
3.k8s-暴露pod和service
云原生·容器·kubernetes
Alice_whj1 天前
AI云原生笔记
人工智能·笔记·云原生
人间打气筒(Ada)1 天前
Kubernetes核心技术-service详解
云原生·容器·kubernetes·云计算·devops·service·service代理
匀泪1 天前
云原生(nginx环境设定)
java·nginx·云原生