基于本文回答
0
评论

Deployment 的滚动更新 (Rolling Update) 机制

知识点图片

Deployment 的滚动更新 (Rolling Update) 是 Kubernetes 中最常用、也是默认的部署更新策略。它的核心目标是在不中断服务(Zero Downtime)的情况下,将应用从一个版本平滑过渡到另一个版本。

以下是关于滚动更新机制的深度解析,包括原理、关键参数、流程以及注意事项。


1. 核心原理

滚动更新通过逐步替换的方式进行更新。Deployment 控制器会创建一个新的 ReplicaSet(副本集),然后逐步增加新 ReplicaSet 的 Pod 数量,同时逐步减少旧 ReplicaSet 的 Pod 数量,直到旧版本 Pod 全部消失,新版本 Pod 达到期望数量。

简单概括:

  1. 启动一个新的 Pod (v2)。
  2. 等待新 Pod 变为 Ready (就绪) 状态。
  3. 销毁一个旧的 Pod (v1)。
  4. 重复上述步骤,直到所有 Pod 更新完毕。

2. 关键配置参数 (strategy)

在 Deployment 的 YAML 文件中,spec.strategy 字段控制更新行为。

yaml
spec:
  replicas: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%        # 最大激增数
      maxUnavailable: 25%  # 最大不可用数

这两个参数决定了更新的速度和稳定性:

A. maxSurge (最大激增数)

  • 含义:在更新过程中,允许存在的 Pod 总数量超过 spec.replicas (期望副本数) 的最大值。
  • :可以是绝对数字(如 2)或百分比(如 25%)。
  • 作用:决定了 K8s 可以“提前”创建多少个新 Pod。值越大,更新越快,但消耗的资源(CPU/内存)越多。
  • 计算:如果 replicas=10, maxSurge=2,则更新期间最多可以有 12 个 Pod 同时运行。

B. maxUnavailable (最大不可用数)

  • 含义:在更新过程中,允许处于“不可用”状态的 Pod 的最大数量。
  • :可以是绝对数字(如 1)或百分比(如 25%)。
  • 作用:决定了在更新期间,最少有多少个 Pod 必须是可用的。值越小,服务越稳定,但更新速度可能变慢。
  • 计算:如果 replicas=10, maxUnavailable=2,则更新期间至少要有 8 个可用的 Pod (10 - 2)。

3. 滚动更新的详细流程

假设我们有一个 Deployment:

  • replicas: 3
  • maxSurge: 1
  • maxUnavailable: 0 (为了保证服务绝对稳定,不允许任何 Pod 不可用)

流程如下:

  1. 初始状态:ReplicaSet-V1 有 3 个 Pod,全部 Running。
  2. 触发更新:用户修改镜像版本。
  3. 创建新 RS:Deployment 创建 ReplicaSet-V2,初始副本数为 0。
  4. Scale Up (扩容):因为 maxSurge=1,Deployment 允许总数达到 4。ReplicaSet-V2 副本数变为 1。系统启动第 1 个新 Pod。
  5. Readiness Check (就绪检查):K8s 等待新 Pod 通过 Readiness Probe。
  6. Scale Down (缩容):一旦新 Pod 就绪,总可用 Pod 变成了 4 个。Deployment 将 ReplicaSet-V1 的副本数减为 2。销毁 1 个旧 Pod。
  7. 循环
    • RS-V2 扩容到 2 -> 等待就绪 -> RS-V1 缩容到 1。
    • RS-V2 扩容到 3 -> 等待就绪 -> RS-V1 缩容到 0。
  8. 完成:ReplicaSet-V1 即使为 0 也会被保留(用于回滚),ReplicaSet-V2 成为主力。

4. 至关重要的配合机制:Readiness Probe

这是滚动更新不中断服务的关键!

如果没有配置 Readiness Probe (就绪探针),Kubernetes 会认为 Pod 一旦启动(Running 状态)就是可用的。

  • 后果:如果你的应用启动需要 30 秒加载数据,但 K8s 在 Pod 启动第 1 秒就认为它 Ready 了,并立即杀掉旧 Pod,流量打到新 Pod 上就会报错(502/Connection Refused),导致服务中断。

正确做法:配置 Readiness Probe,确保新 Pod 真正能够处理流量后,K8s 才会继续滚动更新。

yaml
readinessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 10

此外,配合 minReadySeconds 字段使用效果更佳:

  • minReadySeconds: 10:Pod 变为 Ready 后,必须保持 Ready 状态 10 秒,才被视为真正的“可用”。这可以防止“启动即崩溃”的循环重启问题。

5. 常用命令操作

  • 触发更新

    bash
    kubectl set image deployment/my-app nginx=nginx:1.16
    # 或者直接 edit / apply yaml
  • 查看进度

    bash
    kubectl rollout status deployment/my-app
  • 暂停/恢复更新(用于金丝雀发布场景):

    bash
    kubectl rollout pause deployment/my-app  # 更新一部分后暂停,观察流量
    kubectl rollout resume deployment/my-app # 没问题继续
  • 回滚(如果新版本有问题):

    bash
    kubectl rollout undo deployment/my-app
    # 回滚到特定版本
    kubectl rollout undo deployment/my-app --to-revision=2

6. 优缺点分析

优点

  • 零停机:服务一直在线。
  • 原生支持:无需额外工具,K8s 内置。
  • 风险可控:通过 maxUnavailablemaxSurge 控制更新节奏。

缺点

  • 版本共存:在更新期间,集群中会同时存在 v1 和 v2 两个版本的应用。
    • 注意:如果 v2 修改了数据库 Schema 且不向后兼容,可能会导致 v1 的 Pod 报错。应用必须设计为向后兼容。
  • 流量控制弱:无法像 Istio 那样精确控制 1% 的流量去新版本,它是基于 Pod 数量的粗粒度负载均衡。
  • 回滚慢:如果新版本有 Bug,回滚本质上是一次“反向的滚动更新”,需要时间。

总结

Kubernetes Deployment 的滚动更新通过双 ReplicaSet 控制就绪探针(Readiness Probe)的配合,实现了平滑的版本迭代。理解 maxSurgemaxUnavailable 是调优更新速度和稳定性的关键。

右滑查看面试常问