基于 Bitnami 镜像构建 PostgreSQL 高可用集群
PostgreSQL 高可用方案依托 repmgr(Replication Manager)实现,该工具开源且专用于自动化管理数据库集群的复制拓扑与故障切换流程。
镜像获取与构建
推荐从 Docker Hub 拉取预构建镜像:
docker pull bitnami/postgresql-repmgr:latest
如需特定版本,可指定标签拉取:
docker pull bitnami/postgresql-repmgr:[TAG]
查看可用版本:https://hub.docker.com/r/bitnami/postgresql-repmgr/tags/
也可选择本地构建:
docker build -t bitnami/postgresql-repmgr:latest \
'https://github.com/bitnami/bitnami-docker-postgresql-repmgr.git#master:14/debian-10'
数据持久化配置
容器销毁后数据会丢失,需通过卷挂载实现持久化。将宿主机目录映射至容器内 /bitnami/postgresql 路径,首次启动时若目录为空会自动初始化。
docker run \
-v /data/pg-ha:/bitnami/postgresql \
bitnami/postgresql-repmgr:latest
注意:该镜像以非 root 身份运行(UID 1001),挂载目录需确保权限匹配。
容器网络互联
命令行方式
创建网络
docker network create pg-net --driver bridge
启动 repmgr 实例
docker run -d --rm --name primary \
--network pg-net \
-e REPMGR_PARTNER_NODES=primary \
-e REPMGR_NODE_NAME=primary \
-e REPMGR_NODE_NETWORK_NAME=primary \
-e REPMGR_PRIMARY_HOST=primary \
-e REPMGR_PASSWORD=replmgr_secret \
-e POSTGRESQL_PASSWORD=db_secret \
bitnami/postgresql-repmgr:latest
连接客户端验证
docker run -it --rm \
--network pg-net \
bitnami/postgresql:14 \
psql -h primary -U postgres
Compose 方式
version: '3'
networks:
pg-net:
driver: bridge
services:
db-primary:
image: bitnami/postgresql-repmgr:latest
networks:
- pg-net
environment:
POSTGRESQL_PASSWORD: dbpass
REPMGR_PASSWORD: replpass
REPMGR_PRIMARY_HOST: db-primary
REPMGR_NODE_NETWORK_NAME: db-primary
REPMGR_NODE_NAME: db-primary
REPMGR_PARTNER_NODES: db-primary
app:
image: your-application:latest
networks:
- pg-net
应用容器内通过主机名
db-primary连接数据库服务。
核心环境变量
| 变量名 | 说明 | 默认值 |
|---|---|---|
| POSTGRESQL_PASSWORD | postgres 用户密码 | 无 |
| POSTGRESQL_PASSWORD_FILE | 密码文件路径(优先级高于直接指定) | 无 |
| REPMGR_USERNAME | repmgr 专用账户名 | repmgr |
| REPMGR_PASSWORD | repmgr 账户密码 | 无 |
| REPMGR_PASSWORD_FILE | repmgr 密码文件路径 | 无 |
| REPMGR_USE_PASSFILE | 启用 passfile 替代明文密码 | 无 |
| REPMGR_PASSFILE_PATH | 密码文件存放位置 | 无 |
| REPMGR_PRIMARY_HOST | 初始主节点地址 | 无 |
| REPMGR_PARTNER_NODES | 集群节点列表(逗号分隔) | 无 |
| REPMGR_NODE_NAME | 当前节点标识名称 | 无 |
| REPMGR_NODE_NETWORK_NAME | 当前节点网络主机名 | 无 |
| REPMGR_PGHBA_TRUST_ALL | pg_hba.conf 认证方式设为 trust(配合 pgpool LDAP 时使用) | no |
初始化配置
首次启动执行脚本
容器首次启动时,会自动执行 /docker-entrypoint-initdb.d 目录下 .sh、.sql、.sql.gz 后缀的文件。通过卷挂载注入自定义初始化脚本:
docker run \
-v /data/init-scripts:/docker-entrypoint-initdb.d \
bitnami/postgresql-repmgr:latest
数据库与用户创建
自动创建指定数据库:
docker run --name pg-0 \
-e POSTGRESQL_DATABASE=app_db \
bitnami/postgresql-repmgr:latest
创建受限用户(仅对指定库有权限):
docker run --name pg-0 \
-e POSTGRESQL_USERNAME=app_user \
-e POSTGRESQL_PASSWORD=user_pass \
-e POSTGRESQL_DATABASE=app_db \
bitnami/postgresql-repmgr:latest
指定 POSTGRESQL_USERNAME 后,postgres 用户不再设置密码。如需保留 postgres 远程登录,需额外配置 POSTGRESQL_POSTGRES_PASSWORD。
流复制高可用集群搭建
单主单从架构
步骤一:创建网络
docker network create pg-cluster --driver bridge
步骤二:部署主节点
docker run -d --name node-0 \
--network pg-cluster \
-e REPMGR_PARTNER_NODES=node-0,node-1 \
-e REPMGR_NODE_NAME=node-0 \
-e REPMGR_NODE_NETWORK_NAME=node-0 \
-e REPMGR_PRIMARY_HOST=node-0 \
-e REPMGR_PASSWORD=repl_secret \
-e POSTGRESQL_PASSWORD=db_secret \
bitnami/postgresql-repmgr:latest
步骤三:部署从节点
docker run -d --name node-1 \
--network pg-cluster \
-e REPMGR_PARTNER_NODES=node-0,node-1 \
-e REPMGR_NODE_NAME=node-1 \
-e REPMGR_NODE_NETWORK_NAME=node-1 \
-e REPMGR_PRIMARY_HOST=node-0 \
-e REPMGR_PASSWORD=repl_secret \
-e POSTGRESQL_PASSWORD=db_secret \
bitnami/postgresql-repmgr:latest
此时两节点集群已具备自动故障转移能力。主节点故障时,repmgr 自动提升从节点为新的主节点。集群支持动态增删从节点,无需停机。
注意:集群变更后需同步更新各节点 REPMGR_PARTNER_NODES 环境变量,并重启使配置生效。
TLS 加密通信
| 变量名 | 功能 | 默认值 |
|---|---|---|
| POSTGRESQL_ENABLE_TLS | 启用 TLS 加密 | no |
| POSTGRESQL_TLS_CERT_FILE | 服务器证书路径 | 无 |
| POSTGRESQL_TLS_KEY_FILE | 证书私钥路径 | 无 |
| POSTGRESQL_TLS_CA_FILE | CA 证书路径(启用客户端证书验证) | 无 |
| POSTGRESQL_TLS_CRL_FILE | 证书吊销列表路径 | 无 |
| POSTGRESQL_TLS_PREFER_SERVER_CIPHERS | 优先采用服务端加密套件 | yes |
启用 TLS 后,PostgreSQL 同时兼容加密与非加密连接,但优先使用加密通道。
快速启用示例
docker run \
-v /etc/ssl/certs:/opt/bitnami/postgresql/certs \
-e POSTGRESQL_ENABLE_TLS=yes \
-e POSTGRESQL_TLS_CERT_FILE=/opt/bitnami/postgresql/certs/server.crt \
-e POSTGRESQL_TLS_KEY_FILE=/opt/bitnami/postgresql/certs/server.key \
bitnami/postgresql-repmgr:latest
自定义配置文件
镜像默认配置路径:
/opt/bitnami/repmgr/conf/repmgr.conf/opt/bitnami/postgresql/conf/postgresql.conf/opt/bitnami/postgresql/conf/pg_hba.conf
通过挂载覆盖默认配置:
docker run --name node-0 \
-v /data/pg-conf:/bitnami/repmgr/conf \
bitnami/postgresql-repmgr:latest
权限设置:
sudo chgrp -R root /data/pg-conf
sudo chmod -R g+rwX /data/pg-conf
conf.d 扩展配置
默认 postgresql.conf 包含以下配置:
include_dir = 'conf.d'
可将额外 .conf 文件置于 /bitnami/postgresql/conf/conf.d/ 目录实现配置拆分:
docker run --name node-0 \
-v /data/pg-extra:/bitnami/postgresql/conf/conf.d \
-v /data/pg-conf:/bitnami/repmgr/conf \
bitnami/postgresql-repmgr:latest
修改配置后重启容器生效:
docker restart node-0
日志查看
日志直接输出至标准输出,通过以下命令查看:
docker logs node-0
如需调整日志收集方式,可通过 --log-driver 参数配置,默认采用 json-file 驱动。
版本升级流程
拉取最新镜像
docker pull bitnami/postgresql-repmgr:latest停止现有容器并备份数据
docker stop node-0 node-1 rsync -a /data/pg-data /data/pg-data.bkp.$(date +%Y%m%d-%H%M%S)移除旧容器
docker rm -v node-0 node-1基于新镜像重建
docker run --name node-0 bitnami/postgresql-repmgr:latest
完整环境变量参考
| 变量 | 默认值 |
|---|---|
| REPMGR_NODE_ID | nil |
| REPMGR_NODE_ID_START_SEED | 1000 |
| REPMGR_NODE_NAME | nil |
| REPMGR_NODE_NETWORK_NAME | nil |
| REPMGR_NODE_PRIORITY | 100 |
| REPMGR_PARTNER_NODES | nil |
| REPMGR_PRIMARY_HOST | nil |
| REPMGR_NODE_LOCATION | default |
| REPMGR_PRIMARY_PORT | 5432 |
| REPMGR_PORT_NUMBER | 5432 |
| REPMGR_LOG_LEVEL | NOTICE |
| REPMGR_START_OPTIONS | nil |
| REPMGR_CONNECT_TIMEOUT | 5 |
| REPMGR_RECONNECT_ATTEMPTS | 3 |
| REPMGR_RECONNECT_INTERVAL | 5 |
| REPMGR_USE_REPLICATION_SLOTS | 1 |
| REPMGR_MASTER_RESPONSE_TIMEOUT | 20 |
| REPMGR_DEGRADED_MONITORING_TIMEOUT | 5 |
| REPMGR_USERNAME | repmgr |
| REPMGR_DATABASE | repmgr |
| REPMGR_PASSWORD | nil |
| REPMGR_PASSWORD_FILE | nil |
| REPMGR_FENCE_OLD_PRIMARY | no |
| REPMGR_CHILD_NODES_CHECK_INTERVAL | 5 |
| REPMGR_CHILD_NODES_CONNECTED_MIN_COUNT | 1 |
| REPMGR_CHILD_NODES_DISCONNECT_TIMEOUT | 30 |
| REPMGR_USE_PASSFILE | nil |
| POSTGRESQL_USERNAME | postgres |
| POSTGRESQL_DATABASE | nil |
| POSTGRESQL_PASSWORD | nil |
| POSTGRESQL_PASSWORD_FILE | nil |
| POSTGRESQL_POSTGRES_PASSWORD | nil |
| POSTGRESQL_POSTGRES_PASSWORD_FILE | nil |
| POSTGRESQL_PORT_NUMBER | 5432 |
| POSTGRESQL_INITDB_ARGS | nil |
| POSTGRESQL_PGCTLTIMEOUT | 60 |
| POSTGRESQL_SHUTDOWN_MODE | fast |
| POSTGRESQL_ENABLE_TLS | no |
| POSTGRESQL_TLS_CERT_FILE | nil |
| POSTGRESQL_TLS_KEY_FILE | nil |
| POSTGRESQL_TLS_CA_FILE | nil |
| POSTGRESQL_TLS_CRL_FILE | nil |
| POSTGRESQL_TLS_PREFER_SERVER_CIPHERS | yes |