Milvus Helm 部署零停机滚动升级:rollingUpdate.sh 脚本的原理剖析与实战操作
Milvus 2.2.3 起支持滚动更新(Rolling Update),官方提供了 rollingUpdate.sh 脚本,可在不中断服务的前提下将 Helm 安装的 Milvus 集群逐组件升级到新版本。读完本文,你将掌握该脚本的完整参数与标准操作流程,并理解其“检查-开启 Active Standby-按序 kubectl patch-轮询 rollout 状态”的底层实现,以及零停机设计背后的原理与适用边界。
一、滚动升级的适用范围与前提
Milvus 从 2.2.3 版本开始支持滚动更新,deployments/upgrade/rollingUpdate.sh 脚本可帮助你在零停机的情况下完成版本升级(见 deployments/upgrade/README.md)。使用该脚本前必须确认以下四点限制:
- 源版本必须不低于 2.2.0:滚动更新依赖该版本之后引入的 Active Standby 等协调者高可用机制;
- 仅适用于 Helm 安装的 Milvus:通过 Milvus Operator 安装的集群不在支持范围内;
- 目前仅支持 update 操作:脚本的
-o参数只接受update,回滚(rollback)尚未实现(源码中do_rollback仅打印kubectl rollout history,标注 “not in use now”); - RocksMQ 的 standalone 不支持滚动更新:脚本在
prepare阶段会主动检测并拒绝执行。
二、脚本参数详解
脚本通过 getopts "n:i:t:w:o:" 解析命令行选项(见 rollingUpdate.sh),完整参数如下:
| 参数 | 说明 | 默认值 | 是否必填 |
|---|---|---|---|
-i |
Milvus 实例名称(Helm release name) | None |
是 |
-n |
Milvus 安装的命名空间 | default |
否 |
-t |
目标 Milvus 版本 | None |
是 |
-w |
新的 Milvus 镜像 tag | milvusdb/milvus:v2.2.3 |
是 |
-o |
操作类型 | update |
否 |
脚本内置默认值定义在 rollingUpdate.sh:
readonly STRATEGY='RollingUpdate'
NAMESPACE="default"
IMAGE_TAG="milvusdb/milvus:v2.2.3"
OPERATION="update"
参数校验逻辑(option_check,rollingUpdate.sh)的规则是:
- 缺少
-i直接报错退出; - 操作为
update时,-t与-w二者缺一即报错; -o传入非update的值时打印 Usage 并退出。
若不传任何参数,脚本会打印 Usage 帮助(rollingUpdate.sh):
[Warning]: Based on kubectl
-n [namespace] Default:[default]
The namespace that Milvus is installed in.
-i [instance name] [required] The name of milvus instance.
-t [target_version] [required] The milvus target version.
-w [image_tag] [required] The target milvus image tag.
-o [operation] Only support [update] now.
RollingUpdate Example:
sh rollingUpdate.sh -n default -i my-release -o update -t 2.2.3 -w 'milvusdb/milvus:v2.2.3'
三、滚动升级的标准操作流程
官方给出的升级步骤共四步(见 deployments/upgrade/README.md):
- 检查该 Milvus 实例的所有 Deployment,确认没有任何 Deployment 处于阻塞(blocked)状态;
- 逐个更新 Deployment,更新顺序目前硬编码在脚本中;
- 在命令中指定命名空间、实例名、目标版本与目标镜像;
- 运行脚本。以下示例将 Milvus 升级到 2.2.3:
sh rollingUpdate.sh -n default -i my-release -o update -t 2.2.3 -w 'milvusdb/milvus:v2.2.3'
两个关键实现细节(README 中的 Note):
- 脚本通过
kubectl patch修改 Deployment,并用kubectl rollout status观察其状态; -t指定的 target version 实质是 Deployment 的标签app.kubernetes.io/version,同样通过kubectl patch写入,因此它既用于标记版本,也方便升级后按标签核对各组件版本。
四、脚本内部流程剖析
脚本的主入口是一条链式调用(rollingUpdate.sh):
function main() {
pre_check && prepare && check_rollout_status && do_rollout && check_rollout_status true
exit $?
}
整个升级过程可分为五段,逐一拆解如下。
4.1 预检查:pre_check
pre_check = env_check && option_check && check_instance(rollingUpdate.sh),依次完成三项检查:
env_check:which kubectl确认本机已安装 kubectl,否则直接退出;option_check:即上节的参数必填性校验;check_instance:通过标签选择器在目标命名空间查找该实例的 Deployment:
kubectl get deploy -n $NAMESPACE -l app.kubernetes.io/instance=$INSTANCE,app.kubernetes.io/name=milvus --output=jsonpath={.items..metadata.name}
查不到任何结果时说明 -i 传入的实例名有误,脚本退出。这里可以看出:脚本识别 Milvus 组件完全依赖 Helm Chart 注入的标准标签 app.kubernetes.io/instance 和 app.kubernetes.io/name=milvus,这也是“仅适用于 Helm 安装”这一限制的根源。
4.2 开启滚动更新模式:prepare
prepare 阶段调用 set_rollingupdate_mode(rollingUpdate.sh),做两件事:
(1)拒绝 RocksMQ standalone。从名为 ${INSTANCE}-milvus 的 ConfigMap 中提取 messageQueue 配置:
local configmaps_name=${INSTANCE}-milvus
local mq=$(kubectl -n $NAMESPACE get configmaps $configmaps_name -o jsonpath='{.data}'|egrep -o 'messageQueue: \w*' --color|tail -1|awk '{print $2}')
if [[ $mq == "rocksmq" ]];then
echo "standalone Milvus with mq:rocksmq don't support rolling update now" && exit 1
fi
(2)向 ConfigMap 的 user.yaml 中追加 Active Standby 配置。若检测到尚未开启,则通过 sed 拼接后 kubectl apply,为四个协调者注入 enableActiveStandby: true:
rootCoord:
enableActiveStandby: true
queryCoord:
enableActiveStandby: true
dataCoord:
enableActiveStandby: true
indexCoord:
enableActiveStandby: true
这段配置正是零停机的核心机制,下节详述。注意脚本只对 user.yaml 字段做幂等检查(已包含则跳过重复写入)。
4.3 升级前的全局状态确认:check_rollout_status
do_rollout 执行前先对所有 Deployment 逐个调用 check_deploy_status false(不 watch),只要有一个未处于 rollout successful 状态,就打印该 Deployment 的 Pod 列表并退出,提示“可能正在部署或有故障,需先修复”(rollingUpdate.sh)。这保证了升级起点是一个“全部健康”的集群。
4.4 逐个更新:match_deploy 与 deploy_update
组件顺序是硬编码的。match_deploy 按名称后缀从实例 Deployment 列表中筛出各组件,顺序为(rollingUpdate.sh):
rootcoord → datacoord → indexcoord → querycoord → indexnode → datanode → querynode → proxy → standalone
该顺序的设计意图是从元数据/调度类协调者开始,最后更新直接面向客户端的 proxy;standalone 作为单机部署形态被单独匹配。
每个 Deployment 的更新动作在 deploy_update 中(rollingUpdate.sh):
kubectl -n $NAMESPACE patch deployments.apps $deployment -p \
'{"metadata":{"labels":{"app.kubernetes.io/version":"'$TARGET_VERSION'"}},"spec":{'$wait_time'"strategy":{"type":"'$STRATEGY'"},"template":{"spec":{"containers":[{"image":"'$IMAGE_TAG'","name":"'$name'"}]}}}}'
即一次性 patch 三处:app.kubernetes.io/version 标签、镜像 tag、滚动更新策略 RollingUpdate。另有一个针对性优化——名称包含 coord 的 Deployment 会额外注入 "minReadySeconds":30,让协调者新 Pod 就绪后至少稳定运行 30 秒才继续滚动,降低协调者切换瞬间的抖动风险:
echo $deployment|grep coord >/dev/null && local wait_time='"minReadySeconds":30,' || local wait_time=''
patch 之后立即调用 check_deploy_status true $deploy,底层是:
kubectl -n $NAMESPACE rollout status deployment $deploy --watch=$watchOption | grep -i successful
任一 Deployment 的 rollout 未成功,脚本打印错误并退出,不会继续更新后续组件。
4.5 升级后的最终确认
main 在 do_rollout 之后再次调用 check_rollout_status true(watch 模式),对全部 Deployment 做一轮最终确认,确保整个实例所有组件均 rollout successful 后才以 0 退出。
五、零停机机制解析:Active Standby 与升级顺序
滚动升级能做到“零停机”,依赖两个配合的机制。
机制一:协调者 Active Standby。 Milvus 的四个协调者(rootCoord、queryCoord、dataCoord、indexCoord)各自支持 enableActiveStandby 配置项,当前仓库的 configs/milvus.yaml 中均默认关闭,例如:
- mixCoord 段:
enableActiveStandby: false - rootCoord 段:
enableActiveStandby: false - queryCoord 段:
enableActiveStandby: false - dataCoord 段:
enableActiveStandby: false
在 querycoordv2 源码中可以看到该配置在服务启动时读取并生效(server.go):
s.enableActiveStandBy = Params.QueryCoordCfg.EnableActiveStandby.GetAsBool()
开启后,同一角色可存在多个副本、仅一个处于活跃状态,其余热备待命。滚动升级时旧 Pod 下线,热备 Pod 可接管协调者职责,从而避免“单副本协调者被替换”造成的服务空窗。脚本在 prepare 阶段自动写入这些配置,正是为升级过程临时搭建这条“安全垫”。
机制二:自底向上的更新顺序与逐组件门控。 脚本先更新协调者与节点,最后更新 proxy;且每 patch 一个 Deployment 都会阻塞等待其 rollout status 出现 successful,才处理下一个。从源码结构看,这保证了任意时刻集群中不存在“协调者尚在重启、数据节点也已重启”的叠加窗口。
需要说明的是,mixCoord 配置段在当前仓库中已出现(即协调者合并形态),而脚本针对的仍是 2.2.x 时代分立的 four coordinators 部署拓扑——脚本注入的 enableActiveStandby 键名与 rootcoord/datacoord/indexcoord/querycoord 的顺序都印证了这一点,用它升级更高大版本前建议先核对目标版本的组件名与配置结构。
六、局限性与注意事项
结合 README 与 rollingUpdate.sh 源码,使用时的实际边界包括:
- 无自动回滚能力:
do_rollback目前只调用kubectl rollout history打印历史(rollingUpdate.sh),失败时需借助 K8s 自身的kubectl rollout undo等机制自行处理;store_metadata中也注明“若要支持强更新与回滚,需要保留状态信息”,即设计上的已知缺口。 - 顺序硬编码:组件顺序写死在
match_deploy中,若你的集群存在非标准 Deployment 命名(如经过二次加工的 Chart),可能匹配不到而实际跳过更新。 - 仅基于 kubectl 标签与 ConfigMap 约定工作:实例识别依赖
app.kubernetes.io/instance/app.kubernetes.io/name=milvus标签与${INSTANCE}-milvus命名 ConfigMap,Operator 部署的集群不具备这些约定。 - RocksMQ standalone 直接拒绝执行:RocksMQ 作为单机消息队列不具备分布式 HA 能力,无法保证滚动期间写入连续性。
- 目标版本标签的副作用:
-t会写入app.kubernetes.io/version标签,升级后可用kubectl get deploy -l app.kubernetes.io/version=2.2.3等标签选择器核对各组件版本,脚本中未启用的check_version(rollingUpdate.sh)也正是基于该标签检测实例内是否混跑了多个版本。
七、小结
deployments/upgrade/rollingUpdate.sh 用一个约 180 行的 shell 脚本实现了 Helm 版 Milvus 的零停机滚动升级:以 kubectl 标签定位实例,预检查后自动为协调者开启 Active Standby,再按 rootcoord → datacoord → indexcoord → querycoord → indexnode → datanode → querynode → proxy(standalone)的硬编码顺序逐个 kubectl patch 镜像与版本标签,并对每个 Deployment 阻塞等待 rollout status 成功。掌握其参数与流程后,你可以将其作为 2.2.0 及以上版本集群的日常升级手段;同时应清楚它不支持回滚、不支持 Operator 安装形态与 RocksMQ standalone,失败恢复仍需依赖 Kubernetes 原生的 rollout 工具链。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00