PostgreSQL 教程: 设置 Patroni 实现高可用

五月 7, 2026

摘要:在本教程中,我们将学习如何在 PostgreSQL 中设置 Patroni。

目录

Patroni 负责管理 PostgreSQL 服务,并提供节点管理与监控的命令行接口。

安装 Patroni

为方便操作,本文提供 Debian 系统的简化安装步骤,需在三台服务器上全部执行

首先配置 PostgreSQL 官方软件源(PGDG):

sudo apt install -y postgresql-common
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh

安装 PGDG 软件源中提供的 Patroni 版本。Debian、RedHat 系等支持平台均可直接安装,若无法安装则参考官方文档

sudo apt install -y patroni

执行完毕后,三台全新的虚拟机就已准备好进行配置。

简易配置 Patroni

Debian 版 Patroni 安装包自带pg_createconfig_patroni工具,可将 Patroni 模板转换为适配 Debian 系统的定制化配置文件。使用前需修改模板,将默认的 ZooKeeper 切换为 etcd,三台服务器均需执行

cat<<EOF|sudo tee /etc/patroni/dcs.yml
etcd3:
  host: 127.0.0.1:2379
EOF

注意:YAML 配置头需写etcd3而非etcd。Patroni 为兼容旧版本默认使用 etcd2,而 etcd3 的通信协议完全不同。

随后执行单条命令完成剩余配置:

sudo pg_createconfig_patroni 18 demo

该命令会在/etc/patroni配置目录下生成18-demo.yml文件,systemd 管理该集群、调用patronictl时均会使用此文件。

理解 Patroni 配置

即便配置文件已自动生成,理解各配置段的作用也至关重要,这能帮助其他平台用户在需要时手动配置 Patroni。

首先看分布式配置存储(DCS)核心配置段

scope: "18-demo"
namespace: "/postgresql-common/"
name: patroni-demo-1

etcd3:
  host: 127.0.0.1:2379

当 Patroni 写入 DCS 时,所有键都从namespace参数指定的路径开始。同样,由于一个 DCS 可能托管多个集群,因此该集群的键必须包含scope在键路径中。name参数指示 Patroni 应如何引用此特定节点。配置工具实际上会使用 DCS 来查看哪些名称已被保留,以便唯一标识每个虚拟机。请检查所有三个参数,确保它们正确无误。

接下来看下引导部分的配置(bootstrap)。该段确定了 Patroni 应该如何创建初始的 Postgres 集群、要使用的参数以及其他重要信息。这部分内容也相当长,所以我们来逐一查看:

bootstrap:
  method: pg_createcluster
  pg_createcluster:
    command: /usr/share/patroni/pg_createcluster_patroni

常规情况下 Patroni 使用pg_init创建集群,为适配 Debian 系统对 PostgreSQL 的目录组织规则,此处指定了专用命令,该配置仅出现在 Debian 系统。

接下来看下 DCS 部分配置(bootstrap.dcs)。该段参数会持久化存储在 DCS 层,对集群所有节点生效,初始化后仅能通过patronictl修改,建议初始配置时就设置妥当。

dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
    check_timeline: true
    primary_start_timeout: 300
    synchronous_mode: false

这些参数定义了 Patroni 如何与 DCS 层交互,以及如何管理某些 Postgres 功能。请记住,领导者令牌决定了哪个节点是主节点,因此ttl定义了租约的有效期、loop_wait控制了租约续订之间的等待时间,以及retry_timeout指定等待 DCS 响应的时间。

我们在此输出中包含了primary_start_timeout,是因为领导者竞争并非绝对的。如果 Patroni 将某个节点提升为主节点,或检测到 Postgres 发生故障,它会在此超时时间内强制执行故障转移。此超时时间为崩溃恢复提供宽限期,但您可能会发现默认的五分钟时间过长了。

这里另一个重要的参数是synchronous_mode,它告诉 Patroni 应该自动使用集群中其他节点的名称来管理 Postgres 配置synchronous_standby_names的设置。这就是在 Patroni 中启用同步复制的方法。

接下来是dcs下面的postgresql部分:

postgresql:
      use_pg_rewind: true
      remove_data_directory_on_rewind_failure: true
      remove_data_directory_on_diverged_timelines: true
      use_slots: true
      parameters:
        wal_level: hot_standby

