HA 集群扩展安装
在 Patroni 管理的 HA 集群中安装 PostgreSQL 扩展,与单节点实例有本质区别。
本页解释原因,并介绍 pg ha extension 命令子树。
为什么不能用 pg extension install?
单节点流程(pg extension install <instance> <ext>)的工作方式是:
- 用 Pigsty 包构建
-ext派生镜像 - 停止并用新镜像重建容器
- 编辑
postgresql.conf设置shared_preload_libraries - 在容器内执行
CREATE EXTENSION
在 Patroni 集群中,步骤 2-4 全部失效:
- Patroni 是 PID 1。 重建容器 = 该节点离线。如果是 leader,Patroni 会触发 故障切换 —— 集群在你安装到一半时重新洗牌。
- Patroni 每个循环都从 DCS 重新生成
postgresql.conf。 任何对文件的直接 编辑都会在几秒内被覆盖。shared_preload_libraries必须通过patronictl edit-config(写入 DCS)来设置。 CREATE EXTENSION必须在 leader 上运行,而 leader 可能在远程主机 —— 不在任何本地容器内。
pg ha extension 正确编排了所有这些步骤。
工作原理
安装流程遵循特定顺序,避免上述陷阱:
关键顺序是 resume 必须在 edit-config 之前:暂停状态的 Patroni 集群不会
应用 edit-config 变更。如果在暂停状态下 edit-config,shared_preload_libraries
的更新会被静默丢失。
纯内置扩展快速路径
如果所有请求的扩展都是内置的(contrib 扩展,如 hstore、uuid-ossp,随
PostgreSQL 一起发布),步骤 2-4 会完全跳过 —— 不构建镜像、不重建容器、不
暂停/恢复。流程直接走 edit-config + CREATE EXTENSION。
命令
安装
构建 -ext 镜像,暂停集群,重建本地成员容器。
- 单主机集群(所有成员在本地):自动执行 apply(resume + edit-config + CREATE EXTENSION)
- 跨主机集群:只执行 pause + recreate,集群保持暂停。需要在每台主机上分别运行
install,最后在任意主机上运行
pg ha extension apply完成安装。
扩展以逗号分隔传入:
参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
--database |
postgres |
CREATE EXTENSION 的目标数据库 |
--auto-restart |
false |
跳过 edit-config 触发的滚动重启确认 |
⚠
--database影响全部扩展。 指定--database后,apply阶段会对所有已安装扩展(不仅是本次新增的)在目标数据库执行CREATE EXTENSION IF NOT EXISTS。例如,集群已安装[pg_cron, pg_stat_statements, pgvector],执行pg ha extension install app hstore --database mydb后,这四个扩展都会在mydb中创建。扩展的.so文件已在镜像中,不会重复安装,只是 SQL 对象(函数、类型等)在目标库中注册。如果只想在特定数据库中启用已有扩展,无需重新 install,直接用 psql 连接对应库执行
CREATE EXTENSION IF NOT EXISTS即可。
卸载
在 leader 上执行 DROP EXTENSION,然后通过 patronictl edit-config 更新
shared_preload_libraries(触发滚动重启)。不会重建镜像或重建容器 ——
-ext 镜像只增不减;磁盘回收很少见且需手动操作。
扩展以逗号分隔传入:
列表
显示集群扩展的三个视图:
- Config (pg.yaml): 存储在
pg.yaml中的extensions列表 - DCS (preload): 来自
patronictl show-config的shared_preload_libraries值 - Leader (installed): leader 上
pg_extension中的实际扩展
应用
手动触发安装流程的后半段:恢复集群、执行 patronictl edit-config、在
leader 上执行 CREATE EXTENSION。
用于跨主机集群 —— 在每台主机上运行 install(各自构建镜像并重建本地
成员)后,在任意主机上运行一次 apply 完成 DCS 更新和扩展创建。
⚠
--database对所有已安装扩展生效。apply会对集群中全部扩展在指定数据库执行CREATE EXTENSION IF NOT EXISTS,不仅限于本次新增的扩展。
跨主机工作流
在跨主机集群中,每台主机只管理自己的成员。扩展安装流程分为两个阶段, 全局只暂停/恢复一次,避免不必要的 leader 漂移:
第一阶段 —— 每台主机依次运行 install:
每台主机执行:
- 在本地构建
-ext镜像(合并 DCS 已有的扩展列表,确保包含所有包) - 暂停集群(幂等 —— 第二台主机不会因"已暂停"而报错)
- 用新镜像重建自己的本地成员(同主机内 replica 先、leader 后)
- 保存配置 —— 集群保持暂停状态,不 resume
推荐顺序:从 replica 所在主机开始。 如果 leader 所在主机先执行 install, leader 重建会触发故障切换(leader 漂移到其他主机)。从 replica 主机开始, leader 始终不动,直到最后才处理 leader 所在主机,最大限度减少 leader 漂移 带来的数据同步开销。
第二阶段 —— 一次,在任意主机运行 apply:
- 恢复集群(幂等 —— tolerate “not paused”)
- 通过
patronictl edit-config更新shared_preload_libraries - 等待滚动重启
- 在 leader 上执行
CREATE EXTENSION
注意:
install后集群处于暂停状态。如果忘记执行apply,集群会一直暂停 (自动故障切换被禁用)。此时运行pg ha extension apply或手动patronictl resume <scope>即可恢复。
对于单主机集群(所有成员都在本地),install 自动执行 apply 步骤 ——
不需要单独的命令。
关于 leader 漂移: 目前无法完全避免 leader 漂移。当 leader 所在主机的 容器被重建时,Patroni 进程停止,DCS 中的 leader key 在 TTL 过期后失效, 即使集群已暂停(pause),其他 replica 仍会检测到 key 失效并触发新一轮选举。
replicas-first重建顺序能确保 leader 所在主机是最后一个执行 install 的, 但无法阻止 leader 漂移本身。这是 Patroni + 容器重建的固有限制。
extensions 配置字段
扩展在 pg.yaml 的 Patroni 集群配置中以集群级别跟踪:
这个列表是 pg ha extension list 报告的内容,也是 apply 安装的依据。
install 和 remove 都会自动更新它。
shared_preload_libraries 排序
某些扩展必须出现在 shared_preload_libraries 的第 0 位(如果不在第一位,
PostgreSQL 会 FATAL)。pgcli 在扩展目录中以 PreloadFirst 属性跟踪此约束 ——
当前设置此标记的扩展:
citus—— 分布式 PostgreSQL,必须最先加载timescaledb—— 时序引擎,同样的约束
部分扩展还需要额外的 DCS 参数:
pg_cron需要cron.database_name
pg ha extension 自动处理所有情况:
- 带
PreloadFirst的扩展始终放在 CSV 开头,不管输入顺序如何 - 当存在
pg_cron时,cron.database_name设为--database的值 (默认postgres) - 当
pg_cron被移除时,cron.database_name被清除
示例
安装 pg_stat_statements 和 pg_cron
构建 -ext 镜像,重建所有成员(带 pause/resume),在 DCS 中设置
shared_preload_libraries=pg_stat_statements,pg_cron 和
cron.database_name=mydb,然后在 mydb 中创建两个扩展。
安装 Citus(必须排在 preload 第一位)
即使 citus 列在第二位,preload CSV 也会生成为
citus,pg_stat_statements —— 带 PreloadFirst 的扩展始终放在位置 0。
卸载扩展
从 leader 删除 pg_cron,从 shared_preload_libraries 中移除,并清除
cron.database_name。触发滚动重启。
查看已安装的扩展
限制
- 镜像重建是增量的。 卸载扩展不会重建
-ext镜像或缩小它。要回收磁盘, 需用podman image prune手动清理旧镜像。 - 没有按成员的扩展列表。 扩展是集群级别的 —— 所有成员共享相同的
-ext镜像和相同的shared_preload_libraries。 CREATE EXTENSION只针对一个数据库。 PostgreSQL 扩展是按数据库的。要在 多个数据库中安装,需用--database分别指定每个数据库重新运行。- 跨主机需要手动协调。 每台主机必须先运行
install,然后才能运行一次apply。pgcli 不会 SSH 到远程主机。
参考
- Patroni HA —— 集群搭建、命令和架构
- 扩展管理 —— 单节点扩展管理和 Pigsty 目录
- Patroni 动态配置 —— DCS 参数参考