本文目录导读:

滚动更新(Rolling Update)是Kubernetes等编排系统中,用于无宕机升级应用的核心策略,它的核心思想是逐步、分批替换旧版本的Pod,而不是一次性全部杀掉再重建。
下面详细解释滚动更新的顺序、原理以及关键参数。
核心顺序:先新后旧,先增后减
滚动更新的标准顺序可以概括为:
- 启动新Pod: 控制器(如Deployment)会启动一个或多个新版本的Pod。
- 等待就绪: 它等待这些新Pod成功通过
readiness probe(就绪探针),确认它们可以正常处理流量。 - 关闭旧Pod: 健康的新Pod加入服务后,控制器会优雅地关闭相同数量的旧Pod。
- 重复循环: 这个过程不断重复,直到所有旧Pod都被新Pod替换。
核心原则: 在任何时间点,集群中都同时存在新旧两个版本的Pod,且服务的总容量(可用Pod数量)始终保持在一个可控范围内(由maxSurge和maxUnavailable参数控制)。
关键参数控制顺序和速度
滚动更新的具体“一波”替换多少个Pod,以及如何控制新旧Pod的比例,由两个关键参数决定:
-
maxSurge(最大峰值/超量):- 定义: 在滚动更新期间,允许超出期望副本数(
replicas)的最大Pod数量。 - 形式: 可以是绝对数字(如
2)或百分比(如25%)。 - 作用: 决定了“一次最多能启动多少个新Pod”,值越大,更新速度越快,但瞬间资源消耗也更高。
- 示例(假设
replicas=10,maxSurge=25%):- 最大允许Pod总数 =
10(期望) +5(向上取整为3) =13。 - 一次最多可以启动3个新Pod。
- 最大允许Pod总数 =
- 定义: 在滚动更新期间,允许超出期望副本数(
-
maxUnavailable(最大不可用):- 定义: 在滚动更新期间,允许不可用的最大Pod数量(相对于期望副本数)。
- 形式: 可以是绝对数字(如
1)或百分比(如25%)。 - 作用: 保证了服务的最低可用容量,值越小,服务越稳定(始终有足够多Pod在运行),但更新速度越慢。
- 示例(假设
replicas=10,maxUnavailable=0):- 这意味着在更新过程中,必须保持至少10个Pod可用。
- 必须先启动一个新Pod并确认它可用后,才能关闭一个旧Pod,更新会非常保守和缓慢。
通俗例子理解流程
假设有一个Deployment,replicas=3,maxSurge=1,maxUnavailable=0。
更新流程如下:
- 初始状态: 3个旧Pod都在运行(版本A)。
- 波次1:
- 启动1个新Pod(版本B)。
- 等待新Pod就绪。
- 新Pod就绪后,优雅关闭1个旧Pod。
- 当前状态: 3个Pod运行(2个版本A + 1个版本B)。
- 波次2:
- 启动另1个新Pod(版本B)。
- 等待就绪。
- 就绪后,优雅关闭第2个旧Pod。
- 当前状态: 3个Pod运行(1个版本A + 2个版本B)。
- 波次3:
- 启动最后1个新Pod(版本B)。
- 等待就绪。
- 就绪后,优雅关闭最后1个旧Pod。
- 最终状态: 3个新Pod运行(版本B)。
更细致的顺序:StatefulSet vs Deployment
上面的顺序主要针对无状态应用(Deployment)。有状态应用(StatefulSet) 的滚动更新顺序有所不同,且更关键:
- 默认顺序(逆向顺序/有序): StatefulSet 默认会从最后一个Pod开始,逐个进行更新。
- 原因: 有状态应用(如数据库)的Pod通常有依赖关系(主从复制),从编号最大的Pod(通常是“从”节点)开始更新,能最小化对集群的影响,如果直接更新第一个Pod(通常是“主节点”),可能导致整个集群不可用。
- 示例: 3个Pod(
statefulset-0,statefulset-1,statefulset-2)的更新顺序是:statefulset-2→statefulset-1→statefulset-0。
partition(分区更新): StatefulSet 还支持partition参数,允许你将更新过程割裂成两部分:- 更新区域: 编号
>= partition的Pod会更新。 - 保持区域: 编号
< partition的Pod保持原版本。 - 用途: 金丝雀发布、灰度发布,你可以先更新“从节点”验证新版本,确认无误后再逐步将
partition调低,最终更新“主节点”。
- 更新区域: 编号
顺序与风险控制
| 场景 | 更新顺序 | 关键控制点 | 目的 |
|---|---|---|---|
| 无状态应用 (Deployment) | 并行/随机,但总数由 maxSurge/maxUnavailable 控制 |
先启动新Pod,等待就绪,再关闭旧Pod | 最大化可用性:确保在任何时刻都有足够多的Pod处理请求。 |
| 有状态应用 (StatefulSet) | 逆向有序:从Pod编号最大的开始 | 从最后一个Pod开始更新,逐步向前 | 最小化影响:避免同时变更主从角色,特别适合需要Leader选举或数据同步的场景。 |
常见误区与最佳实践
- 不要用
maxUnavailable=100%: 这等同于一次性删除所有旧Pod再重建,失去了滚动更新的意义(可能导致服务完全中断)。 readiness probe必须正确: 滚动更新的核心依赖就绪探针,如果探针配置错误(永远返回成功或失败),更新流程会出错(要么永远不替换,要么每次替换都失败)。- 注意
initContainers: 如果新版本Pod有initContainers(初始化容器),它们会在每个新Pod启动时运行,这会增加更新总时长。 - 资源竞争: 如果集群资源紧张,
maxSurge设置过大可能导致Pod被Pending(挂起)。
总结一句话: 滚动更新遵循“先建新、后删旧、一批一批、等待就绪”的顺序,通过 maxSurge 控制同时存在的新Pod数,通过 maxUnavailable 控制同时缺失的旧Pod数,来保障服务在更新期间的稳定性。