必须先跑通Consul集群,Patroni才能写入leader锁和节点状态;否则patronictl list会报DCS不可访问而无法启动。Consul需健康直连,配置advertise_addr、ACL token、session_ttl等关键参数,并确保首次按Consul→Patroni顺序启动且清空PG数据目录。

必须先跑通 Consul 集群,Patroni 才能写入 leader 锁和节点状态;否则 patronictl list 会一直报 DCS is not accessible,根本起不来。
Consul 集群必须健康且可被 Patroni 直连
Patroni 不是“连上 Consul 就行”,它依赖 Consul 的 KV 存储和 session 机制做选主,所以 Consul 服务本身必须稳定、网络可达、ACL 权限正确:
- Consul server 节点数建议 ≥3(奇数),避免脑裂;单节点仅用于测试,
retry_timeout * 2 时极易误判失联 -
advertise_addr必须设为其他 Patroni 节点能访问的真实 IP,别用127.0.0.1或localhost;否则 Patroni 连得上但 Consul 内部 session 刷新失败 - 若 Consul 启用了 ACL,Patroni 启动时需提供有效 token:
PATRONI_CONSUL_TOKEN环境变量或配置中consul.token字段 - 验证方式:在 Patroni 节点执行
curl -s http://<consul-ip>:8500/v1/status/leader</consul-ip>应返回 IP;再试curl -s http://<consul-ip>:8500/v1/kv/?recurse</consul-ip>应返回空数组(非 403/401)
Patroni 配置里 Consul 相关字段不能只填 host:port
Consul 后端比 etcd 更依赖显式 session 控制,consul 段漏配关键参数会导致锁无法续期、节点反复 demote:
-
host和port是基础,但必须同时配token(如有 ACL)、scheme(http或https)、verify(HTTPS 场景下控制证书校验) -
session_ttl推荐设为30s,且要 ≥bootstrap.dcs.ttl(后者通常也设 30),否则 session 过期快于 leader 锁续租,触发假故障转移 -
url字段可替代host+port+scheme,例如http://192.168.5.10:8500,但一旦设了url,其他 host/port 参数会被忽略 - Consul 的
checks机制不被 Patroni 使用——Patroni 自己做健康检查,不要在 Consul 里额外注册 service check,否则干扰 leader 判断
postgresql.use_pg_rewind 和 tags.nofailover 是故障转移成败的关键开关
Consul 通了 ≠ 故障转移能成功。Patroni 在 promote 前会做安全校验,这两个布尔值错一个,就卡在 standby 状态不动:
-
postgresql.use_pg_rewind: true—— 必开。主库异常宕机后,备库 WAL 可能落后较多,pg_rewind是唯一安全回退数据目录的方式;关了它,Patroni 日志会直接打印refusing to initialize without pg_rewind -
tags.nofailover: false—— 所有参与选举的节点都必须设为false。哪怕只有一个节点设成true,当主库挂掉,整个集群就失去升主能力,patronictl list显示全部running但角色全是replica -
bootstrap.dcs.synchronous_mode: false(默认)适合大多数场景;设为true会强制同步复制,但要求至少一个 sync standby 在线,否则写操作阻塞——不是故障转移问题,但会影响可用性判断
启动顺序和首次初始化最容易出错
Consul 和 Patroni 的生命周期耦合紧密,顺序和残留状态直接影响集群是否能形成 leader:
- 严格顺序:启动所有 Consul server →
consul members确认 allalive→ 再逐台启 Patroni(不要并行 systemctl start) - 首次启动前,清空 PostgreSQL 数据目录:
rm -rf /var/lib/postgresql/*/main;Patroni 会自己 initdb,手动生成过 standby 会残留recovery.signal,导致启动报cluster has no members - 第一次
patronictl -c patroni.yml list出现空列表?立刻查 Patroni 日志里有没有Failed to get cluster from dcs或Connection refused—— 90% 是 Consul 地址/端口/ACL 配错,不是 Patroni 配置语法问题 - Consul 中 Patroni 写入的路径是
/service/<scope>/</scope>(如/service/postgres-ha/),可用consul kv get -recurse /service/postgres-ha/查看是否已有leader、members等 key
Consul 的 session 机制比 etcd lease 更隐晦,ttl 续期失败不会立即报错,而是等 session 过期后 Patroni 才发现 leader 锁丢失——这个延迟会让故障转移时间不可控。务必盯住 Patroni 日志里的 acquired session 和 renewed session 行,而不是只看 leader 字样。

















