这是本节的多页打印视图。
点击此处打印.
返回本页常规视图.
集群配置
根据需求场景选择合适的实例与集群类型,配置出满足需求的 PostgreSQL 数据库集群。
Pigsty 是一个“配置驱动”的 PostgreSQL 平台:所有行为都来自 ~/pigsty/conf/*.yml 清单与 PGSQL 参数 的组合。
只要写好配置,你就能在几分钟内复刻出一套包含实例、用户、数据库、访问控制、扩展与调优策略的定制集群。
配置入口
- 准备清单:复制
pigsty/conf/*.yml 模板或从零开始编写 Ansible Inventory,将集群分组(all.children.<cls>.hosts)与全局变量(all.vars)写入同一个文件。 - 定义参数:在
vars 区块中覆盖需要的 PGSQL 参数。全局 → 集群 → 主机的覆盖顺序决定了最终值。 - 应用配置:运行
./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_version、pg_mode、pg_packages、pg_extensions、pg_conf 等参数挑选核心版本、风味和调优模板。 - 用户/角色:在
pg_default_roles 与 pg_users 中声明系统角色、业务账号、密码策略以及连接池属性。 - 数据库对象:借助
pg_databases、baseline、schemas、extensions、pool_* 字段按需创建数据库并自动接入 pgbouncer/Grafana。 - 访问控制 (HBA):利用
pg_default_hba_rules 与 pg_hba_rules 维护主机级认证策略,保证不同角色/网络的访问边界。 - 权限模型 (ACL):通过
pg_default_privileges、pg_default_roles、pg_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_databases 与 pg_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 保持一致。
使用以下命令创建该集群:
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-test2 }
你还可以在现有的备份集群上配置一个“复制延迟”。
$ 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
patroni_citus_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 }
每个用户/角色定义都是一个 object,可能包括以下字段,以 dbuser_meta 用户为例:
- name: dbuser_meta # 必需,`name` 是用户定义的唯一必选字段
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` 针对这个角色,配置角色级的数据库参数
pool_mode: transaction # 可选,默认为 transaction 的 pgbouncer 池模式,用户级别
pool_connlimit: -1 # 可选,用户级别的最大数据库连接数,默认 -1 禁用限制
search_path: public # 可选,根据 postgresql 文档的键值配置参数(例如:使用 pigsty 作为默认 search_path)
- 唯一必需的字段是
name,它应该是 PostgreSQL 集群中的一个有效且唯一的用户名。 - 角色不需要
password,但对于可登录的业务用户,通常是需要指定一个密码的。 password 可以是明文或 scram-sha-256 / md5 哈希字符串,请最好不要使用明文密码。- 用户/角色按数组顺序逐一创建,因此,请确保角色/分组的定义在成员之前。
login、superuser、createdb、createrole、inherit、replication、bypassrls 是布尔标志。pgbouncer 默认是禁用的:要将业务用户添加到 pgbouncer 用户列表,您应当显式将其设置为 true。
ACL系统
Pigsty 具有一套内置的,开箱即用的访问控制 / ACL 系统,您只需将以下四个默认角色分配给业务用户即可轻松使用:
dbrole_readwrite:全局读写访问的角色(主属业务使用的生产账号应当具有数据库读写权限)dbrole_readonly:全局只读访问的角色(如果别的业务想要只读访问,可以使用此角色)dbrole_admin:拥有DDL权限的角色 (业务管理员,需要在应用中建表的场景)dbrole_offline:受限的只读访问角色(只能访问 offline 实例,通常是个人用户)
如果您希望重新设计您自己的 ACL 系统,可以考虑定制以下参数和模板:
创建用户
在 pg_default_roles 和 pg_users 中定义的用户和角色,将在集群初始化的 PROVISION 阶段中自动逐一创建。
如果您希望在现有的集群上创建用户,可以使用 bin/pgsql-user 工具。
将新用户/角色定义添加到 all.children.<cls>.pg_users,并使用以下方法创建该数据库:
bin/pgsql-user <cls> <username> # pgsql-user.yml -l <cls> -e username=<username>
不同于数据库,创建用户的剧本总是幂等的。当目标用户已经存在时,Pigsty会修改目标用户的属性使其符合配置。所以在现有集群上重复运行它通常不会有问题。
请使用剧本创建用户
我们不建议您手工创建新的业务用户,特别当您想要创建的用户使用默认的 pgbouncer 连接池时:除非您愿意手工负责维护 Pgbouncer 中的用户列表并与 PostgreSQL 保持一致。
使用 bin/pgsql-user 工具或 pgsql-user.yml 剧本创建新数据库时,会将此数据库一并添加到 Pgbouncer用户 列表中。
修改用户
修改 PostgreSQL 用户的属性的方式与 创建用户 相同。
首先,调整您的用户定义,修改需要调整的属性,然后执行以下命令应用:
bin/pgsql-user <cls> <username> # pgsql-user.yml -l <cls> -e username=<username>
请注意,修改用户不会删除用户,而是通过 ALTER USER 命令修改用户属性;也不会回收用户的权限与分组,并使用 GRANT 命令授予新的角色。
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="
"dbuser_kong" "SCRAM-SHA-256$4096:bK8sLXIieMwFDz67/0dqXQ==$P/tCRgyKx9MC9LH3ErnKsnlOqgNd/nn2RyvThyiK6e4=:CDM8QZNHBdPf97ztusgnE7olaKDNHBN0WeAbP/nzu5A="
"dbuser_grafana" "SCRAM-SHA-256$4096:HjLdGaGmeIAGdWyn2gDt/Q==$jgoyOB8ugoce+Wqjr0EwFf8NaIEMtiTuQTg1iEJs9BM=:ed4HUFqLyB4YpRr+y25FBT7KnlFDnan6JPVT9imxzA4="
"dbuser_gitea" "SCRAM-SHA-256$4096:l1DBGCc4dtircZ8O8Fbzkw==$tpmGwgLuWPDog8IEKdsaDGtiPAxD16z09slvu+rHE74=:pYuFOSDuWSofpD9OZhG7oWvyAR0PQjJBffgHZLpLHds="
"dbuser_dba" "SCRAM-SHA-256$4096:zH8niABU7xmtblVUo2QFew==$Zj7/pq+ICZx7fDcXikiN7GLqkKFA+X5NsvAX6CMshF0=:pqevR2WpizjRecPIQjMZOm+Ap+x0kgPL2Iv5zHZs0+g="
"dbuser_bytebase" "SCRAM-SHA-256$4096:OMoTM9Zf8QcCCMD0svK5gg==$kMchqbf4iLK1U67pVOfGrERa/fY818AwqfBPhsTShNQ=:6HqWteN+AadrUnrgC0byr5A72noqnPugItQjOLFw0Wk="
而用户级别的连接池参数则是使用另一个单独的文件: /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 管理功能。
Pigsty 还提供了一个实用函数 pgb-route ,可以将 pgbouncer 数据库流量快速切换至集群中的其他节点,用于零停机迁移:
连接池用户配置文件 userlist.txt 与 useropts.txt 会在您创建用户时自动刷新,并通过在线重载配置的方式生效,正常不会影响现有的连接。
请注意,pgbouncer_auth_query 参数允许你使用动态查询来完成连接池用户认证,当您懒得管理连接池中的用户时,这是一种折中的方案。
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` 是数据库定义的唯一必选字段
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 # 可选,数据库所有者,默认为 postgres
template: template1 # 可选,要使用的模板,默认为 template1,目标必须是一个模板数据库
encoding: UTF8 # 可选,数据库编码,默认为 UTF8(必须与模板数据库相同)
locale: C # 可选,数据库地区设置,默认为 C(必须与模板数据库相同)
lc_collate: C # 可选,数据库 collate 排序规则,默认为 C(必须与模板数据库相同),没有理由不建议更改。
lc_ctype: C # 可选,数据库 ctype 字符集,默认为 C(必须与模板数据库相同)
tablespace: pg_default # 可选,默认表空间,默认为 'pg_default'
allowconn: true # 可选,是否允许连接,默认为 true。显式设置 false 将完全禁止连接到此数据库
revokeconn: false # 可选,撤销公共连接权限。默认为 false,设置为 true 时,属主和管理员之外用户的 CONNECT 权限会被回收
register_datasource: true # 可选,是否将此数据库注册到 grafana 数据源?默认为 true,显式设置为 false 会跳过注册
connlimit: -1 # 可选,数据库连接限制,默认为 -1 ,不限制,设置为正整数则会限制连接数。
pool_auth_user: dbuser_meta # 可选,连接到此 pgbouncer 数据库的所有连接都将使用此用户进行验证(启用 pgbouncer_auth_query 才有用)
pool_mode: transaction # 可选,数据库级别的 pgbouncer 池化模式,默认为 transaction
pool_size: 64 # 可选,数据库级别的 pgbouncer 默认池子大小,默认为 64
pool_size_reserve: 32 # 可选,数据库级别的 pgbouncer 池子保留空间,默认为 32,当默认池子不够用时,最多再申请这么多条突发连接。
pool_size_min: 0 # 可选,数据库级别的 pgbouncer 池的最小大小,默认为 0
pool_max_db_conn: 100 # 可选,数据库级别的最大数据库连接数,默认为 100
唯一必选的字段是 name,它应该是当前 PostgreSQL 集群中有效且唯一的数据库名称,其他参数都有合理的默认值。
name:数据库名称,必选项。baseline:SQL文件路径(Ansible搜索路径,通常位于files),用于初始化数据库内容。owner:数据库属主,默认为postgrestemplate:数据库创建时使用的模板,默认为template1encoding:数据库默认字符编码,默认为UTF8,默认与实例保持一致。建议不要配置与修改。locale:数据库默认的本地化规则,默认为C,建议不要配置,与实例保持一致。lc_collate:数据库默认的本地化字符串排序规则,默认与实例设置相同,建议不要修改,必须与模板数据库一致。强烈建议不要配置,或配置为C。lc_ctype:数据库默认的LOCALE,默认与实例设置相同,建议不要修改或设置,必须与模板数据库一致。建议配置为C或en_US.UTF8。allowconn:是否允许连接至数据库,默认为true,不建议修改。revokeconn:是否回收连接至数据库的权限?默认为false。如果为true,则数据库上的PUBLIC CONNECT权限会被回收。只有默认用户(dbsu|monitor|admin|replicator|owner)可以连接。此外,admin|owner 会拥有GRANT OPTION,可以赋予其他用户连接权限。tablespace:数据库关联的表空间,默认为pg_default。connlimit:数据库连接数限制,默认为-1,即没有限制。extensions:对象数组 ,每一个对象定义了一个数据库中的扩展,以及其安装的模式。parameters:KV对象,每一个KV定义了一个需要针对数据库通过ALTER DATABASE修改的参数。pgbouncer:布尔选项,是否将该数据库加入到Pgbouncer中。所有数据库都会加入至Pgbouncer列表,除非显式指定pgbouncer: false。comment:数据库备注信息。pool_auth_user:启用 pgbouncer_auth_query 时,连接到此 pgbouncer 数据库的所有连接都将使用这里指定的用户执行认证查询。你需要使用一个具有访问 pg_shadow 表权限的用户。pool_mode:数据库级别的 pgbouncer 池化模式,默认为 transaction,即事物池化。如果留空,会使用 pgbouncer_poolmode 参数作为默认值。pool_size:数据库级别的 pgbouncer 默认池子大小,默认为 64pool_size_reserve:数据库级别的 pgbouncer 池子保留空间,默认为 32,当默认池子不够用时,最多再申请这么多条突发连接。pool_size_min: 数据库级别的 pgbouncer 池的最小大小,默认为 0pool_max_db_conn: 数据库级别的 pgbouncer 连接池最大数据库连接数,默认为 100
新创建的数据库默认会从 template1 数据库 Fork 出来,这个模版数据库会在 PG_PROVISION 阶段进行定制修改:
配置好扩展,模式以及默认权限,因此新创建的数据库也会继承这些配置,除非您显式使用一个其他的数据库作为模板。
关于数据库的访问权限,请参考 ACL:数据库权限 一节。
6 - HBA 认证
Pigsty 中基于主机的身份认证 HBA(Host-Based Authentication)配置详解。
HBA(Host-Based Authentication)控制“谁可以从哪里、以什么方式连接到数据库”。Pigsty 通过 pg_default_hba_rules 与 pg_hba_rules 让 HBA 规则也能以配置形式管理。
Pigsty 会在初始化时渲染 /pg/data/pg_hba.conf 与 /etc/pgbouncer/pg_hba.conf,其中:
pg_default_hba_rules:全局默认规则,通常位于 all.vars。pg_hba_rules:集群/业务级追加规则,在 all.children.<cls>.vars 或主机 vars 中覆盖。pgb_default_hba_rules / pgb_hba_rules:连接池 pgbouncer 的 HBA 规则。- 规则支持按实例角色生效(
role: primary/replica/offline/common),Pigsty 会根据实例的 pg_role 自动筛选。
写法:原始形式与别名形式
每条规则由 title、role 和 rules/别名字段组成:
pg_hba_rules:
- title: allow intranet password access # 注释
role: common # 作用在哪类实例?
rules: # 原始 HBA 文本
- host all all 10.0.0.0/8 md5
- host all all 172.16.0.0/12 md5
为了简化常见配置,可以使用别名形式:
- title: allow grafana view access
role: primary
user: dbuser_view # user/all/${dbsu}/+group
db: meta # all/replication/指定库
addr: infra # world/intra/infra/admin/local/localhost/cluster/<cidr>
auth: ssl # trust/pwd/md5/scram/ssl/ssl-md5/ssl-sha/peer/cert/deny
addr:支持别名(world/intra/infra/admin/local/localhost/cluster)或 10.0.0.0/24 形式的网络。auth:pwd 会根据 pg_pwd_enc 自动使用 md5 或 scram-sha-256;ssl/ssl-md5/ssl-sha 会强制要求 SSL。user:可以是单个用户名、${admin} 等内置变量,或 +dbrole_readonly 这样的角色组。db:指定数据库名称或 all/replication。role:common(所有实例)、primary、replica、offline。- 若同时指定
rules 与别名字段,以 rules 为准。
Pigsty 提供的变量占位符:${dbsu}、${admin}、${monitor}、${repl} 等,会在渲染时替换为当前参数值。
常见配置示例
1. 只允许内网密码访问业务库
pg_hba_rules:
- { title: 'intra readwrite access', role: common,
user: '+dbrole_readwrite', db: all, addr: intra, auth: pwd }
效果:所有业务读写角色可以从内网网段(默认 10/8,172.16/12,192.168/16,可通过 node_firewall_intranet 调整)使用密码访问任意数据库。
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 的实例会增添该规则,要求离线角色从指定网段以 SSL + SCRAM 连接。
3. 管理员强制使用客户端证书
pg_hba_rules:
- title: 'admin cert access'
role: common
user: '${admin}'
db: all
addr: world
auth: cert
效果:管理员角色必须携带客户端证书才能从任意来源连接,可搭配 ssl_cafile 与 patroni_watchdog_mode 构建更严格的访问链。
4. pgbouncer 单独控制
pgb_hba_rules:
- { title: 'app via pgbouncer', role: common,
user: '+dbrole_readwrite', db: all, addr: world, auth: ssl }
效果:pgbouncer 的 HBA 会允许来自任意网段的业务应用接入连接池,但必须在 TLS 隧道下并使用密码认证。
刷新 HBA
修改规则后需要让 PostgreSQL/pgbouncer 重新加载配置:
bin/pgsql-hba <cls> # 重新生成并 reload 集群的 pg_hba.conf
bin/pgsql-hba <cls> ip1 ip2... # 只针对特定实例执行
上述命令内部等价于:
./pgsql.yml -l <cls> -e pg_reload=true -t pg_hba,pg_reload
./pgsql.yml -l <cls> -e pg_reload=true -t pgbouncer_hba,pgbouncer_reload
建议在新增/下线实例、切换主从或修改角色访问范围后立即执行刷新。
默认规则参考
Pigsty 内置的 pg_default_hba_rules 能覆盖绝大多数场景:
pg_default_hba_rules:
- {user: '${dbsu}', db: all, addr: local, auth: ident, title: 'dbsu via local ident' }
- {user: '${dbsu}', db: replication, addr: local, auth: ident, title: 'dbsu local replication'}
- {user: '${repl}', db: replication, addr: localhost, auth: pwd, title: 'replication from localhost'}
- {user: '${repl}', db: replication, addr: intra, auth: pwd, title: 'replication from intranet' }
- {user: '${monitor}', db: all, addr: localhost, auth: pwd, title: 'monitor local password' }
- {user: '${monitor}', db: all, addr: infra, auth: pwd, title: 'monitor infra password' }
- {user: '${admin}', db: all, addr: infra, auth: ssl, title: 'admin infra ssl+pwd' }
- {user: '${admin}', db: all, addr: world, auth: ssl, title: 'admin world ssl+pwd' }
- {user: '+dbrole_readonly',db: all, addr: localhost, auth: pwd, title: 'pgbouncer local access' }
- {user: '+dbrole_readonly',db: all, addr: intra, auth: pwd, title: 'biz users via intranet' }
- {user: '+dbrole_offline', db: all, addr: intra, auth: pwd, title: 'offline jobs via intranet'}
pgbouncer 默认规则也已经封装常见需求:
pgb_default_hba_rules:
- {user: '${dbsu}', db: pgbouncer, addr: local, auth: peer, title: 'dbsu local admin'}
- {user: 'all', db: all, addr: localhost, auth: pwd, title: 'local clients'}
- {user: '${monitor}',db: all, addr: world, auth: deny, title: 'block monitor world'}
- {user: '${admin}', db: all, addr: intra, auth: pwd, title: 'admin via infra'}
- {user: 'all', db: all, addr: intra, auth: pwd, title: 'business via intranet'}
直接在 pg_hba_rules/pgb_hba_rules 中增删条目即可实现差异化访问控制,无需手工编辑 pg_hba.conf。
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 的访问权。
通过这些参数,可以让权限体系与代码一起版本化,真正做到“配置即策略”。