本节定义了 Patroni 如何运行 Postgres 服务。前几个参数控制 Patroni 如何回收旧的主节点,例如尽可能使用pg_rewind工具,以及是否在万不得已的情况下删除数据目录。Patroni 默认使用复制槽来管理副本,以防止在故障情况下进行不必要的副本重建。

您还可以通过parameters部分将 GUC 设置直接传递给所有节点上的 Postgres。这对于提供可能与硬件无关的集群范围的重要设置非常有用,例如wal_levelmax_connectionshot_standby_feedback

dcs.postgresql段落下的最后一部分是pg_hba

pg_hba:
      - local   all             all                                     peer
      - host    all             all             127.0.0.1/32            md5
      - host    all             all             ::1/128                 md5
#      - host    all             all             192.168.8.20/16         md5
      - local   replication     all                                     peer
      - host    replication     all             127.0.0.1/32            md5
      - host    replication     all             ::1/128                 md5
      - host    replication     all             192.168.8.20/16         md5

在启动 Patroni 之前,您需要自定义该部分;Patroni 会使用该部分构建 pg_hba.conf 文件,该文件控制传入连接的访问权限。默认情况下,如果您取消注释禁用的行,则允许服务器子网上的连接;否则,仅允许本地访问。

接下来是另一个postgresql 部分,但这是一个顶级标题,用于告诉 Patroni 应该如何处理此特定服务器上的 Postgres。这些部分在 Patroni 的 YAML 配置设置 文档中有更详细的说明。

这个例子开头是一些 Debian 特有的内容:

postgresql:
  create_replica_method:
    - pg_clonecluster
  pg_clonecluster:
    command: /usr/share/patroni/pg_clonecluster_patroni

与之前一样,这样做是为了让 Debian 能够与其他打包的 Postgres 工具集成,因此在其他平台上可以安全地跳过这一步。之后是一些处理连接相关的参数:

listen: "*:5432"
  connect_address: 192.168.8.20:5432
  use_unix_socket: true

该示例有效地告诉 Patroni 如何连接到本地 Postgres 服务以执行管理操作。使用这些设置时,Patroni 会尽可能使用 Unix 套接字,这是合理的,因为 Patroni 以 postgres 操作系统用户身份运行,并拥有直接的套接字访问权限。

接下来是一个有趣的部分,其中定义了几种路径:

data_dir: /var/lib/postgresql/18/demo
  bin_dir: /usr/lib/postgresql/18/bin
  config_dir: /etc/postgresql/18/demo
  pgpass: /var/lib/postgresql/18-demo.pgpass

Patroni 知道它将被安装在几种不同的环境中,在这些环境中,Postgres 和配置目录可能在完全任意的位置。以上是运行在 Debian 系统上的 Postgres 18 的默认位置。

最后还有一个参数部分,用于设置仅适用于该特定的 Postgres 服务器的参数:

parameters:
    unix_socket_directories: '/var/run/postgresql/'
    logging_collector: 'on'
    log_directory: '/var/log/postgresql'
    log_filename: 'postgresql-18-demo.log'

这里的内容应该不会让人感到意外;它主要包括本地实例的日志存储以及 Unix 套接字目录的位置。这些配置在整个集群中很可能是通用的,但为了安全起见,最好将它们从 DCS 部分中移除。如果由于迁移到不同硬件或操作系统发行版而导致任何差异,您需要能够在本地更改这些配置。

总之,请花些时间检查每个节点上的/etc/patroni/18-demo.yml文件,抽查是否存在任何错误。

启动和验证 Patroni

Patroni 软件包提供了一个标准的 systemd 服务文件;只需在所有虚拟机上启用并启动该服务即可。

sudo systemctl enable patroni@18-demo
sudo systemctl start patroni@18-demo

三个节点中会有一个“赢得”领导者的竞争,成为集群的主节点。Patroni 随后会在该系统上调用pg_createcluster_patroni命令,在启动 Postgres 之前创建数据和配置目录。在其他节点上,Patroni 则会调用pg_clonecluster_patroni命令创建新的流式副本。如果您希望某个特定节点作为主节点启动,只需在该节点上启动 Patroni,等待其建立集群后,再在其他两个节点上启动该服务即可。

最终,三个系统都应该会生成一个新的“demo”数据库,该数据库可通过pg_lsclusters查看:

pg_lsclusters

