一、背景:高可用数据库集群部署的痛点
部署一套生产级的 PostgreSQL 高可用集群,需要协调多个组件:
- ETCD:分布式配置中心,存储集群元数据
- Patroni:高可用管理器,负责主备选举和故障切换
- He3DB内核:数据库本身,1主2备架构
- WAL-G:WAL 归档和备份恢复
- Keepalived:VIP 高可用,提供统一访问入口
这些组件之间存在复杂的依赖关系和启动顺序约束:
传统手工部署的痛点:
-
顺序复杂:先装 ETCD,等集群就绪,再装 Patroni,先启主库,等 Leader 选举,再启备库...
-
容错性差:中途任何一步出错,需要手动清理环境重来
-
效率低下:3 台机器串行操作,大量时间浪费在等待上
-
一致性难保证:手工操作难免遗漏或出错,导致配置不一致
二、设计理念一:幂等性优先
2.1 什么是幂等性?
幂等性(Idempotency):同一操作执行一次和执行多次,产生的效果相同,这是自动化部署工具最重要的设计原则。
“每个模块都应该是幂等的,运行一次部署模块和运行一百次,最终状态应该是一样的”
2.2 为什么幂等性如此重要?
考虑一个常见场景:部署进行到一半,网络抖动导致 SSH 断开。
非幂等设计:
- 不知道执行到哪一步了
- 重新执行可能导致重复操作(如重复创建用户、重复写入配置)
- 只能手动清理环境,从头开始
幂等设计:
- 每个步骤先检查目标状态
- 已完成的步骤自动跳过
- 可以安全地重复执行
- 支持断点续传
三、设计理念二:流水线编排
3.1 串行部署的效率问题
传统的部署方式是完全串行的,这种方式的问题显而易见:大量时间浪费在等待上。
3.2 全并行的正确性问题
那能不能所有操作都并行呢?不行。因为组件之间存在依赖:
- ETCD 集群必须先就绪,Patroni 才能启动
- Primary 必须先成为 Leader,Standby 才能加入集群
- 数据库必须就绪,Keepalived 才能开始健康检查
全并行会导致启动顺序混乱,引发各种竞态问题。
3.3 智能编排:依赖分析 + 混合调度
我们的解决方案是依赖分析 + 混合调度:
-
分析依赖关系:哪些步骤有依赖,哪些没有
-
无依赖步骤并行:最大化利用时间
-
有依赖步骤串行:保证正确的执行顺序
-
阶段同步点:在关键节点等待所有任务完成
核心思路: 整个部署流程被划分为5个阶段,每个阶段内部根据依赖关系决定执行策略:
- 阶段1-3: 各节点任务无相互依赖,可以完全并行执行,仅在阶段结束时设置同步点
- 阶段4: 存在强依赖关系,必须串行执行——Primary节点必须先成为Leader,Standby节点才能依次加入集群
- 阶段5: 全局验证,确保集群整体就绪
这种编排方式的关键在于:识别出哪些操作可以并行,哪些必须串行。通过依赖分析,我们将原本可能需要顺序执行的多个阶段改为并行,只在真正存在依赖的地方(如Leader选举)保持串行,从而在保证正确性的前提下最大化部署效率。
四、设计理念三:声明式配置
4.1 命令式 vs 声明式
命令式(Imperative):告诉系统"怎么做"
1. SSH 登录到 Node12. 下载 ETCD 安装包
2. 解压到 /usr/local/bin4. 创建配置文件
3. 启动服务
4. SSH 登录到 Node27. ...重复...
声明式(Declarative):告诉系统"我要什么"
集群配置:
节点:
- host: xxx.xxx.x.xxx, role: primary
- host: xxx.xxx.x.xxx, role: standby
- host: xxx.xxx.x.xxx, role: standby
组件:
- etcd: enabled
- patroni: enabled
- keepalived: enabled
4.2 声明式的优势
参考 Pigsty 的设计理念:
"用户只需要描述想要的最终状态,工具负责计算如何达到这个状态。"
声明式配置的好处:
-
意图清晰:配置文件就是文档
-
可重复:相同配置 = 相同结果
-
可审计:配置文件可以纳入版本控制
-
降低门槛:用户不需要了解具体执行步骤
4.3 配置驱动部署
我们的工具接收声明式配置,内部自动:
-
解析配置,生成部署计划
-
分析组件依赖,确定执行顺序
-
针对每个节点生成具体配置
-
按流水线编排执行
五、设计理念四:容错与自愈
5.1 部署失败的常见原因
-
网络问题:SSH 连接超时、包下载失败
-
资源问题:磁盘空间不足、内存不够
-
配置问题:端口冲突、权限不足
-
依赖问题:前置组件未就绪
5.2 容错策略
断点续传:
- 基于幂等性设计,失败后可以直接重新执行
- 已完成的步骤会被自动跳过(Check 阶段检测到已满足)
- 从失败的步骤继续,而非从头开始
自动重试:
- 网络抖动等临时性故障,自动重试 N 次
- 重试间隔指数退避,避免雪崩
状态回滚:
- 关键操作前保存状态快照
- 失败时可选择回滚到上一个稳定状态
优雅降级:
- 非关键组件失败不阻塞整体流程
- 例如:监控组件安装失败,数据库集群仍可正常运行
5.3 自愈能力
更进一步,工具可以具备自愈能力:
- 检测异常:定期检查集群状态
- 自动修复:发现配置漂移时自动修正
- 告警通知:无法自动修复时及时告警
这与 Kubernetes 的 Operator 模式类似:持续协调实际状态与期望状态。
六、总结
6.1 核心设计理念
- 幂等性优先
- 每个操作遵循 Check → Execute → Verify
- 支持安全重试和断点续传
- 功能检测而非文件检测
- 流水线编排
- 依赖分析,智能调度
- 无依赖并行,有依赖串行
- 声明式配置
- 用户描述"要什么",工具负责"怎么做"
- 配置即文档,可审计可复现
- 容错与自愈
- 断点续传,自动重试
- 状态回滚,优雅降级
- 持续协调,自动修复
6.2 价值总结