这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

集群配置

根据需求场景选择合适的实例与集群类型,配置出满足需求的 PostgreSQL 数据库集群。

Pigsty 是一个“配置驱动”的 PostgreSQL 平台:所有行为都来自 ~/pigsty/conf/*.yml 清单与 PGSQL 参数 的组合。 只要写好配置,你就能在几分钟内复刻出一套包含实例、用户、数据库、访问控制、扩展与调优策略的定制集群。


配置入口

  1. 准备清单:复制 pigsty/conf/*.yml 模板或从零开始编写 Ansible Inventory,将集群分组(all.children.<cls>.hosts)与全局变量(all.vars)写入同一个文件。
  2. 定义参数:在 vars 区块中覆盖需要的 PGSQL 参数。全局 → 集群 → 主机的覆盖顺序决定了最终值。
  3. 应用配置:运行 ./configure -c <conf>bin/pgsql-add <cls> 等剧本让配置落地。Pigsty 会根据参数生成 Patroni/pgbouncer/pgbackrest 等服务所需的配置文件。

Pigsty 默认的 Demo 清单 conf/pgsql.yml 就是一份最小化示例:一个 pg-meta 集群、全局 pg_version: 18、少量业务用户与数据库定义。你可以在此基础上扩展更多集群。


关注点与文档索引

Pigsty 的 PostgreSQL 配置可以从以下几个维度组合,后续文档会逐一展开“如何配置”:

  • 集群实例:通过 pg_cluster / pg_role / pg_seq / pg_upstream 定义实例拓扑(单机、主从、备份集群、延迟集群、Citus 等)。
  • 内核版本:使用 pg_versionpg_modepg_packagespg_extensionspg_conf 等参数挑选核心版本、风味和调优模板。
  • 用户/角色:在 pg_default_rolespg_users 中声明系统角色、业务账号、密码策略以及连接池属性。
  • 数据库对象:借助 pg_databasesbaselineschemasextensionspool_* 字段按需创建数据库并自动接入 pgbouncer/Grafana。
  • 访问控制 (HBA):利用 pg_default_hba_rulespg_hba_rules 维护主机级认证策略,保证不同角色/网络的访问边界。
  • 权限模型 (ACL):通过 pg_default_privilegespg_default_rolespg_revoke_public 等参数收敛对象权限,开箱即用地提供分层角色体系。

理解这些参数之后,你就可以针对任意业务需求写出“配置即基础设施”的声明式清单,Pigsty 会负责执行并确保幂等。


一个典型示例

下面的片段展示了如何在同一个配置文件中同时控制实例拓扑、内核版本、扩展、用户以及数据库:

all:
  children:
    pg-analytics:
      hosts:
        10.10.10.11: { pg_seq: 1, pg_role: primary }
        10.10.10.12: { pg_seq: 2, pg_role: replica, pg_offline_query: true }
      vars:
        pg_cluster: pg-analytics
        pg_conf: olap.yml
        pg_extensions: [ postgis, timescaledb, pgvector ]
        pg_databases:
          - { name: bi, owner: dbuser_bi, schemas: [mart], extensions: [timescaledb], pool_mode: session }
        pg_users:
          - { name: dbuser_bi, password: DBUser.BI, roles: [dbrole_admin], pgbouncer: true }
  vars:
    pg_version: 17
    pg_packages: [ pgsql-main pgsql-common ]
    pg_hba_rules:
      - { user: dbuser_bi, db: bi, addr: intra, auth: ssl, title: 'BI 只允许内网 SSL 访问' }
  • pg-analytics 集群包含一个主库和一个离线副本。
  • 全局指定 pg_version: 17 与一套扩展示例,并加载 olap.yml 调优。
  • pg_databasespg_users 中声明业务对象,自动生成 schema/extension 与连接池条目。
  • 附加的 pg_hba_rules 限制了访问来源与认证方式。

修改并应用这份清单即可得到一套定制化的 PostgreSQL 集群,而无需手工逐项配置。

1 - 集群实例

根据需求场景选择合适的实例与集群类型,配置出满足需求的 PostgreSQL 数据库集群。

根据需求场景选择合适的实例与集群类型,配置出满足需求的 PostgreSQL 数据库集群。

您可以定义不同类型的实例和集群,下面是 Pigsty 中常见的几种 PostgreSQL 实例/集群类型:


读写主库

我们从最简单的情况开始:由一个主库(Primary)组成的单实例集群:

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-test

这段配置言简意赅,自我描述,仅由 身份参数 构成,请注意 Ansible Group 分组名应当与 pg_cluster 保持一致。

使用以下命令创建该集群:

bin/pgsql-add pg-test

Demo展示,开发测试,承载临时需求,进行无关紧要的计算分析任务时,使用单一数据库实例可能并没有太大问题。但这样的单机集群没有高可用,当出现硬件故障时,您需要使用 PITR 或其他恢复手段来确保集群的 RTO / RPO。为此,您可以考虑为集群添加若干个只读从库


只读从库

要添加一台只读从库(Replica)实例,您可以在 pg-test 中添加一个新节点,并将其 pg_role 设置为replica

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }  # <--- 新添加的从库
  vars:
    pg_cluster: pg-test

如果整个集群不存在,您可以直接创建这个完整的集群。 如果集群主库已经初始化好了,那么您可以向现有集群添加一个从库:

bin/pgsql-add pg-test               # 一次性初始化整个集群
bin/pgsql-add pg-test 10.10.10.12   # 添加从库到现有的集群

当集群主库出现故障时,只读实例(Replica)可以在高可用系统的帮助下接管主库的工作。除此之外,只读实例还可以用于执行只读查询:许多业务的读请求要比写请求多很多,而大部分只读查询负载都可以由从库实例承担。


离线从库

离线实例(Offline)是专门用于服务慢查询、ETL、OLAP流量和交互式查询等的专用只读从库。慢查询/长事务对在线业务的性能与稳定性有不利影响,因此最好将它们与在线业务隔离开来。

要添加离线实例,请为其分配一个新实例,并将pg_role设置为offline

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
    10.10.10.13: { pg_seq: 3, pg_role: offline }  # <--- 新添加的离线从库
  vars:
    pg_cluster: pg-test

专用离线实例的工作方式与常见的从库实例类似,但它在 pg-test-replica 服务中用作备份服务器。 也就是说,只有当所有replica实例都宕机时,离线和主实例才会提供此项只读服务。

许多情况下,数据库资源有限,单独使用一台服务器作为离线实例是不经济的做法。作为折中,您可以选择一台现有的从库实例,打上 pg_offline_query 标记,将其标记为一台可以承载“离线查询”的实例。在这种情况下,这台只读从库会同时承担在线只读请求与离线类查询。您可以使用 pg_default_hba_rulespg_hba_rules 对离线实例进行额外的访问控制。


同步备库

当启用同步备库(Sync Standby)时,PostgreSQL 将选择一个从库作为同步备库,其他所有从库作为候选者。 主数据库会等待备库实例刷新到磁盘,然后才确认提交,备库实例始终拥有最新的数据,没有复制延迟,主从切换至同步备库不会有数据丢失。

PostgreSQL 默认使用异步流复制,这可能会有小的复制延迟(10KB / 10ms 数量级)。当主库失败时,可能会有一个小的数据丢失窗口(可以使用pg_rpo来控制),但对于大多数场景来说,这是可以接受的。

但在某些关键场景中(例如,金融交易),数据丢失是完全不可接受的,或者,读取复制延迟是不可接受的。在这种情况下,您可以使用同步提交来解决这个问题。 要启用同步备库模式,您可以简单地使用pg_conf中的crit.yml模板。

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
    10.10.10.13: { pg_seq: 3, pg_role: replica }
  vars:
    pg_cluster: pg-test
    pg_conf: crit.yml   # <--- 使用 crit 模板

要在现有集群上启用同步备库,请配置集群并启用 synchronous_mode

$ pg edit-config pg-test    # 在管理员节点以管理员用户身份运行
+++
-synchronous_mode: false    # <--- 旧值
+synchronous_mode: true     # <--- 新值
 synchronous_mode_strict: false

应用这些更改?[y/N]: y

在这种情况下,PostgreSQL 配置项 synchronous_standby_names 由 Patroni 自动管理。 一台从库将被选拔为同步从库,它的 application_name 将被写入 PostgreSQL 主库配置文件中并应用生效。


法定人数提交

法定人数提交(Quorum Commit)提供了比同步备库更强大的控制能力:特别是当您有多个从库时,您可以设定提交成功的标准,实现更高/更低的一致性级别(以及可用性之间的权衡)。

如果想要最少两个从库来确认提交,可以通过 Patroni 配置集群,调整参数 synchronous_node_count 并应用生效

synchronous_mode: true          # 确保同步提交已经启用
synchronous_node_count: 2       # 指定“至少”有多少个从库提交成功,才算提交成功

如果你想要使用更多的同步从库,修改 synchronous_node_count 的取值即可。当集群的规模发生变化时,您应当确保这里的配置仍然是有效的,以避免服务不可用。

在这种情况下,PostgreSQL 配置项 synchronous_standby_names 由 Patroni 自动管理。

synchronous_standby_names = '2 ("pg-test-3","pg-test-2")'
示例:使用多个同步从库
$ pg edit-config pg-test
---
+synchronous_node_count: 2

Apply these changes? [y/N]: y

应用配置后,出现两个同步备库。

+ Cluster: pg-test (7080814403632534854) +---------+----+-----------+-----------------+
| Member    | Host        | Role         | State   | TL | Lag in MB | Tags            |
+-----------+-------------+--------------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.10 | Leader       | running |  1 |           | clonefrom: true |
| pg-test-2 | 10.10.10.11 | Sync Standby | running |  1 |         0 | clonefrom: true |
| pg-test-3 | 10.10.10.12 | Sync Standby | running |  1 |         0 | clonefrom: true |
+-----------+-------------+--------------+---------+----+-----------+-----------------+

另一种情景是,使用 任意n个 从库来确认提交。在这种情况下,配置的方式略有不同,例如,假设我们只需要任意一个从库确认提交:

synchronous_mode: quorum        # 使用法定人数提交
postgresql:
  parameters:                   # 修改 PostgreSQL 的配置参数 synchronous_standby_names ,使用 `ANY n ()` 语法
    synchronous_standby_names: 'ANY 1 (*)'  # 你可以指定具体的从库列表,或直接使用 * 通配所有从库。
示例:启用ANY法定人数提交
$ pg edit-config pg-test

+    synchronous_standby_names: 'ANY 1 (*)' # 在 ANY 模式下,需要使用此参数
- synchronous_node_count: 2  # 在 ANY 模式下, 不需要使用此参数

Apply these changes? [y/N]: y

应用后,配置生效,所有备库在 Patroni 中变为普通的 replica。但是在 pg_stat_replication 中可以看到 sync_state 会变为 quorum


备份集群

您可以克隆现有的集群,并创建一个备份集群(Standby Cluster),用于数据迁移、水平拆分、多区域部署,或灾难恢复。

在正常情况下,备份集群将追随上游集群并保持内容同步,您可以将备份集群提升,作为真正地独立集群。

备份集群的定义方式与正常集群的定义基本相同,除了在主库上额外定义了 pg_upstream 参数,备份集群的主库被称为 备份集群领导者 (Standby Leader)。

例如,下面定义了一个pg-test集群,以及其备份集群pg-test2,其配置清单可能如下所示:

# pg-test 是原始集群
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars: { pg_cluster: pg-test }

# pg-test2 是 pg-test 的备份集群
pg-test2:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary , pg_upstream: 10.10.10.11 } # <--- pg_upstream 在这里定义
    10.10.10.13: { pg_seq: 2, pg_role: replica }
  vars: { pg_cluster: pg-test2 }

pg-test2 集群的主节点 pg-test2-1 将是 pg-test 的下游从库,并在pg-test2集群中充当备份集群领导者(Standby Leader)。

只需确保备份集群的主节点上配置了pg_upstream参数,以便自动从原始上游拉取备份。

bin/pgsql-add pg-test     # 创建原始集群
bin/pgsql-add pg-test2    # 创建备份集群
示例:更改复制上游

如有必要(例如,上游发生主从切换/故障转移),您可以通过配置集群更改备份集群的复制上游。

要这样做,只需将standby_cluster.host更改为新的上游IP地址并应用。

$ pg edit-config pg-test2

 standby_cluster:
   create_replica_methods:
   - basebackup
-  host: 10.10.10.13     # <--- 旧的上游
+  host: 10.10.10.12     # <--- 新的上游
   port: 5432

 Apply these changes? [y/N]: y
示例:提升备份集群

你可以随时将备份集群提升为独立集群,这样该集群就可以独立承载写入请求,并与原集群分叉。

为此,你必须配置该集群并完全擦除standby_cluster部分,然后应用。

$ pg edit-config pg-test2
-standby_cluster:
-  create_replica_methods:
-  - basebackup
-  host: 10.10.10.11
-  port: 5432

Apply these changes? [y/N]: y
示例:级联复制

如果您在一台从库上指定了 pg_upstream,而不是主库。那么可以配置集群的 级联复制(Cascade Replication)

在配置级联复制时,您必须使用集群中某一个实例的IP地址作为参数的值,否则初始化会报错。该从库从特定的实例进行流复制,而不是主库。

这台充当 WAL 中继器的实例被称为 桥接实例(Bridge Instance)。使用桥接实例可以分担主库发送 WAL 的负担,当您有几十台从库时,使用桥接实例级联复制是一个不错的注意。

pg-test:
  hosts: # pg-test-1 ---> pg-test-2 ---> pg-test-3
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica } # <--- 桥接实例
    10.10.10.13: { pg_seq: 3, pg_role: replica, pg_upstream: 10.10.10.12 }
    # ^--- 从 pg-test-2 (桥接)复制,而不是从 pg-test-1 (主节点) 
  vars: { pg_cluster: pg-test }

延迟集群

延迟集群(Delayed Cluster)是一种特殊类型的备份集群,用于尽快恢复“意外删除”的数据。

例如,如果你希望有一个名为 pg-testdelay 的集群,其数据内容与一小时前的 pg-test 集群相同:

# pg-test 是原始集群
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars: { pg_cluster: pg-test }

# pg-testdelay 是 pg-test 的延迟集群
pg-testdelay:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary , pg_upstream: 10.10.10.11, pg_delay: 1d }
    10.10.10.13: { pg_seq: 2, pg_role: replica }
  vars: { pg_cluster: pg-testdelay }

你还可以在现有的备份集群配置一个“复制延迟”。

$ pg edit-config pg-testdelay
 standby_cluster:
   create_replica_methods:
   - basebackup
   host: 10.10.10.11
   port: 5432
+  recovery_min_apply_delay: 1h    # <--- 在此处添加延迟时长,例如1小时

Apply these changes? [y/N]: y

当某些元组和表格被意外删除时,你可以通过修改此参数的方式,将此延迟集群推进到适当的时间点,并从中读取数据,快速修复原始集群。

延迟集群需要额外的资源,但比起 PITR 要快得多,并且对系统的影响也小得多,对于非常关键的集群,可以考虑搭建延迟集群。


Citus集群

Pigsty 原生支持 Citus。可以参考 files/pigsty/citus.ymlprod.yml 作为样例。

要定义一个 citus 集群,您需要指定以下参数:

此外,还需要额外的 hba 规则,允许从本地和其他数据节点进行 SSL 访问。如下所示:

all:
  children:
    pg-citus0: # citus 0号分片
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus0 , pg_group: 0 }
    pg-citus1: # citus 1号分片
      hosts: { 10.10.10.11: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus1 , pg_group: 1 }
    pg-citus2: # citus 2号分片
      hosts: { 10.10.10.12: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus2 , pg_group: 2 }
    pg-citus3: # citus 3号分片
      hosts:
        10.10.10.13: { pg_seq: 1, pg_role: primary }
        10.10.10.14: { pg_seq: 2, pg_role: replica }
      vars: { pg_cluster: pg-citus3 , pg_group: 3 }
  vars:                               # 所有 Citus 集群的全局参数
    pg_mode: citus                    # pgsql 集群模式需要设置为: citus
    pg_shard: pg-citus                # citus 水平分片名称: pg-citus
    pg_primary_db: meta               # citus 数据库名称:meta
    pg_dbsu_password: DBUser.Postgres # 如果使用 dbsu ,那么需要为其配置一个密码
    pg_users: [ { name: dbuser_meta ,password: DBUser.Meta ,pgbouncer: true ,roles: [ dbrole_admin ] } ]
    pg_databases: [ { name: meta ,extensions: [ { name: citus }, { name: postgis }, { name: timescaledb } ] } ]
    pg_hba_rules:
      - { user: 'all' ,db: all  ,addr: 127.0.0.1/32 ,auth: ssl ,title: 'all user ssl access from localhost' }
      - { user: 'all' ,db: all  ,addr: intra        ,auth: ssl ,title: 'all user ssl access from intranet'  }

在协调者节点上,您可以创建分布式表和引用表,并从任何数据节点查询它们。从 11.2 开始,任何 Citus 数据库节点都可以扮演协调者的角色了。

SELECT create_distributed_table('pgbench_accounts', 'aid'); SELECT truncate_local_data_after_distributing_table($$public.pgbench_accounts$$);
SELECT create_reference_table('pgbench_branches')         ; SELECT truncate_local_data_after_distributing_table($$public.pgbench_branches$$);
SELECT create_reference_table('pgbench_history')          ; SELECT truncate_local_data_after_distributing_table($$public.pgbench_history$$);
SELECT create_reference_table('pgbench_tellers')          ; SELECT truncate_local_data_after_distributing_table($$public.pgbench_tellers$$);

2 - 内核版本

如何选择合适的 PostgreSQL 内核与大版本。

在 Pigsty 中选择"内核"意味着确定 PostgreSQL 大版本、模式/发行版、需要安装的包以及要加载的调优模板。

Pigsty 从 PostgreSQL 10 起提供支持,当前版本默认打包了 13 - 18 的核心软件,并在 17/18 上提供完整扩展集合。下方内容展示如何通过配置文件完成这些选择。


大版本与软件包

  • pg_version:指定 PostgreSQL 主版本(默认 18)。Pigsty 会根据版本自动映射到正确的包名前缀。
  • pg_packages:定义需要安装的核心包集合,支持使用包别名(默认 pgsql-main pgsql-common,包含内核 + patroni/pgbouncer/pgbackrest 等常用工具)。
  • pg_extensions:额外需要安装的扩展包列表,同样支持别名;缺省为空表示只装核心依赖。
all:
  vars:
    pg_version: 17
    pg_packages: [ pgsql-main pgsql-common ]
    pg_extensions: [ postgis, timescaledb, pgvector, pgml ]

效果:Ansible 在安装阶段会拉取与 pg_version=17 对应的包,将扩展预装到系统中,随后数据库初始化脚本即可直接 CREATE EXTENSION

Pigsty 的离线仓库中不同版本的扩展支持范围不同:12/13 只提供核心与一级扩展,15/17/18 则涵盖全部扩展。若某扩展未预打包,可通过 repo_packages_extra 追加。


内核模式(pg_mode)

pg_mode 控制要部署的内核“风味”,默认 pgsql 表示标准 PostgreSQL。Pigsty 目前支持以下模式:

模式场景
pgsql标准 PostgreSQL,高可用 + 复制
citusCitus 分布式集群,需要额外的 pg_shard / pg_group
gpsqlGreenplum / MatrixDB
mssqlBabelfish for PostgreSQL
mysqlOpenGauss/HaloDB 兼容 MySQL 协议
polar阿里 PolarDB(基于 pg polar 发行)
ivoryIvorySQL(Oracle 兼容语法)
orioleOrioleDB 存储引擎
oraclePostgreSQL + ora 兼容(pg_mode: oracle

选择模式后,Pigsty 会自动加载对应的模板、依赖包与 Patroni 配置。以部署 Citus 为例:

all:
  children:
    pg-citus0:
      hosts: { 10.10.10.11: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus0, pg_group: 0 }
    pg-citus1:
      hosts: { 10.10.10.12: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus1, pg_group: 1 }
  vars:
    pg_mode: citus
    pg_shard: pg-citus
    patroni_citus_db: meta

效果:所有成员会安装 Citus 相关包,Patroni 以分片模式写入 etcd,并自动在 meta 数据库内 CREATE EXTENSION citus


扩展与预置对象

除了系统包,你还可以通过以下参数控制数据库启动后自动加载的组件:

  • pg_libs:写入 shared_preload_libraries 的列表。例如 pg_libs: 'timescaledb, pg_stat_statements, auto_explain'
  • pg_default_extensions / pg_default_schemas:控制初始化脚本对 template1postgres 预创建的 schema、扩展。
  • pg_parameters:为所有实例附加 ALTER SYSTEM SET(写入 postgresql.auto.conf)。

示例:启用 TimescaleDB、pgvector 并自定义一些系统参数。

pg-analytics:
  vars:
    pg_cluster: pg-analytics
    pg_libs: 'timescaledb, pg_stat_statements, pgml'
    pg_default_extensions:
      - { name: timescaledb }
      - { name: pgvector }
    pg_parameters:
      timescaledb.max_background_workers: 8
      shared_preload_libraries: "'timescaledb,pg_stat_statements,pgml'"

效果:初始化时 template1 会创建扩展、Patroni 的 postgresql.conf 注入对应参数,所有业务库继承这些设置。


调优模板 (pg_conf)

pg_conf 指向 roles/pgsql/templates/*.yml 中的 Patroni 模板。Pigsty内置四套通用模板:

模板适用场景
oltp.yml默认模板,面向 4–128 核的 TP 负载
olap.yml针对分析场景优化
crit.yml强调同步提交/最小延迟,适合金融等零丢失场景
tiny.yml轻量机 / 边缘场景 / 资源受限环境

你可以直接替换模板或自定义一个 YAML 文件放在 templates/ 下,然后在集群 vars 里指定。

pg-ledger:
  hosts: { 10.10.10.21: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-ledger
    pg_conf: crit.yml
    pg_parameters:
      synchronous_commit: 'remote_apply'
      max_wal_senders: 16
      wal_keep_size: '2GB'

效果:拷贝 crit.yml 作为 Patroni 配置,叠加 pg_parameters 写入 postgresql.auto.conf,使实例立即以同步提交模式运行。


组合实例:一个完整示例

pg-rag:
  hosts:
    10.10.10.31: { pg_seq: 1, pg_role: primary }
    10.10.10.32: { pg_seq: 2, pg_role: replica }
  vars:
    pg_cluster: pg-rag
    pg_version: 18
    pg_mode: pgsql
    pg_conf: olap.yml
    pg_packages: [ pgsql-main pgsql-common ]
    pg_extensions: [ pgvector, pgml, postgis ]
    pg_libs: 'pg_stat_statements, pgvector, pgml'
    pg_parameters:
      max_parallel_workers: 8
      shared_buffers: '32GB'
  • 第一台主库 + 一台 replica,使用 olap.yml 调优。
  • 安装 PG18 + RAG 常用扩展,自动在系统级加载 pgvector/pgml
  • Patroni/pgbouncer/pgbackrest 由 Pigsty 生成,无需手工干预。

根据业务需要替换上述参数即可完成内核层的全部定制。

3 - 别名翻译

Pigsty 提供软件包别名翻译机制,可以屏蔽底层操作系统的二进制包细节差异,让安装更简易。

PostgreSQL 在不同操作系统上的软件包命名规则存在显著差异:

  • EL 系统(RHEL/Rocky/Alma/…)使用 pgvector_17postgis36_17* 这样的格式
  • Debian/Ubuntu 系统使用 postgresql-17-pgvectorpostgresql-17-postgis-3 这样的格式

这种差异给用户带来了额外的认知负担:您需要记住不同系统的包名规则,还要处理 PostgreSQL 版本号嵌入的问题。

软件包别名

Pigsty 通过 软件包别名(Package Alias) 机制解决了这个问题:您只需使用统一的别名,Pigsty 会处理好所有细节:

# 使用别名 —— 简单、统一、跨平台
pg_extensions: [ postgis, pgvector, timescaledb ]

# 等效于 EL9 + PG17 上的实际包名
pg_extensions: [ postgis36_17*, pgvector_17*, timescaledb-tsl_17* ]

# 等效于 Ubuntu 24 + PG17 上的实际包名
pg_extensions: [ postgresql-17-postgis-3, postgresql-17-pgvector, postgresql-17-timescaledb-tsl ]

别名翻译

别名还可以将一组软件包归类为一个整体,例如 Pigsty 默认安装的软件包 —— pg_packages 的默认值是:

pg_packages:                      # pg packages to be installed, alias can be used
  - pgsql-main pgsql-common

Pigsty 将查询当前的操作系统别名清单(假设为 el10.x86_64),将其翻译为 PGSQL 内核,扩展,以及工具包:

pgsql-main:    "postgresql$v postgresql$v-server postgresql$v-libs postgresql$v-contrib postgresql$v-plperl postgresql$v-plpython3 postgresql$v-pltcl postgresql$v-llvmjit pg_repack_$v* wal2json_$v* pgvector_$v*"
pgsql-common:  "patroni patroni-etcd pgbouncer pgbackrest pg_exporter pgbackrest_exporter vip-manager"

接下来,Pigsty 又进一步通过当前指定的 PG 大版本(假设 pg_version = 18 ),将 pgsql-main 翻译为:

pg18-main:   "postgresql18 postgresql18-server postgresql18-libs postgresql18-contrib postgresql18-plperl postgresql18-plpython3 postgresql18-pltcl postgresql18-llvmjit pg_repack_18* wal2json_18* pgvector_18*"

通过这种方式,Pigsty 屏蔽了软件包的复杂性,让用户可以简单的指定自己想要的功能组件。


哪些变量可以使用别名?

您可以在以下四个参数中使用包别名,别名会根据翻译流程自动转换为实际的软件包名称:


别名列表

你可以在 Pigsty 项目源代码的 roles/node_id/vars/ 目录下,找到各操作系统与架构对应的别名映射文件:


工作原理

别名翻译流程

用户配置别名 --> 检测操作系统 -->  查找别名映射表 ---> 替换$v占位符 ---> 安装实际软件包
     ↓              ↓               ↓                               ↓
  postgis      el9.x86_64      postgis36_$v*                postgis36_17*
  postgis      u24.x86_64      postgresql-$v-postgis-3      postgresql-17-postgis-3

版本占位符

Pigsty 的别名系统使用 $v 作为 PostgreSQL 版本号的占位符。当您使用 pg_version 指定了 PostgreSQL 版本后,所有别名中的 $v 都会被替换为实际版本号。

例如,当 pg_version: 17 时:

别名定义 (EL)展开结果
postgresql$v*postgresql17*
pgvector_$v*pgvector_17*
timescaledb-tsl_$v*timescaledb-tsl_17*
别名定义 (Debian/Ubuntu)展开结果
postgresql-$vpostgresql-17
postgresql-$v-pgvectorpostgresql-17-pgvector
postgresql-$v-timescaledb-tslpostgresql-17-timescaledb-tsl

通配符匹配

在 EL 系统上,许多别名使用 * 通配符来匹配相关的子包。例如:

  • postgis36_17* 会匹配 postgis36_17postgis36_17-clientpostgis36_17-utils
  • postgresql17* 会匹配 postgresql17postgresql17-serverpostgresql17-libspostgresql17-contrib

这种设计确保您无需逐一列出每个子包,一个别名即可安装完整的扩展。

4 - 用户/角色

用户/角色指的是使用 SQL 命令 CREATE USER/ROLE 创建的,数据库集簇内的逻辑对象。

在这里的上下文中,用户指的是使用 SQL 命令 CREATE USER/ROLE 创建的,数据库集簇内的逻辑对象。

在PostgreSQL中,用户直接隶属于数据库集簇而非某个具体的数据库。因此在创建业务数据库和业务用户时,应当遵循"先用户,后数据库"的原则。


定义用户

Pigsty通过两个配置参数定义数据库集群中的角色与用户:

  • pg_default_roles:定义全局统一使用的角色和用户
  • pg_users:在数据库集群层面定义业务用户和角色

前者用于定义了整套环境中共用的角色与用户,后者定义单个集群中特有的业务角色与用户。二者形式相同,均为用户定义对象的数组。

你可以定义多个用户/角色,它们会按照先全局,后集群,最后按数组内排序的顺序依次创建,所以后面的用户可以属于前面定义的角色。

下面是 Pigsty 演示环境中默认集群 pg-meta 中的业务用户定义:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_users:
      - {name: dbuser_meta     ,password: DBUser.Meta     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: pigsty admin user }
      - {name: dbuser_view     ,password: DBUser.Viewer   ,pgbouncer: true ,roles: [dbrole_readonly] ,comment: read-only viewer for meta database }
      - {name: dbuser_grafana  ,password: DBUser.Grafana  ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for grafana database    }
      - {name: dbuser_bytebase ,password: DBUser.Bytebase ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for bytebase database   }
      - {name: dbuser_kong     ,password: DBUser.Kong     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for kong api gateway    }
      - {name: dbuser_gitea    ,password: DBUser.Gitea    ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for gitea service       }
      - {name: dbuser_wiki     ,password: DBUser.Wiki     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for wiki.js service     }
      - {name: dbuser_noco     ,password: DBUser.Noco     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for nocodb service      }
      - {name: dbuser_remove   ,state: absent }  # 使用 state: absent 删除用户

每个用户/角色定义都是一个 object,可能包括以下字段,以 dbuser_meta 用户为例:

- name: dbuser_meta               # 必需,`name` 是用户定义的唯一必选字段
  state: create                   # 可选,用户状态:create(创建,默认)、absent(删除)
  password: DBUser.Meta           # 可选,密码,可以是 scram-sha-256 哈希字符串或明文
  login: true                     # 可选,默认情况下可以登录
  superuser: false                # 可选,默认为 false,是超级用户吗?
  createdb: false                 # 可选,默认为 false,可以创建数据库吗?
  createrole: false               # 可选,默认为 false,可以创建角色吗?
  inherit: true                   # 可选,默认情况下,此角色可以使用继承的权限吗?
  replication: false              # 可选,默认为 false,此角色可以进行复制吗?
  bypassrls: false                # 可选,默认为 false,此角色可以绕过行级安全吗?
  pgbouncer: true                 # 可选,默认为 false,将此用户添加到 pgbouncer 用户列表吗?(使用连接池的生产用户应该显式定义为 true)
  connlimit: -1                   # 可选,用户连接限制,默认 -1 禁用限制
  expire_in: 3650                 # 可选,此角色过期时间:从创建时 + n天计算(优先级比 expire_at 更高)
  expire_at: '2030-12-31'         # 可选,此角色过期的时间点,使用 YYYY-MM-DD 格式的字符串指定一个特定日期(优先级没 expire_in 高)
  comment: pigsty admin user      # 可选,此用户/角色的说明与备注字符串
  roles: [dbrole_admin]           # 可选,所属角色,默认角色为:dbrole_{admin,readonly,readwrite,offline}
  parameters:                     # 可选,使用 `ALTER ROLE SET` 针对这个角色,配置角色级的数据库参数
    search_path: public           # 例如:为用户设置默认 search_path
  pool_mode: transaction          # 可选,默认为 transaction 的 pgbouncer 池模式,用户级别
  pool_connlimit: -1              # 可选,用户级别的最大数据库连接数,默认 -1 禁用限制
  • 唯一必需的字段是 name,它应该是 PostgreSQL 集群中的一个有效且唯一的用户名。
  • 用户名必须匹配正则表达式 ^[a-z_][a-z0-9_]{0,62}$(小写字母、数字、下划线,以字母或下划线开头,最长63字符)。
  • 角色不需要 password,但对于可登录的业务用户,通常是需要指定一个密码的。
  • password 可以是明文或 scram-sha-256 / md5 哈希字符串,请最好不要使用明文密码。
  • 用户/角色按数组顺序逐一创建,因此,请确保角色/分组的定义在成员之前。
  • loginsuperusercreatedbcreateroleinheritreplicationbypassrls 是布尔标志。
  • pgbouncer 默认是禁用的:要将业务用户添加到 pgbouncer 用户列表,您应当显式将其设置为 true

参数总览

字段分类类型可变性说明
name基本string必选用户名,必须是有效且唯一的标识符
state基本enum可选用户状态:create(默认)、absent
password基本string可变用户密码,明文或哈希
comment基本string可变用户备注信息
login权限bool可变是否允许登录,默认 true
superuser权限bool可变是否为超级用户,默认 false
createdb权限bool可变是否可创建数据库,默认 false
createrole权限bool可变是否可创建角色,默认 false
inherit权限bool可变是否继承所属角色权限,默认 true
replication权限bool可变是否可进行复制,默认 false
bypassrls权限bool可变是否可绕过行级安全,默认 false
connlimit权限int可变连接数限制,-1 表示不限制
expire_in有效期int可变从当前日期起 N 天后过期(优先级高于 expire_at
expire_at有效期string可变过期日期,YYYY-MM-DD 格式
roles角色array增量所属角色数组,支持字符串或对象格式
parameters参数object可变角色级参数
pgbouncer连接池bool可变是否加入连接池,默认 false
pool_mode连接池enum可变池化模式:transaction(默认)
pool_connlimit连接池int可变连接池用户最大连接数

可变性说明

可变性含义
必选必须指定的字段
可选可选字段,有默认值
可变可通过重新执行剧本修改
增量只会添加新内容,不会删除已有内容

基本参数

name

  • 类型string
  • 可变性:必选
  • 说明:用户名,集群内唯一标识符

用户名必须是有效的 PostgreSQL 标识符,必须匹配正则表达式 ^[a-z_][a-z0-9_]{0,62}$

  • 以小写字母或下划线开头
  • 只能包含小写字母、数字、下划线
  • 最长 63 个字符
- name: dbuser_app         # 标准命名
- name: app_readonly       # 下划线分隔
- name: _internal          # 下划线开头(用于内部角色)

state

  • 类型enum
  • 可变性:可选
  • 默认值create
  • 可选值createabsent
  • 说明:用户目标状态
状态说明
create创建用户(默认),已存在则更新属性
absent删除用户,使用 DROP ROLE
- name: dbuser_app             # state 默认为 create
- name: dbuser_old
  state: absent                # 删除用户

注意:以下系统用户无法通过 state: absent 删除:

  • postgres(超级用户)
  • replicator(或 pg_replication_username 配置的用户)
  • dbuser_dba(或 pg_admin_username 配置的用户)
  • dbuser_monitor(或 pg_monitor_username 配置的用户)

password

  • 类型string
  • 可变性:可变
  • 默认值:无
  • 说明:用户密码

密码可以是以下格式之一:

  • 明文密码DBUser.Meta(不推荐用于生产环境)
  • SCRAM-SHA-256 哈希SCRAM-SHA-256$4096:...(推荐)
  • MD5 哈希md5...(兼容旧版本)
# 明文密码(会被记录到配置文件,不推荐)
- name: dbuser_app
  password: MySecretPassword

# SCRAM-SHA-256 哈希(推荐)
- name: dbuser_app
  password: 'SCRAM-SHA-256$4096:xxx$yyy:zzz'

生成 SCRAM-SHA-256 哈希

# 使用 PostgreSQL 生成
psql -c "SELECT 'SCRAM-SHA-256$' || pg_catalog.scram_sha_256('your_password')"

# 或使用 Python
python3 -c "import hashlib, secrets; print('SCRAM-SHA-256$4096:' + ...)"

comment

  • 类型string
  • 可变性:可变
  • 默认值business user {name}
  • 说明:用户备注信息

会执行 COMMENT ON ROLE 语句。支持中文和特殊字符(会自动转义单引号)。

- name: dbuser_app
  comment: '业务应用主账号'

权限参数

login

  • 类型bool
  • 可变性:可变
  • 默认值true
  • 说明:是否允许登录

设置为 false 创建的是角色(Role)而非用户(User),通常用于权限分组。

# 创建可登录用户
- name: dbuser_app
  login: true

# 创建角色(不可登录)
- name: dbrole_custom
  login: false

superuser

  • 类型bool
  • 可变性:可变
  • 默认值false
  • 说明:是否为超级用户

createdb

  • 类型bool
  • 可变性:可变
  • 默认值false
  • 说明:是否可创建数据库

createrole

  • 类型bool
  • 可变性:可变
  • 默认值false
  • 说明:是否可创建角色

inherit

  • 类型bool
  • 可变性:可变
  • 默认值true
  • 说明:是否自动继承所属角色的权限

设置为 false 时,用户需要通过 SET ROLE 显式切换角色才能使用继承的权限。

replication

  • 类型bool
  • 可变性:可变
  • 默认值false
  • 说明:是否可以发起流复制连接

通常只有复制用户(如 replicator)需要此权限。

bypassrls

  • 类型bool
  • 可变性:可变
  • 默认值false
  • 说明:是否可以绕过行级安全(RLS)策略

connlimit

  • 类型int
  • 可变性:可变
  • 默认值-1(不限制)
  • 说明:用户最大并发连接数
- name: dbuser_app
  connlimit: 100           # 最多 100 个并发连接

- name: dbuser_batch
  connlimit: 10            # 批处理用户限制连接数

有效期参数

expire_in

  • 类型int
  • 可变性:可变
  • 说明:从当前日期起 N 天后过期

此参数优先级高于 expire_at。每次执行剧本时会重新计算过期时间。

- name: temp_user
  expire_in: 30            # 30 天后过期

- name: long_term_user
  expire_in: 3650          # 约 10 年后过期

expire_at

  • 类型string
  • 可变性:可变
  • 说明:指定过期日期

格式为 YYYY-MM-DD 或特殊值 infinity(永不过期)。

- name: contractor_user
  expire_at: '2024-12-31'  # 指定日期过期

- name: permanent_user
  expire_at: 'infinity'    # 永不过期

注意expire_in 优先级高于 expire_at,如果同时指定,只有 expire_in 生效。


角色成员参数

roles

  • 类型array
  • 可变性:增量
  • 说明:用户所属角色数组

roles 数组支持两种格式:

简单格式(字符串)

- name: dbuser_app
  roles:
    - dbrole_readwrite
    - pg_read_all_data

生成的 SQL:

GRANT "dbrole_readwrite" TO "dbuser_app";
GRANT "pg_read_all_data" TO "dbuser_app";

扩展格式(对象)

对象格式支持更精细的角色成员关系控制:

- name: dbuser_app
  roles:
    - dbrole_readwrite                              # 简单字符串:GRANT 角色
    - { name: dbrole_admin, admin: true }           # GRANT WITH ADMIN OPTION
    - { name: pg_monitor, set: false }              # PG16+: REVOKE SET OPTION
    - { name: pg_signal_backend, inherit: false }   # PG16+: REVOKE INHERIT OPTION
    - { name: old_role, state: absent }             # REVOKE 角色成员关系

对象格式参数

参数类型说明
namestring角色名称(必选)
stateenumgrant(默认)或 absent/revoke:控制成员关系
adminbooltrue: WITH ADMIN OPTION / false: REVOKE ADMIN
setboolPG16+: true: WITH SET TRUE / false: REVOKE SET
inheritboolPG16+: true: WITH INHERIT TRUE / false: REVOKE INHERIT

PostgreSQL 16+ 新特性

PostgreSQL 16 引入了更细粒度的角色成员关系控制:

  • ADMIN OPTION:允许将角色授予其他用户
  • SET OPTION:允许使用 SET ROLE 切换到该角色
  • INHERIT OPTION:是否自动继承该角色的权限
# PostgreSQL 16+ 完整示例
- name: dbuser_app
  roles:
    # 普通成员关系
    - dbrole_readwrite

    # 可以将 dbrole_admin 授予其他用户
    - { name: dbrole_admin, admin: true }

    # 不能 SET ROLE 到 pg_monitor(只能继承权限)
    - { name: pg_monitor, set: false }

    # 不自动继承 pg_execute_server_program 的权限(需要显式 SET ROLE)
    - { name: pg_execute_server_program, inherit: false }

    # 撤销 old_role 的成员关系
    - { name: old_role, state: absent }

注意setinherit 选项仅在 PostgreSQL 16+ 中有效,在早期版本会被忽略并生成警告注释。


角色级参数

parameters

  • 类型object
  • 可变性:可变
  • 说明:角色级配置参数

通过 ALTER ROLE ... SET 设置参数,参数会对该用户的所有会话生效。

- name: dbuser_analyst
  parameters:
    work_mem: '256MB'
    statement_timeout: '5min'
    search_path: 'analytics,public'
    log_statement: 'all'

生成的 SQL:

ALTER USER "dbuser_analyst" SET "work_mem" = '256MB';
ALTER USER "dbuser_analyst" SET "statement_timeout" = '5min';
ALTER USER "dbuser_analyst" SET "search_path" = 'analytics,public';
ALTER USER "dbuser_analyst" SET "log_statement" = 'all';

重置参数为默认值

使用特殊值 DEFAULT(大小写不敏感)可以将参数重置为 PostgreSQL 默认值:

- name: dbuser_app
  parameters:
    work_mem: DEFAULT         # 重置为 PostgreSQL 默认值
    statement_timeout: '30s'  # 设置新值

生成的 SQL:

ALTER USER "dbuser_app" SET "work_mem" = DEFAULT;
ALTER USER "dbuser_app" SET "statement_timeout" = '30s';

常用角色级参数

参数说明示例值
work_mem查询工作内存'64MB'
statement_timeout语句超时时间'30s'
lock_timeout锁等待超时'10s'
idle_in_transaction_session_timeout空闲事务超时'10min'
search_pathSchema 搜索路径'app,public'
log_statement日志记录级别'ddl'
temp_file_limit临时文件大小限制'10GB'

连接池参数

这些参数控制用户在 Pgbouncer 连接池中的行为。

pgbouncer

  • 类型bool
  • 可变性:可变
  • 默认值false
  • 说明:是否将用户添加到 Pgbouncer 用户列表
# 生产用户:需要连接池
- name: dbuser_app
  password: DBUser.App
  pgbouncer: true

# 内部用户:不需要连接池
- name: dbuser_internal
  password: DBUser.Internal
  pgbouncer: false           # 默认值,可省略

pool_mode

  • 类型enum
  • 可变性:可变
  • 可选值transactionsessionstatement
  • 默认值transaction
  • 说明:用户级别的池化模式
模式说明适用场景
transaction事务结束后归还连接(默认)大多数 OLTP 应用
session会话结束后归还连接需要会话状态的应用
statement语句结束后归还连接简单无状态查询
# DBA 用户使用 session 模式(可能需要 SET 命令等会话状态)
- name: dbuser_dba
  pgbouncer: true
  pool_mode: session

# 普通业务用户使用 transaction 模式
- name: dbuser_app
  pgbouncer: true
  pool_mode: transaction

pool_connlimit

  • 类型int
  • 可变性:可变
  • 默认值-1(不限制)
  • 说明:用户级别的连接池最大连接数
- name: dbuser_app
  pgbouncer: true
  pool_connlimit: 50         # 此用户最多使用 50 个连接池连接

ACL系统

Pigsty 具有一套内置的,开箱即用的访问控制 / ACL 系统,您只需将以下四个默认角色分配给业务用户即可轻松使用:

  • dbrole_readwrite:全局读写访问的角色(主属业务使用的生产账号应当具有数据库读写权限)
  • dbrole_readonly:全局只读访问的角色(如果别的业务想要只读访问,可以使用此角色)
  • dbrole_admin:拥有DDL权限的角色 (业务管理员,需要在应用中建表的场景)
  • dbrole_offline:受限的只读访问角色(只能访问 offline 实例,通常是个人用户)

如果您希望重新设计您自己的 ACL 系统,可以考虑定制以下参数和模板:


Pgbouncer用户

默认情况下启用 Pgbouncer,并作为连接池中间件,其用户默认被管理。

Pigsty 默认将 pg_users 中显式带有 pgbouncer: true 标志的所有用户添加到 pgbouncer 用户列表中。

Pgbouncer 连接池中的用户在 /etc/pgbouncer/userlist.txt 中列出:

"postgres" ""
"dbuser_wiki" "SCRAM-SHA-256$4096:+77dyhrPeFDT/TptHs7/7Q==$KeatuohpKIYzHPCt/tqBu85vI11o9mar/by0hHYM2W8=:X9gig4JtjoS8Y/o1vQsIX/gY1Fns8ynTXkbWOjUfbRQ="
"dbuser_view" "SCRAM-SHA-256$4096:DFoZHU/DXsHL8MJ8regdEw==$gx9sUGgpVpdSM4o6A2R9PKAUkAsRPLhLoBDLBUYtKS0=:MujSgKe6rxcIUMv4GnyXJmV0YNbf39uFRZv724+X1FE="
"dbuser_monitor" "SCRAM-SHA-256$4096:fwU97ZMO/KR0ScHO5+UuBg==$CrNsmGrx1DkIGrtrD1Wjexb/aygzqQdirTO1oBZROPY=:L8+dJ+fqlMQh7y4PmVR/gbAOvYWOr+KINjeMZ8LlFww="
"dbuser_meta" "SCRAM-SHA-256$4096:leB2RQPcw1OIiRnPnOMUEg==$eyC+NIMKeoTxshJu314+BmbMFpCcspzI3UFZ1RYfNyU=:fJgXcykVPvOfro2MWNkl5q38oz21nSl1dTtM65uYR1Q="

而用户级别的连接池参数则是使用另一个单独的文件: /etc/pgbouncer/useropts.txt 进行维护,比如:

dbuser_dba                  = pool_mode=session max_user_connections=16
dbuser_monitor              = pool_mode=session max_user_connections=8

当您创建用户时,Pgbouncer 的用户列表定义文件将会被刷新,并通过在线重载配置的方式生效,不会影响现有的连接。

Pgbouncer 使用和 PostgreSQL 同样的 dbsu 运行,默认为 postgres 操作系统用户,您可以使用 pgb 别名,使用 dbsu 访问 pgbouncer 管理功能。

请注意,pgbouncer_auth_query 参数允许你使用动态查询来完成连接池用户认证,当您懒得管理连接池中的用户时,这是一种折中的方案。

关于用户管理操作,请参考 用户管理 一节。

关于用户的访问权限,请参考 ACL:角色权限 一节。

5 - 数据库

数据库指的是使用 SQL 命令 CREATE DATABASE 创建的,数据库集簇内的逻辑对象。

在这里的上下文中,数据库指的是使用 SQL 命令 CREATE DATABASE 创建的,数据库集簇内的逻辑对象。

一组 PostgreSQL 服务器可以同时服务于多个 数据库 (Database)。在 Pigsty 中,你可以在集群配置中定义好所需的数据库。

Pigsty会对默认模板数据库template1进行修改与定制,创建默认模式,安装默认扩展,配置默认权限,新创建的数据库默认会从template1继承这些设置。

默认情况下,所有业务数据库都会被1:1添加到 Pgbouncer 连接池中;pg_exporter 默认会通过 自动发现 机制查找所有业务数据库并进行库内对象监控。


定义数据库

业务数据库定义在数据库集群参数 pg_databases 中,这是一个数据库定义构成的对象数组。 数组内的数据库按照定义顺序依次创建,因此后面定义的数据库可以使用先前定义的数据库作为模板

下面是 Pigsty 演示环境中默认集群 pg-meta 中的数据库定义:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_databases:
      - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [{name: postgis, schema: public}, {name: timescaledb}]}
      - { name: grafana  ,owner: dbuser_grafana  ,revokeconn: true ,comment: grafana primary database }
      - { name: bytebase ,owner: dbuser_bytebase ,revokeconn: true ,comment: bytebase primary database }
      - { name: kong     ,owner: dbuser_kong     ,revokeconn: true ,comment: kong the api gateway database }
      - { name: gitea    ,owner: dbuser_gitea    ,revokeconn: true ,comment: gitea meta database }
      - { name: wiki     ,owner: dbuser_wiki     ,revokeconn: true ,comment: wiki meta database }
      - { name: noco     ,owner: dbuser_noco     ,revokeconn: true ,comment: nocodb database }

每个数据库定义都是一个 object,可能包括以下字段,以 meta 数据库为例:

- name: meta                      # 必选,`name` 是数据库定义的唯一必选字段
  state: create                   # 可选,数据库状态:create(创建,默认)、absent(删除)、recreate(重建)
  baseline: cmdb.sql              # 可选,数据库 sql 的基线定义文件路径(ansible 搜索路径中的相对路径,如 files/)
  pgbouncer: true                 # 可选,是否将此数据库添加到 pgbouncer 数据库列表?默认为 true
  schemas: [pigsty]               # 可选,要创建的附加模式,由模式名称字符串组成的数组
  extensions:                     # 可选,要安装的附加扩展: 扩展对象的数组
    - { name: postgis , schema: public }  # 可以指定将扩展安装到某个模式中,也可以不指定(不指定则安装到 search_path 首位模式中)
    - { name: timescaledb }               # 例如有的扩展会创建并使用固定的模式,就不需要指定模式。
  comment: pigsty meta database   # 可选,数据库的说明与备注信息
  owner: postgres                 # 可选,数据库所有者,不指定则为当前用户
  template: template1             # 可选,要使用的模板,默认为 template1,目标必须是一个模板数据库
  strategy: FILE_COPY             # 可选,克隆策略:FILE_COPY 或 WAL_LOG(PG15+),不指定使用 PG 默认
  encoding: UTF8                  # 可选,不指定则继承模板/集群配置(UTF8)
  locale: C                       # 可选,不指定则继承模板/集群配置(C)
  lc_collate: C                   # 可选,不指定则继承模板/集群配置(C)
  lc_ctype: C                     # 可选,不指定则继承模板/集群配置(C)
  locale_provider: libc           # 可选,本地化提供者:libc、icu、builtin(PG15+)
  icu_locale: en-US               # 可选,ICU 本地化规则(PG15+)
  icu_rules: ''                   # 可选,ICU 排序规则(PG16+)
  builtin_locale: C.UTF-8         # 可选,内置本地化提供者规则(PG17+)
  tablespace: pg_default          # 可选,默认表空间,默认为 'pg_default'
  is_template: false              # 可选,是否标记为模板数据库,允许任何有 CREATEDB 权限的用户克隆
  allowconn: true                 # 可选,是否允许连接,默认为 true。显式设置 false 将完全禁止连接到此数据库
  revokeconn: false               # 可选,撤销公共连接权限。默认为 false,设置为 true 时,属主和管理员之外用户的 CONNECT 权限会被回收
  register_datasource: true       # 可选,是否将此数据库注册到 grafana 数据源?默认为 true,显式设置为 false 会跳过注册
  connlimit: -1                   # 可选,数据库连接限制,默认为 -1 ,不限制,设置为正整数则会限制连接数。
  parameters:                     # 可选,数据库级参数,通过 ALTER DATABASE SET 设置
    work_mem: '64MB'
    statement_timeout: '30s'
  pool_auth_user: dbuser_meta     # 可选,连接到此 pgbouncer 数据库的所有连接都将使用此用户进行验证(启用 pgbouncer_auth_query 才有用)
  pool_mode: transaction          # 可选,数据库级别的 pgbouncer 池化模式,默认为 transaction
  pool_size: 64                   # 可选,数据库级别的 pgbouncer 默认池子大小,默认为 64
  pool_reserve: 32                # 可选,数据库级别的 pgbouncer 池子保留空间,默认为 32,当默认池子不够用时,最多再申请这么多条突发连接。
  pool_size_min: 0                # 可选,数据库级别的 pgbouncer 池的最小大小,默认为 0
  pool_connlimit: 100             # 可选,数据库级别的最大数据库连接数,默认为 100

唯一必选的字段是 name,它应该是当前 PostgreSQL 集群中有效且唯一的数据库名称,其他参数都有合理的默认值。


参数总览

字段分类类型可变性说明
name基本string必选数据库名称,必须是有效且唯一的标识符
state基本enum可选数据库状态:create(默认)、absentrecreate
owner基本string可变数据库属主,不指定则为 postgres
comment基本string可变数据库备注信息
template模板string不可变创建时使用的模板数据库,默认 template1
strategy模板enum不可变克隆策略:FILE_COPYWAL_LOG(PG15+)
encoding编码string不可变字符编码,默认继承模板(UTF8
locale编码string不可变本地化规则,默认继承模板(C
lc_collate编码string不可变排序规则,默认继承模板(C
lc_ctype编码string不可变字符分类,默认继承模板(C
locale_provider编码enum不可变本地化提供者:libcicubuiltin(PG15+)
icu_locale编码string不可变ICU 本地化规则(PG15+)
icu_rules编码string不可变ICU 排序定制规则(PG16+)
builtin_locale编码string不可变内置本地化规则(PG17+)
tablespace存储string可变默认表空间,修改会触发数据迁移
is_template权限bool可变是否标记为模板数据库
allowconn权限bool可变是否允许连接,默认 true
revokeconn权限bool可变是否回收 PUBLIC 的 CONNECT 权限
connlimit权限int可变连接数限制,-1 表示不限制
baseline初始化string一次性SQL 基线文件路径,仅首次创建时执行
schemas初始化(string|object)[]增量要创建的模式定义数组
extensions初始化object[]增量要安装的扩展定义数组
parameters初始化object可变数据库级参数
pgbouncer连接池bool可变是否加入连接池,默认 true
pool_mode连接池enum可变池化模式:transaction(默认)
pool_size连接池int可变默认池大小,默认 64
pool_size_min连接池int可变最小池大小,默认 0
pool_reserve连接池int可变保留池大小,默认 32
pool_connlimit连接池int可变最大数据库连接数,默认 100
pool_auth_user连接池string可变认证查询用户
register_datasource监控bool可变是否注册到 Grafana 数据源,默认 true

可变性说明

可变性含义
必选必须指定的字段
可选可选字段,有默认值
不可变仅在创建时生效,创建后无法修改,需重建数据库
可变可通过重新执行剧本修改
一次性仅在首次创建时执行,已存在的数据库不会重复执行
增量只会添加新内容,不会删除已有内容

基本参数

name

  • 类型string
  • 可变性:必选
  • 说明:数据库名称,集群内唯一标识符

数据库名称必须是有效的 PostgreSQL 标识符,建议使用小写字母、数字和下划线,避免使用特殊字符。

- name: myapp              # 简单命名
- name: my_application     # 下划线分隔
- name: app_v2             # 包含版本号

state

  • 类型enum
  • 可变性:可选
  • 默认值create
  • 可选值createabsentrecreate
  • 说明:数据库目标状态
状态说明
create创建数据库(默认),已存在则跳过
absent删除数据库,使用 DROP DATABASE WITH (FORCE)
recreate先删除再创建,用于重置数据库
- name: myapp                # state 默认为 create
- name: olddb
  state: absent              # 删除数据库
- name: testdb
  state: recreate            # 重建数据库

owner

  • 类型string
  • 可变性:可变
  • 默认值postgres(当前用户)
  • 说明:数据库所有者

指定的用户必须已存在。修改 owner 会执行:

ALTER DATABASE "myapp" OWNER TO "new_owner";
GRANT ALL PRIVILEGES ON DATABASE "myapp" TO "new_owner";

comment

  • 类型string
  • 可变性:可变
  • 默认值business database {name}
  • 说明:数据库备注信息

会执行 COMMENT ON DATABASE 语句。支持中文和特殊字符(会自动转义单引号)。


模板与克隆参数

template

  • 类型string
  • 可变性:不可变
  • 默认值template1
  • 说明:创建数据库时使用的模板

常用模板:

模板说明
template1默认模板,包含 Pigsty 预配置的扩展和权限
template0干净模板,用于指定不同编码或本地化设置时必须使用
自定义数据库可以使用已有数据库作为模板克隆

重要:使用 icubuiltin 本地化提供者时,必须指定 template: template0

- name: myapp_icu
  template: template0        # 使用 ICU 时必须
  locale_provider: icu
  icu_locale: en-US

strategy

  • 类型enum
  • 可变性:不可变
  • 版本要求:PostgreSQL 15+
  • 可选值FILE_COPYWAL_LOG
  • 说明:从模板克隆数据库的策略
策略说明适用场景
FILE_COPY直接复制数据文件(PG15+ 默认)大模板,通用场景
WAL_LOG通过 WAL 日志复制小模板,不阻塞连接

在 PostgreSQL 14 及更早版本中,此参数会被忽略。


编码与本地化参数

encoding

  • 类型string
  • 可变性:不可变
  • 默认值:继承模板(通常为 UTF8
  • 说明:数据库字符编码

常用编码:UTF8LATIN1SQL_ASCII

locale

  • 类型string
  • 可变性:不可变
  • 默认值:继承模板(通常为 C
  • 说明:数据库本地化规则,同时设置 lc_collatelc_ctype

lc_collate

  • 类型string
  • 可变性:不可变
  • 默认值:继承模板(通常为 C
  • 说明:字符串排序规则

常用值:CC.UTF-8en_US.UTF-8zh_CN.UTF-8

lc_ctype

  • 类型string
  • 可变性:不可变
  • 默认值:继承模板(通常为 C
  • 说明:字符分类规则(大小写、数字等)

locale_provider

  • 类型enum
  • 可变性:不可变
  • 版本要求:PostgreSQL 15+
  • 可选值libcicubuiltin
  • 默认值libc
  • 说明:本地化实现提供者
提供者版本说明
libc-使用操作系统 C 库,传统默认方式
icuPG15+使用 ICU 库,跨平台一致
builtinPG17+PostgreSQL 内置实现,最高效的 C/C.UTF-8

注意:使用 icubuiltin 时,必须指定 template: template0

icu_locale

  • 类型string
  • 可变性:不可变
  • 版本要求:PostgreSQL 15+
  • 说明:ICU 本地化规则标识符

常用值:

说明
en-US美式英语
en-GB英式英语
zh-Hans简体中文
zh-Hant繁体中文
ja-JP日语
ko-KR韩语
- name: chinese_db
  template: template0
  locale_provider: icu
  icu_locale: zh-Hans
  encoding: UTF8

icu_rules

  • 类型string
  • 可变性:不可变
  • 版本要求:PostgreSQL 16+
  • 说明:ICU 排序定制规则

用于自定义排序行为,使用 ICU 规则语法。

- name: custom_sort_db
  template: template0
  locale_provider: icu
  icu_locale: en-US
  icu_rules: '&V << w <<< W'  # 自定义 V/W 排序

builtin_locale

  • 类型string
  • 可变性:不可变
  • 版本要求:PostgreSQL 17+
  • 可选值CC.UTF-8
  • 说明:内置本地化提供者的规则

builtin 提供者比 libc 更快,特别适合只需要 CC.UTF-8 排序的场景。

- name: fast_db
  template: template0
  locale_provider: builtin
  builtin_locale: C.UTF-8
  encoding: UTF8

存储与权限参数

tablespace

  • 类型string
  • 可变性:可变
  • 默认值pg_default
  • 说明:数据库默认表空间

修改表空间会触发数据物理迁移,对于大数据库可能需要较长时间。

- name: archive_db
  tablespace: slow_hdd       # 归档数据使用慢速存储

is_template

  • 类型bool
  • 可变性:可变
  • 默认值false
  • 说明:是否标记为模板数据库

设置为 true 后,任何有 CREATEDB 权限的用户都可以使用此数据库作为模板克隆新数据库。

- name: app_template
  is_template: true          # 允许普通用户克隆
  schemas: [core, api]
  extensions: [postgis]

注意:标记为 is_template: true 的数据库删除时,会先执行 ALTER DATABASE ... IS_TEMPLATE false

allowconn

  • 类型bool
  • 可变性:可变
  • 默认值true
  • 说明:是否允许连接到此数据库

设置为 false 会完全禁止任何用户连接到此数据库(包括超级用户)。

- name: archive_db
  allowconn: false           # 禁止连接

revokeconn

  • 类型bool
  • 可变性:可变
  • 默认值false
  • 说明:是否回收 PUBLIC 的 CONNECT 权限

设置为 true 时:

  • 回收 PUBLIC 的 CONNECT 权限
  • 授予 replicator、monitor 连接权限
  • 授予 admin、owner 连接权限(WITH GRANT OPTION)

设置为 false 时:

  • 恢复 PUBLIC 的 CONNECT 权限
- name: secure_db
  owner: dbuser_secure
  revokeconn: true           # 只有指定用户可连接

connlimit

  • 类型int
  • 可变性:可变
  • 默认值-1(不限制)
  • 说明:数据库最大连接数限制
- name: limited_db
  connlimit: 50              # 最多 50 个并发连接

初始化参数

baseline

  • 类型string
  • 可变性:一次性
  • 说明:SQL 基线文件路径

指定在数据库创建后执行的 SQL 文件,用于初始化表结构、数据等。

  • 路径是相对于 Ansible 搜索路径(通常是 files/ 目录)
  • 仅在首次创建数据库时执行
  • 使用 state: recreate 重建时会重新执行
- name: myapp
  baseline: myapp_init.sql   # 会查找 files/myapp_init.sql

schemas

  • 类型(string | object)[]
  • 可变性:增量
  • 说明:要创建的模式定义数组

支持两种格式:

schemas:
  # 简单格式:只指定模式名
  - app
  - api

  # 完整格式:对象定义
  - name: core               # 模式名(必选)
    owner: dbuser_app        # 模式属主(可选)
  - name: old_schema
    state: absent            # 删除模式

模式属主:使用 owner 指定模式属主,会生成 AUTHORIZATION 子句:

- name: myapp
  owner: dbuser_myapp
  schemas:
    - name: app
      owner: dbuser_myapp    # 模式属主与数据库属主一致
    - name: audit
      owner: dbuser_audit    # 模式属主为其他用户

执行的 SQL:

CREATE SCHEMA IF NOT EXISTS "app" AUTHORIZATION "dbuser_myapp";
CREATE SCHEMA IF NOT EXISTS "audit" AUTHORIZATION "dbuser_audit";

删除模式:使用 state: absent 删除模式:

schemas:
  - { name: deprecated_schema, state: absent }

执行的 SQL:

DROP SCHEMA IF EXISTS "deprecated_schema" CASCADE;

注意

  • 创建操作是增量的,使用 IF NOT EXISTS
  • 删除操作使用 CASCADE,会同时删除模式内的所有对象

extensions

  • 类型object[]
  • 可变性:增量
  • 说明:要安装的扩展定义数组

支持两种格式:

extensions:
  # 简单格式:只指定扩展名
  - postgis
  - pg_trgm

  # 完整格式:对象定义
  - name: vector             # 扩展名(必选)
    schema: public           # 安装到指定 schema(可选)
    version: '0.5.1'         # 指定版本(可选)
    state: absent            # 设为 absent 可卸载扩展(可选)

扩展卸载:使用 state: absent 可以卸载扩展:

extensions:
  - { name: pg_trgm, state: absent }  # 卸载 pg_trgm

卸载会执行 DROP EXTENSION IF EXISTS "name" CASCADE,注意 CASCADE 会删除依赖对象。

parameters

  • 类型object
  • 可变性:可变
  • 说明:数据库级配置参数

通过 ALTER DATABASE ... SET 设置参数,参数会对连接到此数据库的所有会话生效。

- name: analytics
  parameters:
    work_mem: '256MB'
    maintenance_work_mem: '512MB'
    statement_timeout: '5min'
    search_path: 'analytics,public'

重置参数:使用特殊值 DEFAULT(大小写不敏感)重置为 PostgreSQL 默认值:

- name: myapp
  parameters:
    work_mem: DEFAULT        # 重置为默认值
    statement_timeout: '30s' # 设置新值

执行的 SQL:

ALTER DATABASE "myapp" SET "work_mem" = DEFAULT;
ALTER DATABASE "myapp" SET "statement_timeout" = '30s';

连接池参数

这些参数控制数据库在 Pgbouncer 连接池中的行为。

pgbouncer

  • 类型bool
  • 可变性:可变
  • 默认值true
  • 说明:是否将数据库添加到 Pgbouncer 连接池
- name: internal_db
  pgbouncer: false           # 不通过连接池访问

pool_mode

  • 类型enum
  • 可变性:可变
  • 可选值transactionsessionstatement
  • 默认值transaction
  • 说明:数据库级别的池化模式
模式说明适用场景
transaction事务结束后归还连接大多数 OLTP 应用
session会话结束后归还连接需要会话状态的应用
statement语句结束后归还连接简单无状态查询

pool_size

  • 类型int
  • 可变性:可变
  • 默认值64
  • 说明:数据库默认连接池大小

pool_size_min

  • 类型int
  • 可变性:可变
  • 默认值0
  • 说明:最小连接池大小,预热连接数

pool_reserve

  • 类型int
  • 可变性:可变
  • 默认值32
  • 说明:保留连接数,突发时可额外申请的连接

pool_connlimit

  • 类型int
  • 可变性:可变
  • 默认值100
  • 说明:通过连接池访问此数据库的最大连接数

pool_auth_user

  • 类型string
  • 可变性:可变
  • 说明:认证查询用户

需要启用 pgbouncer_auth_query 后生效。 指定后,所有到此数据库的连接都会使用该用户查询密码。


监控参数

register_datasource

  • 类型bool
  • 可变性:可变
  • 默认值true
  • 说明:是否注册到 Grafana 数据源

设置为 false 可以跳过 Grafana 数据源注册,适用于不需要监控的临时数据库。


模板继承

许多参数如果不显式指定,会从模板数据库继承。默认模板是 template1,其编码设置由集群初始化参数决定:

集群参数默认值说明
pg_encodingUTF8集群默认字符编码
pg_localeC集群默认本地化
pg_lc_collateC集群默认排序规则
pg_lc_ctypeC集群默认字符分类

新创建的数据库默认会从 template1 数据库 Fork 出来,这个模版数据库会在 PG_PROVISION 阶段进行定制修改: 配置好扩展、模式以及默认权限,因此新创建的数据库也会继承这些配置,除非您显式使用一个其他的数据库作为模板。

关于数据库管理操作,请参考 数据库管理 一节。

关于数据库的访问权限,请参考 ACL:数据库权限 一节。

6 - HBA 规则

Pigsty 中 PostgreSQL 与 Pgbouncer 的 HBA(Host-Based Authentication)规则配置详解。

HBA(Host-Based Authentication)控制"谁可以从哪里、以什么方式连接到数据库"。 Pigsty 通过 pg_default_hba_rulespg_hba_rules 让 HBA 规则也能以声明式配置形式管理。


概述

Pigsty 在集群初始化或 HBA 刷新时渲染以下配置文件:

配置文件路径说明
PostgreSQL HBA/pg/data/pg_hba.confPostgreSQL 服务器的 HBA 规则
Pgbouncer HBA/etc/pgbouncer/pgb_hba.conf连接池 Pgbouncer 的 HBA 规则

HBA 规则由以下参数控制:

参数层级说明
pg_default_hba_rulesGPostgreSQL 全局默认 HBA 规则
pg_hba_rulesG/C/IPostgreSQL 集群/实例级追加规则
pgb_default_hba_rulesGPgbouncer 全局默认 HBA 规则
pgb_hba_rulesG/C/IPgbouncer 集群/实例级追加规则

规则特性:

  • 按角色过滤:规则支持 role 字段,根据实例的 pg_role 自动筛选生效
  • 按顺序排序:规则支持 order 字段,控制规则在最终配置文件中的位置
  • 两种写法:支持别名形式(简化语法)和原始形式(直接 HBA 文本)

参数详解

pg_default_hba_rules

PostgreSQL 全局默认 HBA 规则列表,通常定义在 all.vars 中,为所有 PostgreSQL 集群提供基础访问控制。

  • 类型:rule[]
  • 层级:全局 (G)
  • 默认值:见下文
pg_default_hba_rules:
  - {user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'  ,order: 100}
  - {user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident' ,order: 150}
  - {user: '${repl}'    ,db: replication ,addr: localhost ,auth: pwd   ,title: 'replicator replication from localhost',order: 200}
  - {user: '${repl}'    ,db: replication ,addr: intra     ,auth: pwd   ,title: 'replicator replication from intranet' ,order: 250}
  - {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: pwd   ,title: 'replicator postgres db from intranet' ,order: 300}
  - {user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password' ,order: 350}
  - {user: '${monitor}' ,db: all         ,addr: infra     ,auth: pwd   ,title: 'monitor from infra host with password',order: 400}
  - {user: '${admin}'   ,db: all         ,addr: infra     ,auth: ssl   ,title: 'admin @ infra nodes with pwd & ssl'   ,order: 450}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: ssl   ,title: 'admin @ everywhere with ssl & pwd'    ,order: 500}
  - {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: pwd   ,title: 'pgbouncer read/write via local socket',order: 550}
  - {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: pwd   ,title: 'read/write biz user via password'     ,order: 600}
  - {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: pwd   ,title: 'allow etl offline tasks from intranet',order: 650}

pg_hba_rules

PostgreSQL 集群/实例级 HBA 追加规则,可在集群或实例级别覆盖,与默认规则合并后按 order 排序。

  • 类型:rule[]
  • 层级:全局/集群/实例 (G/C/I)
  • 默认值:[]
pg_hba_rules:
  - {user: app_user, db: app_db, addr: intra, auth: pwd, title: 'app user access'}

pgb_default_hba_rules

Pgbouncer 全局默认 HBA 规则列表,通常定义在 all.vars 中。

  • 类型:rule[]
  • 层级:全局 (G)
  • 默认值:见下文
pgb_default_hba_rules:
  - {user: '${dbsu}'    ,db: pgbouncer   ,addr: local     ,auth: peer  ,title: 'dbsu local admin access with os ident',order: 100}
  - {user: 'all'        ,db: all         ,addr: localhost ,auth: pwd   ,title: 'allow all user local access with pwd' ,order: 150}
  - {user: '${monitor}' ,db: pgbouncer   ,addr: intra     ,auth: pwd   ,title: 'monitor access via intranet with pwd' ,order: 200}
  - {user: '${monitor}' ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other monitor access addr' ,order: 250}
  - {user: '${admin}'   ,db: all         ,addr: intra     ,auth: pwd   ,title: 'admin access via intranet with pwd'   ,order: 300}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other admin access addr'   ,order: 350}
  - {user: 'all'        ,db: all         ,addr: intra     ,auth: pwd   ,title: 'allow all user intra access with pwd' ,order: 400}

pgb_hba_rules

Pgbouncer 集群/实例级 HBA 追加规则。

  • 类型:rule[]
  • 层级:全局/集群/实例 (G/C/I)
  • 默认值:[]

注意:Pgbouncer HBA 不支持 db: replication


规则字段

每条 HBA 规则是一个 YAML 字典,支持以下字段:

字段类型必需默认值说明
userstringall用户名,支持 all、变量占位符、+rolename
dbstringall数据库名,支持 allreplication、具体库名
addrstring是*-地址别名或 CIDR,见地址别名
authstringpwd认证方式别名,见认证方式
titlestring-规则说明/注释,会渲染为配置文件中的注释
rolestringcommon实例角色过滤,见角色过滤
orderint1000排序权重,数字小的排前面,见排序机制
ruleslist是*-原始 HBA 文本行列表,与 addr 二选一

addrrules 必须指定其一。使用 rules 时可以直接写原始 HBA 格式。


地址别名

Pigsty 提供地址别名,简化 HBA 规则编写:

别名展开为说明
localUnix socket本地 Unix 套接字连接
localhostUnix socket + 127.0.0.1/32 + ::1/128本地回环地址
admin${admin_ip}/32管理员 IP 地址
infra所有 infra 组节点 IP基础设施节点列表
cluster当前集群所有成员 IP同一集群内的所有实例
intra / intranet10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16内网 CIDR 网段
world / all0.0.0.0/0 + ::/0任意地址(IPv4 + IPv6)
<CIDR>直接使用192.168.1.0/2410.1.1.100/32

内网 CIDR 可通过 node_firewall_intranet 参数自定义:

node_firewall_intranet:
  - 10.0.0.0/8
  - 172.16.0.0/12
  - 192.168.0.0/16

认证方式

Pigsty 提供认证方式别名,简化配置:

别名实际方式连接类型说明
pwdscram-sha-256md5host根据 pg_pwd_enc 自动选择
sslscram-sha-256md5hostssl强制 SSL + 密码
ssl-shascram-sha-256hostssl强制 SSL + SCRAM-SHA-256
ssl-md5md5hostssl强制 SSL + MD5
certcerthostssl客户端证书认证
trusttrusthost无条件信任(危险)
deny / rejectrejecthost拒绝连接
identidenthostOS 用户映射(PostgreSQL)
peerpeerlocalOS 用户映射(Pgbouncer/本地)

pg_pwd_enc 默认为 scram-sha-256,可设为 md5 以兼容老客户端。


用户变量

HBA 规则支持以下用户占位符,渲染时自动替换为实际用户名:

占位符默认值说明
${dbsu}postgres数据库超级用户
${repl}replicator复制用户
${monitor}dbuser_monitor监控用户
${admin}dbuser_dba管理员用户

这些变量的实际值由对应参数控制:

pg_dbsu: postgres
pg_replication_username: replicator
pg_monitor_username: dbuser_monitor
pg_admin_username: dbuser_dba

角色过滤

HBA 规则的 role 字段控制规则在哪些实例上生效:

角色说明
common默认值,所有实例都生效
primary仅主库实例生效
replica仅从库实例生效
offline仅离线实例生效(pg_role: offlinepg_offline_query: true
standby备库实例
delayed延迟从库实例

角色过滤基于实例的 pg_role 变量进行匹配。不匹配的规则会被注释掉(以 # 开头)。

pg_hba_rules:
  # 仅在主库生效
  - {user: writer, db: all, addr: intra, auth: pwd, role: primary, title: 'writer only on primary'}

  # 仅在离线实例生效
  - {user: '+dbrole_offline', db: all, addr: '172.20.0.0/16', auth: ssl, role: offline, title: 'offline dedicated'}

排序机制

PostgreSQL HBA 是首条匹配生效,规则顺序至关重要。Pigsty 通过 order 字段控制规则渲染顺序。

Order 区间约定

区间用途
0 - 99用户高优先规则(在所有默认规则之前)
100 - 650默认规则区(间隔 50,便于插入)
1000+用户规则默认值(不填 order 时追加到最后)

默认规则 Order 分配

PostgreSQL 默认规则

Order规则说明
100dbsu local ident
150dbsu replication local
200replicator localhost
250replicator intra replication
300replicator intra postgres
350monitor localhost
400monitor infra
450admin infra ssl
500admin world ssl
550dbrole_readonly localhost
600dbrole_readonly intra
650dbrole_offline intra

Pgbouncer 默认规则

Order规则说明
100dbsu local peer
150all localhost pwd
200monitor pgbouncer intra
250monitor world deny
300admin intra pwd
350admin world deny
400all intra pwd

排序示例

pg_hba_rules:
  # order: 0,在所有默认规则之前(黑名单)
  - {user: all, db: all, addr: '10.1.1.100/32', auth: deny, order: 0, title: 'blacklist bad ip'}

  # order: 120,在 dbsu(100) 和 replicator(200) 之间
  - {user: auditor, db: all, addr: local, auth: ident, order: 120, title: 'auditor access'}

  # order: 420,在 monitor(400) 和 admin(450) 之间
  - {user: exporter, db: all, addr: infra, auth: pwd, order: 420, title: 'prometheus exporter'}

  # 不填 order,默认 1000,追加到所有默认规则之后
  - {user: app_user, db: app_db, addr: intra, auth: pwd, title: 'app user access'}

写法示例

别名形式

使用 Pigsty 提供的简化语法:

pg_hba_rules:
  - title: allow grafana view access
    role: primary
    user: dbuser_view
    db: meta
    addr: infra
    auth: ssl

渲染结果:

# allow grafana view access [primary]
hostssl  meta               dbuser_view        10.10.10.10/32     scram-sha-256

原始形式

直接使用 PostgreSQL HBA 语法:

pg_hba_rules:
  - title: allow intranet password access
    role: common
    rules:
      - host all all 10.0.0.0/8 scram-sha-256
      - host all all 172.16.0.0/12 scram-sha-256
      - host all all 192.168.0.0/16 scram-sha-256

渲染结果:

# allow intranet password access [common]
host all all 10.0.0.0/8 scram-sha-256
host all all 172.16.0.0/12 scram-sha-256
host all all 192.168.0.0/16 scram-sha-256

常见配置示例

1. 内网密码访问业务库

pg_hba_rules:
  - title: 'intra readwrite access'
    role: common
    user: '+dbrole_readwrite'
    db: all
    addr: intra
    auth: pwd

效果:所有业务读写角色可以从内网网段使用密码访问任意数据库。

2. 离线实例专用网络

pg_hba_rules:
  - title: 'offline replica dedicated network'
    role: offline
    user: '+dbrole_offline'
    db: all
    addr: 172.20.0.0/16
    auth: ssl-sha

效果:仅 pg_role: offlinepg_offline_query: true 的实例启用该规则。

3. 黑名单 IP

pg_hba_rules:
  - user: all
    db: all
    addr: '10.1.1.100/32'
    auth: deny
    order: 0
    title: 'block compromised host'

效果:order: 0 排在所有默认规则(100+)之前,优先匹配并拒绝。

4. 白名单特定应用

pg_hba_rules:
  - title: 'allow app server access'
    user: app_user
    db: app_db
    addr: '192.168.1.10/32'
    auth: ssl
    order: 50

效果:特定应用服务器使用 SSL 连接,高优先级(50)确保在默认规则之前匹配。

5. 管理员强制证书认证

pg_hba_rules:
  - title: 'admin cert access'
    role: common
    user: '${admin}'
    db: all
    addr: world
    auth: cert
    order: 10

效果:管理员必须携带客户端证书才能连接,order: 10 优先于默认的 ssl 规则(450/500)。

6. 允许外网只读访问

pg_hba_rules:
  - title: 'readonly from internet'
    role: replica
    user: '+dbrole_readonly'
    db: all
    addr: world
    auth: ssl

效果:只读用户可从外网通过 SSL 连接从库。

7. Pgbouncer 专用规则

pgb_hba_rules:
  - title: 'app via pgbouncer'
    role: common
    user: '+dbrole_readwrite'
    db: all
    addr: world
    auth: ssl

注意:Pgbouncer HBA 不支持 db: replication

8. 多条件组合

pg_hba_rules:
  # 开发环境:信任本地连接
  - {user: all, db: all, addr: local, auth: trust, title: 'dev trust local'}

  # 生产环境:严格 SSL
  - {user: '+dbrole_readwrite', db: all, addr: intra, auth: ssl-sha, title: 'prod ssl only'}

  # 监控专用:从 Prometheus 节点
  - {user: '${monitor}', db: all, addr: infra, auth: pwd, order: 380, title: 'prometheus access'}

9. 按数据库限制访问

pg_hba_rules:
  # 财务系统:仅允许特定网段
  - {user: fin_user, db: finance_db, addr: '10.20.0.0/16', auth: ssl, title: 'finance restricted'}

  # HR 系统:仅允许 HR 网段
  - {user: hr_user, db: hr_db, addr: '10.30.0.0/16', auth: ssl, title: 'hr restricted'}

10. 完整集群配置示例

pg-prod:
  hosts:
    10.10.10.11: {pg_seq: 1, pg_role: primary}
    10.10.10.12: {pg_seq: 2, pg_role: replica}
    10.10.10.13: {pg_seq: 3, pg_role: offline}
  vars:
    pg_cluster: pg-prod

    pg_hba_rules:
      # 黑名单:已知恶意 IP
      - {user: all, db: all, addr: '10.1.1.100/32', auth: deny, order: 0, title: 'blacklist'}

      # 应用服务器白名单
      - {user: app_user, db: app_db, addr: '192.168.1.0/24', auth: ssl, order: 50, title: 'app servers'}

      # ETL 任务:仅离线实例
      - {user: etl_user, db: all, addr: '172.20.0.0/16', auth: pwd, role: offline, title: 'etl tasks'}

      # 监控增强
      - {user: '${monitor}', db: all, addr: cluster, auth: pwd, order: 380, title: 'cluster monitor'}

    pgb_hba_rules:
      # 应用通过连接池
      - {user: '+dbrole_readwrite', db: all, addr: '192.168.1.0/24', auth: ssl, title: 'app via pgbouncer'}

渲染原理

Pigsty 使用 Jinja2 模板渲染 HBA 配置文件:

  1. 合并规则pg_default_hba_rules + pg_hba_rules
  2. 排序规则:按 order 字段升序排列(无 order 的规则追加到最后)
  3. 角色过滤:根据实例 pg_role 筛选,不匹配的规则被注释
  4. 变量替换${dbsu} 等占位符替换为实际用户名
  5. 地址展开intrainfra 等别名展开为实际 IP/CIDR
  6. 认证映射pwdssl 等别名映射为实际认证方式

模板位置:

  • PostgreSQL:roles/pgsql/templates/pg_hba.conf
  • Pgbouncer:roles/pgsql/templates/pgbouncer.hba

注意事项

  1. 顺序敏感:PostgreSQL HBA 首条匹配生效,规则顺序很重要
  2. 角色匹配:确保 role 字段与目标实例的 pg_role 一致
  3. 地址验证:CIDR 格式必须正确,如 10.0.0.0/8 而非 10.0.0.0/255.0.0.0
  4. Pgbouncer 限制:不支持 db: replication
  5. 变量作用域:用户变量仅限预定义的四个(${dbsu}, ${repl}, ${monitor}, ${admin}
  6. SSL 配置:使用 sslcert 认证方式前确保 SSL 已正确配置
  7. 测试优先:修改 HBA 前建议先在测试环境验证

测试与验证

Pigsty 提供了 HBA order 排序功能的测试工具,可在部署前验证配置正确性:

运行排序逻辑测试

# 在 pigsty 目录下运行排序逻辑测试
./files/test-hba-order.yml

该测试验证:

  • 规则按 order 字段正确排序
  • order 字段的规则追加到末尾
  • 相同 order 值的规则保持原始顺序(稳定排序)
  • 向后兼容性(旧配置无需修改)

运行模板渲染测试

# 在目标服务器上测试 HBA 模板渲染
./files/test-hba-render.yml -l 10.10.10.10

该测试在目标服务器上渲染 HBA 模板,验证:

  • 模板语法正确
  • 规则顺序符合预期
  • 高优先级规则出现在前面

验证渲染结果

# 查看渲染后的 PostgreSQL HBA
cat /pg/data/pg_hba.conf

# 查看规则标题顺序(验证 order 生效)
grep '^#' /pg/data/pg_hba.conf | grep -v '^#=' | head -20

# 验证首条规则是否为预期的高优先级规则
head -30 /pg/data/pg_hba.conf

相关参数

参数说明
pg_pwd_enc密码加密方式:scram-sha-256(默认)或 md5
pg_dbsu数据库超级用户名
pg_replication_username复制用户名
pg_monitor_username监控用户名
pg_admin_username管理员用户名
node_firewall_intranet内网 CIDR 定义

相关文档

7 - 访问控制

Pigsty 提供的默认角色系统与权限模型

访问控制由“角色体系 + 权限模板 + HBA”共同决定。本节聚焦于如何通过配置参数声明角色与对象权限。

Pigsty 预置了一套精简的 ACL 模型,全部通过以下参数描述:

  • pg_default_roles:系统角色与系统用户。
  • pg_users:业务用户与角色。
  • pg_default_privileges:管理员/属主新建对象时的默认权限。
  • pg_revoke_publicpg_default_schemaspg_default_extensions:控制 template1 的默认行为。

理解这些参数后,你就可以写出完全可复现的权限配置。


默认角色体系(pg_default_roles)

默认包含 4 个业务角色 + 4 个系统用户:

名称类型说明
dbrole_readonlyNOLOGIN所有业务共用,拥有 SELECT/USAGE
dbrole_readwriteNOLOGIN继承只读角色,并拥有 INSERT/UPDATE/DELETE
dbrole_adminNOLOGIN继承 pg_monitor + 读写角色,可建对象和触发器
dbrole_offlineNOLOGIN受限只读角色,仅允许访问离线实例
postgres用户系统超级用户,与 pg_dbsu 同名
replicator用户用于流复制与备份,继承监控与只读权限
dbuser_dba用户主要管理员账号,同时同步到 pgbouncer
dbuser_monitor用户监控账号,具备 pg_monitor 权限,默认记录慢 SQL

这些定义位于 pg_default_roles,理论上可以自定义,但若要替换名称,必须同步更新 HBA/ACL/脚本中的引用。

示例:为离线任务额外加一个 dbrole_etl

pg_default_roles:
  - { name: dbrole_etl, login: false, roles: [dbrole_offline], comment: 'etl read-only role' }
  - { name: dbrole_admin, login: false, roles: [pg_monitor, dbrole_readwrite, dbrole_etl] }

效果:所有继承 dbrole_admin 的用户自动拥有 dbrole_etl 权限,可访问 offline 实例并执行 ETL。


默认用户与凭据参数

系统用户的用户名/密码由以下参数控制:

参数默认值作用
pg_dbsupostgres数据库/系统超级用户
pg_dbsu_password空字符串dbsu 密码(默认不启用)
pg_replication_usernamereplicator复制用户名称
pg_replication_passwordDBUser.Replicator复制用户密码
pg_admin_usernamedbuser_dba管理员用户名
pg_admin_passwordDBUser.DBA管理员密码
pg_monitor_usernamedbuser_monitor监控用户
pg_monitor_passwordDBUser.Monitor监控用户密码

如果修改这些参数,请同步在 pg_default_roles 中更新对应用户的定义,以避免角色属性不一致。


业务角色与授权(pg_users)

业务用户通过 pg_users 声明(详细字段见用户配置),其中 roles 字段控制授予的业务角色。

示例:创建只读/读写用户各一名:

pg_users:
  - { name: app_reader,  password: DBUser.Reader,  roles: [dbrole_readonly],  pgbouncer: true }
  - { name: app_writer,  password: DBUser.Writer,  roles: [dbrole_readwrite], pgbouncer: true }

通过继承 dbrole_* 来控制访问权限,无需为每个库单独 GRANT。配合 pg_hba_rules 即可区分访问来源。

若需要更细粒度的 ACL,可在 baseline SQL 中或后续剧本里使用标准 GRANT/REVOKE。Pigsty 不会阻止你额外授予权限。


默认权限模板(pg_default_privileges)

pg_default_privileges 会在 postgresdbuser_dbadbrole_admin(业务管理员 SET ROLE 后)上设置 DEFAULT PRIVILEGE。默认模板如下:

pg_default_privileges:
  - GRANT USAGE      ON SCHEMAS   TO dbrole_readonly
  - GRANT SELECT     ON TABLES    TO dbrole_readonly
  - GRANT SELECT     ON SEQUENCES TO dbrole_readonly
  - GRANT EXECUTE    ON FUNCTIONS TO dbrole_readonly
  - GRANT USAGE      ON SCHEMAS   TO dbrole_offline
  - GRANT SELECT     ON TABLES    TO dbrole_offline
  - GRANT SELECT     ON SEQUENCES TO dbrole_offline
  - GRANT EXECUTE    ON FUNCTIONS TO dbrole_offline
  - GRANT INSERT     ON TABLES    TO dbrole_readwrite
  - GRANT UPDATE     ON TABLES    TO dbrole_readwrite
  - GRANT DELETE     ON TABLES    TO dbrole_readwrite
  - GRANT USAGE      ON SEQUENCES TO dbrole_readwrite
  - GRANT UPDATE     ON SEQUENCES TO dbrole_readwrite
  - GRANT TRUNCATE   ON TABLES    TO dbrole_admin
  - GRANT REFERENCES ON TABLES    TO dbrole_admin
  - GRANT TRIGGER    ON TABLES    TO dbrole_admin
  - GRANT CREATE     ON SCHEMAS   TO dbrole_admin

只要对象由上述管理员创建,就会自动携带对应权限,无需人为执行 GRANT。若业务需要自定义模板,直接替换该数组即可。

额外提示:

  • pg_revoke_public 默认为 true,意味着自动撤销 PUBLIC 在数据库和 public schema 上的 CREATE 权限。
  • pg_default_schemaspg_default_extensions 控制在 template1/postgres 中预创建的 schema/扩展,通常用于监控对象(monitor schema、pg_stat_statements 等)。

常见配置场景

为合作方提供只读账号

pg_users:
  - name: partner_ro
    password: Partner.Read
    roles: [dbrole_readonly]
pg_hba_rules:
  - { user: partner_ro, db: analytics, addr: 203.0.113.0/24, auth: ssl }

效果:合作方账号登录后只具备默认只读权限,并且只能通过 TLS 从指定网段访问 analytics 库。

为业务管理员赋予 DDL 能力

pg_users:
  - name: app_admin
    password: DBUser.AppAdmin
    roles: [dbrole_admin]

业务管理员通过 SET ROLE dbrole_admin 或直接以 app_admin 登录,即可继承默认的 DDL 权限模板。

自定义默认权限

pg_default_privileges:
  - GRANT INSERT,UPDATE,DELETE ON TABLES TO dbrole_admin
  - GRANT SELECT,UPDATE ON SEQUENCES TO dbrole_admin
  - GRANT SELECT ON TABLES TO reporting_group

替换默认模板后,所有由管理员创建的对象都会携带新的权限定义,避免逐对象授权。


与其他组件的协同

  • HBA 规则:使用 pg_hba_rules 将角色与来源进行绑定(例如只让 dbrole_offline 访问离线实例)。
  • Pgbouncerpgbouncer: true 的用户会被写入 userlist.txtpool_mode/pool_connlimit 可以控制连接池层面的配额。
  • Grafana/监控dbuser_monitor 的权限来自 pg_default_roles,如果你新增监控用户,记得赋予 pg_monitor + monitor schema 的访问权。

通过这些参数,可以让权限体系与代码一起版本化,真正做到“配置即策略”。