PostgreSQL本身通过流复制支持一主多备,但原生机制缺少自动故障检测和主库切换能力。Patroni是一个用Python编写的模板化高可用管理工具,它在流复制基础上引入分布式协调组件,持续监控节点健康并自动完成主备角色调整。部署Patroni并不是简单安装一个软件,而是要把数据库、协调服务和守护进程三者组合成可自愈的集群。

环境规划与基础依赖安装
在开始部署之前,需要明确集群的节点数量与网络拓扑。通常一个稳妥的Patroni集群至少包含三个物理机或虚拟机,分别运行一个PostgreSQL实例和一个etcd成员。etcd负责存储集群元数据,采用奇数节点以避免选主平票。如果只有两台数据库服务器,可以将etcd独立部署在第三台轻量机器上,或者借用已有的etcd集群。
操作系统层面要统一关闭防火墙对所需端口的限制,PostgreSQL默认使用5432,etcd使用2379和2380,Patroni的REST API默认8008。同时所有节点必须配置互相解析的主机名或固定IP,时间同步服务NTP也要正常工作,因为etcd对时钟偏移非常敏感。依赖包方面,各节点需安装相同大版本的PostgreSQL服务器包,以及Python3和pip,随后通过pip安装patroni和patroni[etcd]额外组件。
创建专用的系统用户能提升安全性。建议建立名为postgres的系统账户,家目录指向数据盘,Patroni进程也以该账户运行。数据目录权限必须严格限制为700,且属主为postgres。很多部署失败案例都源于用root初始化数据库后又未修正目录权限,导致Patroni拉起PostgreSQL时被拒绝访问。
etcd协调服务搭建与校验
etcd是Patroni最常用的分布式配置存储(DCS)。在每个etcd节点上,需要编写单元配置文件指定名称、监听地址和集群初始状态。以下示例展示了一个三节点etcd的核心配置片段,实际部署时要把节点IP替换为真实地址,并保证initial-cluster参数覆盖全部成员。
# etcd.conf.yml 示例 name: etcd1 data-dir: /var/lib/etcd listen-client-urls: http://192.168.0.1:2379 advertise-client-urls: http://192.168.0.1:2379 listen-peer-urls: http://192.168.0.1:2380 initial-advertise-peer-urls: http://192.168.0.1:2380 initial-cluster: etcd1=http://192.168.0.1:2380,etcd2=http://192.168.0.2:2380,etcd3=http://192.168.0.3:2380 initial-cluster-token: patroni-cluster initial-cluster-state: new
启动etcd后,应使用etcdctl检查集群健康。执行etcdctl endpoint health能看到每个节点返回is healthy。Patroni并不直接连接数据库 peer,而是把主库锁、配置和领袖键值写入etcd。若etcd出现脑裂或数据目录损坏,Patroni会误判集群状态,因此etcd自身的备份与监控不可省略。
对于不想自建etcd的团队,Patroni也支持Consul、ZooKeeper或Kubernetes API作为DCS。但无论选哪种,延迟和可用性都直接影响故障切换速度。在跨机房场景中,把DCS放在多数派机房,数据库备库放在少数派机房,能在网络分区时优先保主库可用,避免双主写入。
Patroni配置文件与集群引导
Patroni的主配置文件通常采用YAML格式,涵盖scope、namespace、DCS连接、restapi、bootstrap和postgresql几个核心段。scope定义集群名,namespace对应DCS中的目录前缀。restapi段要设置监听地址和认证,防止未授权调用切换接口。以下配置展示了单节点初始化时的关键字段,其中bootstrap段告诉Patroni首次启动时如何创建主库。
scope: pg_cluster
namespace: /service/
name: pg1
restapi:
listen: 192.168.0.1:8008
connect_address: 192.168.0.1:8008
authentication:
username: patroni
password: strong_pass
etcd:
hosts:
- 192.168.0.1:2379
- 192.168.0.2:2379
- 192.168.0.3:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
initdb:
- encoding: UTF8
- locale: C
postgresql:
listen: 192.168.0.1:5432
connect_address: 192.168.0.1:5432
data_dir: /data/pgdata
authentication:
replication:
username: replicator
password: repl_pass
superuser:
username: postgres
password: pg_pass
在第一个节点上启动patroni后,它会自动初始化数据目录、生成postgresql.conf并拉起主库,然后在etcd中注册自己为leader。第二、第三个节点使用同样的配置但修改name和IP,启动后Patroni会识别出已有集群,自动以pg_basebackup方式从主库克隆数据并成为备库。整个过程无需手工执行备份还原,极大降低人为出错概率。
集群运行后,可通过curl访问任意节点的8008端口查看状态,例如curl http://192.168.0.1:8008/patroni返回JSON描述角色与 timelines。当主库进程被kill,Patroni在loop_wait加ttl周期内检测不到心跳,便由备库中选举延迟最小的节点提升为新主。应用端配合HAProxy或智能驱动连接,即可实现连接层对切换无感知。
watchdog与常见故障处理
Linux硬件看门狗(watchdog)能解决极端情况下的脑裂。Patroni支持在无法访问DCS时主动触发重启,防止旧主库在网络隔离后继续接受写入。配置中需设置watchdog段并加载内核模块softdog,同时Patroni要以足够权限打开/dev/watchdog。若环境不支持硬件看门狗,至少应开启软件层面的自动降级策略。
实践中常见的问题是最大滞后参数设置过低,导致备库稍有延迟就被判定不可选主,反而延长恢复时间。应根据业务峰值写入量调整maximum_lag_on_failover。另外,PostgreSQL的postgresql.conf中某些参数会被Patroni接管,手工修改后可能被覆盖,正确做法是在Patroni配置的postgresql.parameters下声明,由Patroni统一下发。
日志是排查Patroni行为的主要依据。每个节点的patroni.log会记录选主、克隆和健康检查细节。当切换异常时,优先比对各节点日志中的DCS读写错误与系统资源占用,多数故障都能归因于etcd不可达或磁盘IO饱和。建立集中式日志收集后,运维人员可在切换发生数秒内定位根因。
PostgreSQLPatroni高可用修改时间:2026-08-16 17:36:41