在K8S中,Deployment升级策略有哪些?
在 Kubernetes 中,Deployment 是管理无状态应用部署的核心控制器,它提供了声明式的更新能力,允许你安全、可控地将 Pod 从一个版本更新到另一个版本。其升级策略主要通过 .spec.strategy
字段定义,主要有以下两种策略:
RollingUpdate
(滚动更新 - 默认策略)Recreate
(重新创建)
下面详细解析这两种策略的特性、工作原理及适用场景:
1. RollingUpdate
(滚动更新 - 默认策略)
- 核心思想: 逐步、平滑地替换旧版本的 Pod 副本为新版本的 Pod 副本。在整个更新过程中,应用始终保持 可用状态(零停机时间或接近零停机时间),并且能够处理用户请求。
- 工作原理:
- 逐步创建新 Pod: Deployment 控制器启动新版本的 Pod (
new ReplicaSet
)。新 Pod 启动后,会经历Pending
->ContainerCreating
->Running
状态,并且必须通过就绪探针 (readinessProbe
) 的检查,才会被视为“就绪”。 - 逐步终止旧 Pod: 一旦新 Pod 就绪并能够处理请求,控制器就会开始终止一个或多个旧版本的 Pod (
old ReplicaSet
)。终止前会等待其完成正在处理的请求(如果配置了preStop
钩子,会先执行它)。 - 循环往复: 这个过程(创建新 Pod -> 等待新 Pod 就绪 -> 终止旧 Pod)持续进行,直到所有旧 Pod 都被新 Pod 替换完毕。
- 逐步创建新 Pod: Deployment 控制器启动新版本的 Pod (
- 关键控制参数:
.spec.strategy.rollingUpdate
下可以配置两个重要参数来控制更新速度和风险:maxUnavailable
(最大不可用数):- 指定在更新过程中,允许同时不可用(例如正在终止、启动中或未就绪)的 Pod 数量占总期望副本数 (
spec.replicas
) 的比例或绝对数量。 - 目的: 确保在更新期间始终有足够数量的 Pod(
期望副本数 - maxUnavailable
)可用,以维持服务的基本容量和稳定性。这是保证服务可用的关键约束。 - 取值: 可以是整数(绝对数量,如
1
)或百分比字符串(如"25%"
)。默认值为25%
。 - 示例: 如果有 10 个副本 (
replicas: 10
),maxUnavailable: 2
或maxUnavailable: "20%"
,意味着更新过程中最多允许 2 个 Pod 不可用,至少有 8 个 Pod 可用。
- 指定在更新过程中,允许同时不可用(例如正在终止、启动中或未就绪)的 Pod 数量占总期望副本数 (
maxSurge
(最大峰值数):- 指定在更新过程中,允许创建的超过期望副本数的 Pod 数量占总期望副本数的比例或绝对数量。
- 目的: 控制更新速度和新旧 Pod 同时运行的数量上限。允许在终止旧 Pod 之前先启动更多新 Pod,可以加速更新过程,但会暂时消耗更多资源。
- 取值: 可以是整数(绝对数量,如
1
)或百分比字符串(如"25%"
)。默认值为25%
。 - 示例: 如果有 10 个副本 (
replicas: 10
),maxSurge: 3
或maxSurge: "30%"
,意味着在更新过程中,Pod 总数(旧+新)最多可以达到10 + 3 = 13
个。
- 工作流程简化示例 (假设
replicas: 4
,maxUnavailable: 1
,maxSurge: 1
):- 终止 1 个旧 Pod (此时可用旧 Pod: 3)。
- 创建 1 个新 Pod 并等待其就绪 (此时总 Pod 数: 4 (3旧+1新))。
- 再终止 1 个旧 Pod (可用旧 Pod: 2, 新 Pod: 1 就绪)。
- 再创建 1 个新 Pod 并等待其就绪 (总 Pod 数: 4 (2旧+2新))。
- 重复步骤 3 和 4,直到所有 4 个 Pod 都是新版本。
- 优点:
- 零停机/高可用: 服务在整个更新过程中持续可用。
- 平滑过渡: 流量逐渐从旧实例迁移到新实例,负载均衡器有足够时间调整。
- 容错性好: 如果新版本 Pod 启动失败或无法通过就绪探针,更新过程会自动暂停(旧的健康 Pod 仍在运行),方便回滚或调试。
- 支持回滚: 可以轻松回滚到之前的 ReplicaSet 版本。
- 缺点:
- 更新速度相对较慢: 受
maxUnavailable
和maxSurge
限制,以及新 Pod 启动、就绪所需时间影响。 - 资源消耗略高: 在更新过程中,会同时运行新旧两套 Pod (
maxSurge
允许的额外 Pod),临时占用更多资源。 - 存在短暂版本共存: 新旧版本的 Pod 会同时运行一段时间,需要确保应用设计能兼容这种短暂共存(如 API 向后兼容)。
- 更新速度相对较慢: 受
- 适用场景: 生产环境的绝大多数情况,尤其是对服务可用性要求高的场景(如 Web 服务、API 服务)。
2. Recreate
(重新创建)
- 核心思想: 先一次性终止所有旧版本的 Pod,然后再一次性创建所有新版本的 Pod。在旧 Pod 完全终止到新 Pod 启动并准备好这段时间内,服务会中断。
- 工作原理:
- 终止所有旧 Pod: Deployment 控制器首先删除由旧 ReplicaSet 管理的所有 Pod。这些 Pod 会被优雅终止(发送
TERM
信号,执行preStop
钩子,等待宽限期结束)。 - 等待旧 Pod 完全终止: 控制器等待所有旧 Pod 被完全删除。
- 创建所有新 Pod: 只有等所有旧 Pod 都消失后,控制器才开始创建新 ReplicaSet 管理的所有新 Pod。新 Pod 启动并需要通过就绪探针后,服务才恢复。
- 终止所有旧 Pod: Deployment 控制器首先删除由旧 ReplicaSet 管理的所有 Pod。这些 Pod 会被优雅终止(发送
- 关键控制参数: 此策略本身没有像
RollingUpdate
那样的额外参数 (maxUnavailable
,maxSurge
)。 - 优点:
- 过程简单直接: 实现逻辑简单。
- 确保版本一致性: 在更新过程中,不会同时存在新旧版本的 Pod。新 Pod 启动时,旧环境已被完全清理干净。
- 资源使用平稳: 在更新间隙(中断期间),没有 Pod 运行;新 Pod 启动后,资源消耗立即回到设定副本数。没有
maxSurge
带来的临时资源超额。
- 缺点:
- 服务中断: 在旧 Pod 全部终止到新 Pod 全部就绪这段时间内(可能持续数秒到数分钟),服务完全不可用。这是该策略的主要缺点。
- 回滚窗口窄: 如果在创建新 Pod 时遇到问题,回滚需要重新经历一次
Recreate
过程,中断时间更长。
- 适用场景:
- 开发、测试环境: 快速迭代,对短暂中断不敏感。
- 批处理任务/离线作业: 任务本身不是持续服务,允许中断。
- 数据库 schema 迁移等需要独占操作: 确保迁移时只有新版本应用在运行,避免旧版本应用访问新 schema 导致错误。(需谨慎评估中断影响)
- 应用无法容忍新旧版本短暂共存: 极其罕见的情况,通常应优先解决应用兼容性问题。
配置示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 3
strategy:
type: RollingUpdate # 或 Recreate
rollingUpdate: # 仅当 type: RollingUpdate 时有效
maxUnavailable: 1 # 或 "25%"
maxSurge: 1 # 或 "25%"
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: my-registry/my-app:v2.0.0 # 更新镜像触发升级
ports:
- containerPort: 8080
readinessProbe: # 对 RollingUpdate 至关重要!
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
选择策略的关键考虑因素
- 服务可用性要求:
- 要求高可用(零停机): 必须选择
RollingUpdate
。 - 允许短暂中断: 可以考虑
Recreate
(通常仅在非生产环境或特定场景)。
- 要求高可用(零停机): 必须选择
- 应用兼容性:
- 新旧版本可以共存:
RollingUpdate
是首选。 - 新旧版本绝对不能共存(极其罕见): 可能需要
Recreate
,但应优先尝试解决兼容性问题。
- 新旧版本可以共存:
- 更新速度:
- 需要快速完成更新(容忍资源峰值):
RollingUpdate
可通过增大maxSurge
和maxUnavailable
来加速(但风险增加)。 - 速度次要,稳定第一:
RollingUpdate
配合保守的maxUnavailable
(如1
或"10%"
)。
- 需要快速完成更新(容忍资源峰值):
- 资源限制:
- 集群资源紧张,无法容忍临时超额:
RollingUpdate
需设置较小的maxSurge
或Recreate
(后者只在中断期省资源)。
- 集群资源紧张,无法容忍临时超额:
- 操作类型:
- 常规应用更新:
RollingUpdate
。 - 需要独占访问资源的操作(如特定数据库迁移):
Recreate
(需评估中断影响)。
- 常规应用更新:
总结: RollingUpdate
凭借其平滑、高可用的特性,是 Kubernetes Deployment 默认且强烈推荐用于生产环境的升级策略。Recreate
仅适用于少数能容忍服务中断的特定场景。理解并合理配置 maxUnavailable
和 maxSurge
对于优化 RollingUpdate
的性能、速度和风险至关重要。同时,确保为 Pod 配置有效的 readinessProbe
是 RollingUpdate
成功的关键。