两款数据库 Operator:从部署文档到声明式配置
问题
两款分布式数据库的部署原本靠一份很长的文档:几十个步骤,多个组件有严格的启动顺序,配置项之间有隐含约束(比如某个副本数必须和某个分片数匹配)。文档写得再细,人执行还是会错——错的地方还很分散,有人漏了一步,有人把顺序搞反,有人配置项填了个合法但不兼容的值。
更麻烦的是出错之后不好查。因为部署过程没有留下结构化的状态,只能靠翻日志倒推执行到哪一步、哪一步出了偏差。
做法
Operator 的核心价值不是「自动化部署」——脚本也能自动化。核心价值是把「期望状态」和「当前状态」都变成可查询的结构化数据,然后让控制循环去消除两者的差距。
把隐含约束写进 CRD 校验。 配置项之间的约束原来只存在于文档的注意事项里,现在写成 OpenAPI schema 校验和 admission 逻辑。填了不兼容的值会在提交时被拒绝,而不是部署到一半才崩。这一项对「出错率降低 80%」的贡献最大——大部分部署失败根本不是执行错误,是配置本身就不合法。
启动顺序交给状态机,不是交给 sleep。 脚本化部署里常见的做法是「启动 A,睡 30 秒,启动 B」。这在慢环境里会失败,在快环境里会浪费时间。Operator 里改成显式的阶段状态:A 真正就绪了才推进到 B,就绪的判定是查询 A 的实际状态而不是等时间。
状态可查询。 CR 的 status 字段暴露当前处于哪个阶段、每个组件的健康状况、上一次协调的结果和错误。查问题从「翻日志倒推」变成 kubectl get 一眼看到。
关于 OperatorHub.io Level 3
Operator 的成熟度分五级。Level 1 是能装,Level 2 是能升级,Level 3 是要支持完整的生命周期——备份、恢复、故障转移、灾难恢复。
做到 Level 3 的过程里,最难的不是实现这些操作,而是处理它们的中断和并发。备份进行到一半 Operator 重启了怎么办?扩容和升级同时被触发怎么办?Kubernetes 的控制循环是幂等重入的,这意味着每一个多步骤操作都必须能从任意中断点安全恢复——不能假设「我上次执行到哪里」,只能每次都从实际状态重新推导下一步该做什么。
这个约束一开始很别扭,习惯之后会发现它是对的:它强迫你把状态外化,而外化的状态正好就是可观测性。
结果
- 部署出错率降低 80%,绝大部分来自配置校验前移。
- 交付效率提升 50%,来自不再需要人守着执行、也不再需要出错后重来。
- 通过 OperatorHub.io Level 3 认证,两款数据库可以被标准化地纳管。
事后看,值得记下来的
能在提交时拒绝的错误,不要等到运行时才发现。 校验前移的收益远超它的实现成本,但它经常被排在「先把主流程跑通」之后,然后就一直排在后面。
幂等不是一个可选的工程美德,是分布式系统的入场券。 写 Operator 之前我对幂等的理解停留在「重复执行结果一样」;写完之后的理解是「不许依赖任何关于历史执行的记忆」。这是两个强度差很远的要求。
声明式的真正好处是可对账。 命令式脚本执行完就没了,你无法回答「现在的状态和期望一致吗」。声明式配置让这个问题随时可答——这比省下的那些人工操作时间更有价值。