Ver Cluster Port Status         Owner    Data directory              Log file
18  demo    5432 online,patroni postgres /var/lib/postgresql/18/demo /var/log/postgresql/postgresql-18-demo.log

下一步是检查 Patroni 集群本身的状态。您应该能够以postgres操作系统用户身份从任何节点运行此命令。虽然也可以使用root用户,但既然 Patroni 已经安装并正在管理集群,最好避免依赖 root 用户。

patronictl -c /etc/patroni/18-demo.yml list

+ Cluster: 18-demo (7606465692216410488) -+-----------+----+-------------+-----+------------+-----+
| Member         | Host         | Role    | State     | TL | Receive LSN | Lag | Replay LSN | Lag |
+----------------+--------------+---------+-----------+----+-------------+-----+------------+-----+
| patroni-demo-1 | 192.168.8.20 | Leader  | running   |  2 |             |     |            |     |
| patroni-demo-2 | 192.168.8.21 | Replica | streaming |  2 |   0/4000060 |   0 |  0/4000060 |   0 |
| patroni-demo-3 | 192.168.8.22 | Replica | streaming |  2 |   0/4000060 |   0 |  0/4000060 |   0 |
+----------------+--------------+---------+-----------+----+-------------+-----+------------+-----+

该输出表明集群运行状况良好,节点 1 为当前主节点,两个副本均在进行流式传输,且无复制延迟。成功!

编辑集群配置

最后一步可能需要修改存储在 DCS 层中的集群配置。这些配置包括用于引导集群初始状态的 Postgres 参数和 pg_hba.conf 条目,在早期阶段很容易出错。

再次使用patronictl,来编辑配置:

patronictl -c /etc/patroni/18-demo.yml edit-config

Patroni 会将当前的 DCS 配置加载到当前的默认编辑器中,在我们的例子中,它看起来像这样:

check_timeline: true
loop_wait: 10
maximum_lag_on_failover: 1048576
postgresql:
  parameters: null
  pg_hba:
  - local   all             all                                     peer
  - host    all             all             127.0.0.1/32            md5
  - host    all             all             ::1/128                 md5
  - host    all             all             192.168.8.20/16         md5
  - local   replication     all                                     peer
  - host    replication     all             127.0.0.1/32            md5
  - host    replication     all             ::1/128                 md5
  - host    replication     all             192.168.8.20/16         md5
  remove_data_directory_on_diverged_timelines: true
  remove_data_directory_on_rewind_failure: true
  use_pg_rewind: true
  use_slots: true
retry_timeout: 10
ttl: 30

利用这个机会修复任何缺失的 HBA 条目,或添加任何应该应用于所有节点的 Postgres 参数。例如,在postgresql.parameters下面添加wal_level设置以启用逻辑复制:

check_timeline: true
loop_wait: 10
maximum_lag_on_failover: 1048576
postgresql:
  parameters:
    wal_level: logical
  pg_hba:
  - local   all             all                                     peer
  - host    all             all             127.0.0.1/32            md5
  - host    all             all             ::1/128                 md5
  - host    all             all             192.168.8.20/16         md5
  - local   replication     all                                     peer
  - host    replication     all             127.0.0.1/32            md5
  - host    replication     all             ::1/128                 md5
  - host    replication     all             192.168.8.20/16         md5
  remove_data_directory_on_diverged_timelines: true
  remove_data_directory_on_rewind_failure: true
  use_pg_rewind: true
  use_slots: true
retry_timeout: 10
ttl: 30

由于更改wal_level参数需要重启 Postgres 服务,请使用patronictl命令重启集群中的节点:

patronictl -c /etc/patroni/18-demo.yml restart 18-demo --force

然后检查 Postgres 数据库,确认设置是否按预期更改。这是节点 3 的输出,即使是从节点 1 修改了 DCS 配置并重启了集群:

SHOW wal_level;
wal_level 
-----------
 logical

结语

Patroni 的搭建本身并不难,但要正确配置、了解每个部分的工作原理以及部署后如何持续修改集群,却是一个复杂的过程。不过,如果您一直按照教程操作,现在应该已经拥有一个可以正常运行的 Patroni 集群了。

Postgres 支持多主机连接字符串,在target_session_attr参数中指定read-write会将连接限制在主节点上。使用 psql 连接可能如下所示:

psql -d "user=postgres host=pg1,pg2,pg3 target_session_attrs=read-write"

了解更多

PostgreSQL 管理