深度|Zilliz Cloud 精细管控升级的三年心路复盘
过去几年,Milvus 在开源社区取得成功之后,我们很自然地开始思考下一个问题:能不能把它做成一款真正的云上产品,让用户不再需要理解背后的部署、扩容和运维细节,只通过一个 endpoint,就能获得稳定的向量数据库服务。
因为,一个真正进入生产环境的向量数据库,必要要严肃面对成本、版本升级、容量规划、故障恢复、监控告警、资源扩缩容和性能调优……这些对于大多数团队来说,重要但并不直接创造业务价值的需求。
在此背景下,云服务的意义,不仅在于借助极致的弹性,让业务增长时可以快速获得更多资源,流量下降时不必长期为闲置容量买单,同时也不需要为了应对峰值,提前准备一套长期处于低利用率的基础设施,带来更高的资源性价比;更在于把这些复杂度收进平台内部,让用户可以将最核心的资源,放在增长本身。
因此,我们要提供的,绝不是一个“已经部署好的 Milvus”,而是更低的运维成本、更高的资源利用率、更高性价比,以及面对业务波动时随时可用的弹性,于是,在 2023 年,我们推出了Zilliz Cloud 。
最开始,这件事听起来并不复杂。
Milvus 已经能够运行在 Kubernetes 上,也有相对成熟的部署工具。按照最直觉的思路,无非是把开源版本部署到云上,再补上一套控制台、监控、计费和运维系统。很多数据库的云托管产品,也确实是沿着这条路径发展起来的。
但真正开始做之后,我们很快发现:把 Milvus 跑在云上,和把 Milvus 做成云服务,是两件完全不同的事情。
用户看到的可能只是一个数据库地址,但在这个地址背后,运行的并不是一个单体进程。Proxy、QueryNode、DataNode、Coordinator、StreamingNode,以及对象存储、消息系统和索引服务,共同组成了一个不断变化的分布式系统。
把这些组件的 Pod 拉起来后,怎么让它们可以稳定对外服务?如何保证用户在升级、重启中依然能得到稳定的连续服务?多云环境中,权限模型、后端发现、私网接入和控制链路各不相同要如何设计?
也就是说,要做好云上的 Milvus也就是 Zilliz Cloud,绝不是给开源 Milvus 外面套一层 Kubernetes 和控制台,需要的是一套围绕分布式数据库生命周期的控制系统。
过去几年,我们在 Zilliz Cloud 上做的大量工作,几乎都围绕这个问题展开:如何把一个复杂的分布式数据库,变成一个用户不需要感知复杂度的云服务。
以下是我们的一些探索经验。
2023 年:基于 Operator 的第一阶段实践
在 2023 年,Zilliz Cloud 的管控方式和许多开源用户的实践类似:围绕 Milvus Operator 构建一层简单工作流,通过渲染配置,然后一次性 Patch 到 Kubernetes 中。
这一时期的大致链路是:客户提交创建或变配请求后,管控系统计算目标规格和配置,将其转换为声明式资源;中间控制器继续把这些资源展开为 Milvus 自定义资源,最终由 Operator 生成 Deployment、Service 和 ConfigMap 等 Kubernetes 对象。
升级或变配时,系统通常按组件更新声明式配置,再由 Kubernetes 执行滚动更新。
Operator rollout comparison
这个模式的好处是声明式、实现快、早期搭建成本低。只要声明正确,Kubernetes 理论上会帮你得到想要的状态。
但当我们开始严肃地维护线上服务时,这种模式的问题很快暴露出来。
第一个问题是有状态节点下线不可控。Pod 进入 Terminating 状态,并不代表它承载的数据和任务已经安全迁移。对于查询节点和流式节点,如果迁移没有在设计的退出窗口时间内内完成,节点最终可能被强制终止,从而对客户请求产生影响。
第二个问题是可观测性不足。管控系统可以看到某个组件无法继续滚动,或者新 Pod 无法启动,但很难直接判断问题发生在资源调度、数据迁移、节点接管还是数据库内部状态。故障排查通常需要跨多个团队逐层定位。
第三个问题是是配置维护成本不断上升。早期配置往往通过一个巨大的表格、数据库记录和动态 SQL 维护。随着规格、区域和版本增加,配置项越来越多。一次看似简单的参数调整,也可能需要同步修改多个环境,并承担配置遗漏和区域漂移的风险。
于是,这些问题推动了第一代精细化管控的建设。
第一代精细化管控:从 Operator 黑盒到可介入工作流
随着客户在生产环境中承载越来越多的数据和流量,扩缩容、升级和重启已经不能被视为普通的 Kubernetes 滚动更新。
对于有状态节点而言,真正重要的不是旧 Pod 是否被删除,而是它承载的数据和任务是否已经安全转移。原有模式把大部分过程交给 Operator 和 Deployment Controller,管控系统难以判断迁移进度,也难以在异常发生时及时介入。
而从用户价值方面来看,客户并不关心后台使用了多少个控制器,他们关心的是升级能否按预期完成、扩容是否影响查询,以及出现异常时服务是否仍然可用。
因此,2024 年 8 月左右,团队开始推动第一代精细化管控。它的目标,是把不可见、不可控的滚动更新,转变成可跟踪、可暂停、可恢复的生命周期操作,使生产变更更加稳定和可预测。
第一项改造,是把原来依赖 Operator 黑盒执行的流程拆成更细粒度的工作流。
新的工作流不再把整个过程完全交给 Kubernetes,而是将一次变配拆分成多个相对独立的步骤。
以查询节点升级为例,系统可以先调整数据库内部的调度状态,再启动新的节点;等待新节点完成数据加载和健康检查后,逐步迁移旧节点上的负载,最后再下线旧节点。
每个步骤只负责一类动作,并拥有独立的状态、超时和错误处理逻辑。
这样带来两个明显收益。
一是可观测性增强。工作流在哪一步失败,失败原因是什么,可以直接从步骤和告警中看到,不再只是看到“QN 滚不动”这种笼统状态。
二是可介入性增强。如果某一步数据加载失败或迁移异常,工作流可以停在对应环节,给运维和研发同学时间排查,而不是进入不可逆的 Terminating 流程,最终被强制杀掉。
第二项改造,是配置系统函数化。 将实例编排配置和数据库运行参数统一表达为可测试的代码逻辑。
配置函数根据实例规格、副本数量、隔离级别、服务计划和数据库版本等输入,生成最终的组件资源配置和运行参数。
相比表格,函数化配置在第一眼看上去不一定更加直观,但它更适合表达复杂条件和依赖关系。
原来需要在大量配置行中维护的组合关系,可以被收敛成一组可复用、可测试、可版本管理的规则。相同逻辑可以部署到不同区域,减少手工 SQL、表格同步和环境漂移带来的风险。
函数化配置也显著提升了问题排查能力。系统可以追踪某项配置是如何计算出来的,并通过自动化测试验证不同输入组合下的输出结果。
随着自动化工具和智能 Agent 被引入研发流程,代码化规则也更容易被分析、解释和验证。
经过这一阶段的建设,Zilliz Cloud 逐步具备了组件级、Pod 级和实例级的精细化生命周期管理能力。
第二代精细化管控:在线调度与成本优化
第一代精细化管控解决了“怎么安全下线一个 Pod”,但还没有解决“负载往哪里迁”和“调度影响多大”的问题。
于是,到了 2025 年上半年,随着实例和基础设施规模扩大,不同物理节点之间可能出现明显的资源水位差异:部分节点负载过高,存在资源争抢和驱逐风险;另一些节点利用率偏低,造成资源浪费。
在原有模式下,调整资源分布往往需要触发较大范围的实例变更,操作成本和影响面都比较高。
但在线调度能力对客户而言,意味着热点节点和资源竞争更容易被提前处理,扩缩容和日常维护的影响范围更小。平台资源利用率的提升,也为持续提供更具性价比的服务打下基础。
因此,第二代精细化管控基于第一代的工作流能力,进一步引入了在线调度能力。团队可以根据不同 Kubernetes 节点的水位,动态调整 Milvus Pod 的分布。
这带来了几个关键收益。
第一,可以把 Pod 更灵活地调度到不同物理节点上,提升整体资源利用率。
第二,可以降低运维操作的爆炸半径。比如某个配置实际上只被 MixCoord 使用,那么就只需要重启 MixCoord,不必重启 QueryNode、StreamingNode 和 Proxy。
第三,可以支撑大规模成本优化。第二代精细化管控完成后,团队对线上机器做了一次大规模整理。到 2025 年 6 月左右,海外 SaaS 几个主要 Region 的成本降低了 50% 以上。
这一阶段之后,管控系统一度进入相对稳定的状态。
第三代精细化管控:直连 K8s、多 Deployment 与蓝绿升级
前两代架构设计时,大多数实例规模相对有限。随着越来越多大型生产负载进入云平台,线上开始出现更高计算规格、多查询副本和高并发读写的实例。
在这些场景中,原有架构暴露出两个主要瓶颈。
一方面,资源操作链路仍然较长。同一份状态可能同时存在于多个控制层和自定义资源中,运维时需要不断校准多份元信息。
另一方面,多副本实例仍然共享部分 Kubernetes 资源边界。扩缩容和升级需要同时协调数据库元信息、管控状态和 Pod 状态,容易产生复杂的中间状态。
对于大型生产实例,升级时间越长,风险暴露窗口就越大。一次扩缩容如果持续较长时间,也会限制客户应对突发流量的能力。
因此,第三代管控的目标,是缩短操作链路、明确副本边界,并把数据准备过程与线上流量隔离,使大型实例也能够快速、稳定地完成升级和扩缩容。
这意味着管控架构正式与早期开源 Operator 模式切开。管控团队直接管理底层 K8s 资源,调用链路更短,操作更灵活,工具开发速度也更快。当然,这也对管控团队提出了更高要求:必须更深入理解各云、各 Region、各类 K8s 资源和网络行为。
第三代管控的另一个重要改造,是为每个查询副本建立独立资源边界。
一个数据库实例通常只有一份逻辑数据,但可以通过多个查询副本承载更高的查询流量。每个副本加载相同的数据,并共同对外提供服务。
在旧架构中,多个副本可能放在同一个 Deployment 中,副本隔离主要依赖内核逻辑。管控侧需要调用内核接口声明某个 Resource Group 需要多少个 QueryNode,内核再把对应数量的 QueryNode 逻辑分配进去。
这使扩缩容变得复杂。缩容时,平台不仅要调整 Pod 数量,还要同步更新数据库内部的资源组和副本状态。如果底层删除了不属于目标副本的节点,系统还需要再次触发数据迁移和重新平衡。
新架构为每个查询副本建立独立的 Kubernetes 工作负载单元。
在 Kubernetes 层面,每个副本都有清晰的资源边界。增加副本时,系统创建新的独立单元;删除副本时,只需要回收对应单元,不会影响其他副本。
StreamingNode 也获得了更好的隔离性,减少扩副本过程中不必要的任务接管和负载波动。
有了 RG 级多 Deployment 资源边界,再看蓝绿升级就更清楚了。传统滚动升级通常按节点串行执行:先拉起一个新节点,将旧节点上的数据和任务迁移过去,再下线旧节点,然后继续处理下一个节点。
对于小规模实例,这种方式相对简单。但在大型实例中,它存在两个问题。
第一,串行升级在大集群上天然很慢。一个 QueryNode 的迁移可能需要几分钟,如果是几百 CU 的大实例,整体升级时间会非常长。
第二,数据迁移和客户服务发生在同一个副本里。新节点一边加载旧节点迁移来的数据,一边继续承接客户读写流量。在客户流量很高时,新节点很容易被打满甚至打崩。
蓝绿升级解决了这个问题。
新的模式下,管控会先拉起一个全新的副本。这个新副本独立加载数据,加载过程中不承接客户流量,旧副本继续稳定提供服务。
当新副本完全就绪后,系统再逐步将新请求切换到新副本。旧副本继续处理已经进入的长尾请求,待请求排空后,再释放数据和底层资源。
这个过程有几个好处。
第一,数据加载不影响线上服务。新副本准备好之前,客户流量始终在旧副本上。
第二,故障排查窗口更宽。如果新节点因为配置、资源或版本问题无法稳定运行,系统可以保留旧副本继续服务,并在新副本接入流量前完成修复或回退。
第三,大型实例可以并行准备新资源,显著缩短整体升级和扩缩容时间(极端场景下耗时约为原来的八分之一)。随着新架构逐步推广,实例变配耗时和失败率都到明显改善,复杂场景中的收益更加突出。
尾声 下一阶段:把更多基础设施纳入生命周期管控
回顾这三代演进,可以看到 Zilliz Cloud 管控系统的关注点在不断下沉、不断扩大。
第一代解决的是:不要把复杂生命周期操作交给 Operator 黑盒,要让每一步可观测、可介入。
第二代解决的是:不要只能重启整个实例,要能按组件、按 Pod 精细调度,从而支撑资源优化和成本优化。
第三代解决的是:不要再被多层资源转发和元信息同步束缚,要让管控直接接近底层 Kubernetes 资源,同时支撑多副本、多 Deployment、蓝绿升级和大客户场景。
但这还不是终点。
未来,网络、权限、I/O 配置、机器配置,甚至 etcd 或后续 Catalog Service,都可能进一步纳入生命周期管控体系。随着产品走向更成熟的大规模 SaaS,管控系统需要覆盖的不只是 Milvus 业务组件本身,还包括它依赖的整个云基础设施。
这些问题都很难,但也正是云上产品走向成熟的必经之路。
从这个角度看,过去三年管控架构的演进,不只是一次次技术重构,而是 Zilliz Cloud 从“能托管 Milvus”走向“能稳定、精细、规模化地运营 Milvus”的过程。






