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 保持一致。
使用以下命令创建该集群:
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_rules和pg_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.yml 与 prod.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,高可用 + 复制 |
citus | Citus 分布式集群,需要额外的 pg_shard / pg_group |
gpsql | Greenplum / MatrixDB |
mssql | Babelfish for PostgreSQL |
mysql | OpenGauss/HaloDB 兼容 MySQL 协议 |
polar | 阿里 PolarDB(基于 pg polar 发行) |
ivory | IvorySQL(Oracle 兼容语法) |
oriole | OrioleDB 存储引擎 |
oracle | PostgreSQL + 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:控制初始化脚本对 template1 与 postgres 预创建的 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_17,postgis36_17* 这样的格式 - Debian/Ubuntu 系统使用
postgresql-17-pgvector,postgresql-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-$v | postgresql-17 |
postgresql-$v-pgvector | postgresql-17-pgvector |
postgresql-$v-timescaledb-tsl | postgresql-17-timescaledb-tsl |
通配符匹配
在 EL 系统上,许多别名使用 * 通配符来匹配相关的子包。例如:
postgis36_17* 会匹配 postgis36_17、postgis36_17-client、postgis36_17-utils 等postgresql17* 会匹配 postgresql17、postgresql17-server、postgresql17-libs、postgresql17-contrib 等
这种设计确保您无需逐一列出每个子包,一个别名即可安装完整的扩展。
4 - 用户/角色
用户/角色指的是使用 SQL 命令 CREATE USER/ROLE 创建的,数据库集簇内的逻辑对象。
在这里的上下文中,用户指的是使用 SQL 命令 CREATE USER/ROLE 创建的,数据库集簇内的逻辑对象。
在PostgreSQL中,用户直接隶属于数据库集簇而非某个具体的数据库。因此在创建业务数据库和业务用户时,应当遵循"先用户,后数据库"的原则。
定义用户
Pigsty通过两个配置参数定义数据库集群中的角色与用户:
前者用于定义了整套环境中共用的角色与用户,后者定义单个集群中特有的业务角色与用户。二者形式相同,均为用户定义对象的数组。
你可以定义多个用户/角色,它们会按照先全局,后集群,最后按数组内排序的顺序依次创建,所以后面的用户可以属于前面定义的角色。
下面是 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 哈希字符串,请最好不要使用明文密码。- 用户/角色按数组顺序逐一创建,因此,请确保角色/分组的定义在成员之前。
login、superuser、createdb、createrole、inherit、replication、bypassrls 是布尔标志。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 - 可选值:
create、absent - 说明:用户目标状态
| 状态 | 说明 |
|---|
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:' + ...)"
- 类型:
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
格式为 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 角色成员关系
对象格式参数
| 参数 | 类型 | 说明 |
|---|
name | string | 角色名称(必选) |
state | enum | grant(默认)或 absent/revoke:控制成员关系 |
admin | bool | true: WITH ADMIN OPTION / false: REVOKE ADMIN |
set | bool | PG16+: true: WITH SET TRUE / false: REVOKE SET |
inherit | bool | PG16+: 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 }
注意:set 和 inherit 选项仅在 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_path | Schema 搜索路径 | 'app,public' |
log_statement | 日志记录级别 | 'ddl' |
temp_file_limit | 临时文件大小限制 | '10GB' |
连接池参数
这些参数控制用户在 Pgbouncer 连接池中的行为。
pgbouncer
- 类型:
bool - 可变性:可变
- 默认值:
false - 说明:是否将用户添加到 Pgbouncer 用户列表
重要
对于需要通过连接池访问数据库的生产用户,必须显式设置 pgbouncer: true。
默认为 false 是为了避免意外将内部用户暴露给连接池。
# 生产用户:需要连接池
- name: dbuser_app
password: DBUser.App
pgbouncer: true
# 内部用户:不需要连接池
- name: dbuser_internal
password: DBUser.Internal
pgbouncer: false # 默认值,可省略
pool_mode
- 类型:
enum - 可变性:可变
- 可选值:
transaction、session、statement - 默认值:
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(默认)、absent、recreate |
owner | 基本 | string | 可变 | 数据库属主,不指定则为 postgres |
comment | 基本 | string | 可变 | 数据库备注信息 |
template | 模板 | string | 不可变 | 创建时使用的模板数据库,默认 template1 |
strategy | 模板 | enum | 不可变 | 克隆策略:FILE_COPY 或 WAL_LOG(PG15+) |
encoding | 编码 | string | 不可变 | 字符编码,默认继承模板(UTF8) |
locale | 编码 | string | 不可变 | 本地化规则,默认继承模板(C) |
lc_collate | 编码 | string | 不可变 | 排序规则,默认继承模板(C) |
lc_ctype | 编码 | string | 不可变 | 字符分类,默认继承模板(C) |
locale_provider | 编码 | enum | 不可变 | 本地化提供者:libc、icu、builtin(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 - 可选值:
create、absent、recreate - 说明:数据库目标状态
| 状态 | 说明 |
|---|
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";
- 类型:
string - 可变性:可变
- 默认值:
business database {name} - 说明:数据库备注信息
会执行 COMMENT ON DATABASE 语句。支持中文和特殊字符(会自动转义单引号)。
模板与克隆参数
template
- 类型:
string - 可变性:不可变
- 默认值:
template1 - 说明:创建数据库时使用的模板
常用模板:
| 模板 | 说明 |
|---|
template1 | 默认模板,包含 Pigsty 预配置的扩展和权限 |
template0 | 干净模板,用于指定不同编码或本地化设置时必须使用 |
| 自定义数据库 | 可以使用已有数据库作为模板克隆 |
重要:使用 icu 或 builtin 本地化提供者时,必须指定 template: template0。
- name: myapp_icu
template: template0 # 使用 ICU 时必须
locale_provider: icu
icu_locale: en-US
strategy
- 类型:
enum - 可变性:不可变
- 版本要求:PostgreSQL 15+
- 可选值:
FILE_COPY、WAL_LOG - 说明:从模板克隆数据库的策略
| 策略 | 说明 | 适用场景 |
|---|
FILE_COPY | 直接复制数据文件(PG15+ 默认) | 大模板,通用场景 |
WAL_LOG | 通过 WAL 日志复制 | 小模板,不阻塞连接 |
在 PostgreSQL 14 及更早版本中,此参数会被忽略。
编码与本地化参数
encoding
- 类型:
string - 可变性:不可变
- 默认值:继承模板(通常为
UTF8) - 说明:数据库字符编码
常用编码:UTF8、LATIN1、SQL_ASCII
locale
- 类型:
string - 可变性:不可变
- 默认值:继承模板(通常为
C) - 说明:数据库本地化规则,同时设置
lc_collate 和 lc_ctype
lc_collate
- 类型:
string - 可变性:不可变
- 默认值:继承模板(通常为
C) - 说明:字符串排序规则
常用值:C、C.UTF-8、en_US.UTF-8、zh_CN.UTF-8
lc_ctype
- 类型:
string - 可变性:不可变
- 默认值:继承模板(通常为
C) - 说明:字符分类规则(大小写、数字等)
locale_provider
- 类型:
enum - 可变性:不可变
- 版本要求:PostgreSQL 15+
- 可选值:
libc、icu、builtin - 默认值:
libc - 说明:本地化实现提供者
| 提供者 | 版本 | 说明 |
|---|
libc | - | 使用操作系统 C 库,传统默认方式 |
icu | PG15+ | 使用 ICU 库,跨平台一致 |
builtin | PG17+ | PostgreSQL 内置实现,最高效的 C/C.UTF-8 |
注意:使用 icu 或 builtin 时,必须指定 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+
- 可选值:
C、C.UTF-8 - 说明:内置本地化提供者的规则
builtin 提供者比 libc 更快,特别适合只需要 C 或 C.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 时:
- 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 - 可变性:可变
- 可选值:
transaction、session、statement - 默认值:
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
需要启用 pgbouncer_auth_query 后生效。
指定后,所有到此数据库的连接都会使用该用户查询密码。
监控参数
register_datasource
- 类型:
bool - 可变性:可变
- 默认值:
true - 说明:是否注册到 Grafana 数据源
设置为 false 可以跳过 Grafana 数据源注册,适用于不需要监控的临时数据库。
模板继承
许多参数如果不显式指定,会从模板数据库继承。默认模板是 template1,其编码设置由集群初始化参数决定:
新创建的数据库默认会从 template1 数据库 Fork 出来,这个模版数据库会在 PG_PROVISION 阶段进行定制修改:
配置好扩展、模式以及默认权限,因此新创建的数据库也会继承这些配置,除非您显式使用一个其他的数据库作为模板。
关于数据库管理操作,请参考 数据库管理 一节。
关于数据库的访问权限,请参考 ACL:数据库权限 一节。
6 - HBA 规则
Pigsty 中 PostgreSQL 与 Pgbouncer 的 HBA(Host-Based Authentication)规则配置详解。
HBA(Host-Based Authentication)控制"谁可以从哪里、以什么方式连接到数据库"。
Pigsty 通过 pg_default_hba_rules 与 pg_hba_rules 让 HBA 规则也能以声明式配置形式管理。
概述
Pigsty 在集群初始化或 HBA 刷新时渲染以下配置文件:
| 配置文件 | 路径 | 说明 |
|---|
| PostgreSQL HBA | /pg/data/pg_hba.conf | PostgreSQL 服务器的 HBA 规则 |
| Pgbouncer HBA | /etc/pgbouncer/pgb_hba.conf | 连接池 Pgbouncer 的 HBA 规则 |
HBA 规则由以下参数控制:
规则特性:
- 按角色过滤:规则支持
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 字典,支持以下字段:
| 字段 | 类型 | 必需 | 默认值 | 说明 |
|---|
user | string | 否 | all | 用户名,支持 all、变量占位符、+rolename 等 |
db | string | 否 | all | 数据库名,支持 all、replication、具体库名 |
addr | string | 是* | - | 地址别名或 CIDR,见地址别名 |
auth | string | 否 | pwd | 认证方式别名,见认证方式 |
title | string | 否 | - | 规则说明/注释,会渲染为配置文件中的注释 |
role | string | 否 | common | 实例角色过滤,见角色过滤 |
order | int | 否 | 1000 | 排序权重,数字小的排前面,见排序机制 |
rules | list | 是* | - | 原始 HBA 文本行列表,与 addr 二选一 |
addr 和 rules 必须指定其一。使用 rules 时可以直接写原始 HBA 格式。
地址别名
Pigsty 提供地址别名,简化 HBA 规则编写:
| 别名 | 展开为 | 说明 |
|---|
local | Unix socket | 本地 Unix 套接字连接 |
localhost | Unix socket + 127.0.0.1/32 + ::1/128 | 本地回环地址 |
admin | ${admin_ip}/32 | 管理员 IP 地址 |
infra | 所有 infra 组节点 IP | 基础设施节点列表 |
cluster | 当前集群所有成员 IP | 同一集群内的所有实例 |
intra / intranet | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 | 内网 CIDR 网段 |
world / all | 0.0.0.0/0 + ::/0 | 任意地址(IPv4 + IPv6) |
<CIDR> | 直接使用 | 如 192.168.1.0/24、10.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 提供认证方式别名,简化配置:
| 别名 | 实际方式 | 连接类型 | 说明 |
|---|
pwd | scram-sha-256 或 md5 | host | 根据 pg_pwd_enc 自动选择 |
ssl | scram-sha-256 或 md5 | hostssl | 强制 SSL + 密码 |
ssl-sha | scram-sha-256 | hostssl | 强制 SSL + SCRAM-SHA-256 |
ssl-md5 | md5 | hostssl | 强制 SSL + MD5 |
cert | cert | hostssl | 客户端证书认证 |
trust | trust | host | 无条件信任(危险) |
deny / reject | reject | host | 拒绝连接 |
ident | ident | host | OS 用户映射(PostgreSQL) |
peer | peer | local | OS 用户映射(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: offline 或 pg_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 | 规则说明 |
|---|
| 100 | dbsu local ident |
| 150 | dbsu replication local |
| 200 | replicator localhost |
| 250 | replicator intra replication |
| 300 | replicator intra postgres |
| 350 | monitor localhost |
| 400 | monitor infra |
| 450 | admin infra ssl |
| 500 | admin world ssl |
| 550 | dbrole_readonly localhost |
| 600 | dbrole_readonly intra |
| 650 | dbrole_offline intra |
Pgbouncer 默认规则:
| Order | 规则说明 |
|---|
| 100 | dbsu local peer |
| 150 | all localhost pwd |
| 200 | monitor pgbouncer intra |
| 250 | monitor world deny |
| 300 | admin intra pwd |
| 350 | admin world deny |
| 400 | all 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: offline 或 pg_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 配置文件:
- 合并规则:
pg_default_hba_rules + pg_hba_rules - 排序规则:按
order 字段升序排列(无 order 的规则追加到最后) - 角色过滤:根据实例
pg_role 筛选,不匹配的规则被注释 - 变量替换:
${dbsu} 等占位符替换为实际用户名 - 地址展开:
intra、infra 等别名展开为实际 IP/CIDR - 认证映射:
pwd、ssl 等别名映射为实际认证方式
模板位置:
- PostgreSQL:
roles/pgsql/templates/pg_hba.conf - Pgbouncer:
roles/pgsql/templates/pgbouncer.hba
注意事项
- 顺序敏感:PostgreSQL HBA 首条匹配生效,规则顺序很重要
- 角色匹配:确保
role 字段与目标实例的 pg_role 一致 - 地址验证:CIDR 格式必须正确,如
10.0.0.0/8 而非 10.0.0.0/255.0.0.0 - Pgbouncer 限制:不支持
db: replication - 变量作用域:用户变量仅限预定义的四个(
${dbsu}, ${repl}, ${monitor}, ${admin}) - SSL 配置:使用
ssl、cert 认证方式前确保 SSL 已正确配置 - 测试优先:修改 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_public、pg_default_schemas、pg_default_extensions:控制 template1 的默认行为。
理解这些参数后,你就可以写出完全可复现的权限配置。
默认角色体系(pg_default_roles)
默认包含 4 个业务角色 + 4 个系统用户:
| 名称 | 类型 | 说明 |
|---|
dbrole_readonly | NOLOGIN | 所有业务共用,拥有 SELECT/USAGE |
dbrole_readwrite | NOLOGIN | 继承只读角色,并拥有 INSERT/UPDATE/DELETE |
dbrole_admin | NOLOGIN | 继承 pg_monitor + 读写角色,可建对象和触发器 |
dbrole_offline | NOLOGIN | 受限只读角色,仅允许访问离线实例 |
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_dbsu | postgres | 数据库/系统超级用户 |
pg_dbsu_password | 空字符串 | dbsu 密码(默认不启用) |
pg_replication_username | replicator | 复制用户名称 |
pg_replication_password | DBUser.Replicator | 复制用户密码 |
pg_admin_username | dbuser_dba | 管理员用户名 |
pg_admin_password | DBUser.DBA | 管理员密码 |
pg_monitor_username | dbuser_monitor | 监控用户 |
pg_monitor_password | DBUser.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 会在 postgres、dbuser_dba、dbrole_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_schemas 和 pg_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 访问离线实例)。 - Pgbouncer:
pgbouncer: true 的用户会被写入 userlist.txt,pool_mode/pool_connlimit 可以控制连接池层面的配额。 - Grafana/监控:
dbuser_monitor 的权限来自 pg_default_roles,如果你新增监控用户,记得赋予 pg_monitor + monitor schema 的访问权。
通过这些参数,可以让权限体系与代码一起版本化,真正做到“配置即策略”。