pg_auto_failover 数据库主备配置 三台服务器部署
pg_auto_failover 三节点高可用部署实战(跨主机 Docker 版)
一、架构说明
| 角色 | 机器IP | 主机名标识 | 端口 | 数据目录 |
|---|---|---|---|---|
| Monitor | 192.168.2.23 | monitor | 5432 | /server/pgtemp/data/monitor |
| Node1(首发主) | 192.168.2.16 | node1 | 5432 | /server/pgtemp/data/node1 |
| Node2(备) | 192.168.2.27 | node2 | 5432 | /server/pgtemp/data/node2 |
统一镜像:
citusdata/pg_auto_failover:latest
容器内 PG 用户 UID/GID =101:102
网络模式:network_mode: host(跨主机必须,bridge 会导致 hostname/IP 解析异常)
二、前置准备(每台机器各自执行)
Monitor 服务器(192.168.2.23)
sudo mkdir -p /server/pgtemp/data/monitor/pgdata
sudo mkdir -p /server/pgtemp/data/backup
sudo chown -R 101:102 /server/pgtemp
sudo chmod -R 777 /server/pgtemp/data
sudo ufw allow 5432/tcp
Node1 服务器(192.168.2.16)
sudo mkdir -p /server/pgtemp/data/node1/pgdata
sudo mkdir -p /server/pgtemp/data/backup
sudo chown -R 101:102 /server/pgtemp
sudo chmod -R 777 /server/pgtemp/data
sudo ufw allow 5432/tcp
Node2 服务器(192.168.2.27)
sudo mkdir -p /server/pgtemp/data/node2/pgdata
sudo mkdir -p /server/pgtemp/data/backup
sudo chown -R 101:102 /server/pgtemp
sudo chmod -R 777 /server/pgtemp/data
sudo ufw allow 5432/tcp
三、Monitor 节点部署(192.168.2.23)
docker-compose-monitor.yml
services:
monitor:
image: citusdata/pg_auto_failover:latest
user: "101:102"
container_name: pg_monitor
network_mode: host
environment:
PGDATA: /server/pgtemp/data/monitor/pgdata
XDG_DATA_HOME: /server/pgtemp/data/monitor/xdg/share
XDG_CONFIG_HOME: /server/pgtemp/data/monitor/xdg/config
XDG_RUNTIME_DIR: /server/pgtemp/data/monitor/xdg/run
command: >-
pg_autoctl create monitor
--pgdata /server/pgtemp/data/monitor/pgdata
--auth trust
--ssl-self-signed
--run
volumes:
- /server/pgtemp/data/monitor:/server/pgtemp/data/monitor
- /server/pgtemp/data/backup:/server/pgtemp/data/backup
restart: unless-stopped
启动
docker compose -f docker-compose-monitor.yml up -d
sleep 15
docker logs pg_monitor --tail 20
Monitor pg_hba 放行节点
docker exec pg_monitor bash -c "
cat >> /server/pgtemp/data/monitor/pgdata/pg_hba.conf << 'EOF'
# autoctl_node from nodes
hostssl pg_auto_failover autoctl_node 192.168.2.16/32 trust
hostssl pg_auto_failover autoctl_node 192.168.2.27/32 trust
hostssl pg_auto_failover autoctl_node 127.0.0.1/32 trust
# dev user from all
host all dev 0.0.0.0/0 md5
EOF
"
docker exec pg_monitor psql -U postgres -c "SELECT pg_reload_conf();"
Monitor 创建 dev 用户
docker exec pg_monitor psql -U postgres \
-c "CREATE USER dev WITH SUPERUSER PASSWORD 'boawayAdmin';"
Monitor 上的 dev 用户是为了让应用能从 Monitor 查询集群状态(例如
pg_autoctl show uri),并非业务数据库所在。
四、Node1 部署(192.168.2.16)
docker-compose-node1.yml
services:
node1:
image: citusdata/pg_auto_failover:latest
user: "101:102"
container_name: pg_node1
network_mode: host
environment:
PGDATA: /server/pgtemp/data/node1/pgdata
XDG_DATA_HOME: /server/pgtemp/data/node1/xdg/share
XDG_CONFIG_HOME: /server/pgtemp/data/node1/xdg/config
XDG_RUNTIME_DIR: /server/pgtemp/data/node1/xdg/run
command: >-
pg_autoctl create postgres
--name node1
--hostname 192.168.2.16
--pgdata /server/pgtemp/data/node1/pgdata
--monitor 'postgresql://autoctl_node@192.168.2.23:5432/pg_auto_failover?sslmode=require'
--ssl-self-signed --auth trust --pg-hba-lan --run
volumes:
- /server/pgtemp/data/node1:/server/pgtemp/data/node1
- /server/pgtemp/data/backup:/server/pgtemp/data/backup
restart: unless-stopped
启动
docker compose -f docker-compose-node1.yml up -d
sleep 20
docker logs pg_node1 --tail 30
Node1 创建 dev 用户和数据库
# 建用户
docker exec pg_node1 psql -U postgres \
-c "CREATE USER dev WITH SUPERUSER PASSWORD 'boawayAdmin';"
# 建库(归属 dev 用户)
docker exec pg_node1 psql -U postgres \
-c "CREATE DATABASE dev OWNER dev;"
# 加 HBA 规则
docker exec pg_node1 bash -c "
echo 'host all dev 0.0.0.0/0 md5' >> /server/pgtemp/data/node1/pgdata/pg_hba.conf
pg_ctl reload -D /server/pgtemp/data/node1/pgdata
"
五、Node2 部署(192.168.2.27)
docker-compose-node2.yml
services:
node2:
image: citusdata/pg_auto_failover:latest
user: "101:102"
container_name: pg_node2
network_mode: host
environment:
PGDATA: /server/pgtemp/data/node2/pgdata
XDG_DATA_HOME: /server/pgtemp/data/node2/xdg/share
XDG_CONFIG_HOME: /server/pgtemp/data/node2/xdg/config
XDG_RUNTIME_DIR: /server/pgtemp/data/node2/xdg/run
command: >-
pg_autoctl create postgres
--name node2
--hostname 192.168.2.27
--pgdata /server/pgtemp/data/node2/pgdata
--monitor 'postgresql://autoctl_node@192.168.2.23:5432/pg_auto_failover?sslmode=require'
--ssl-self-signed --auth trust --pg-hba-lan --run
volumes:
- /server/pgtemp/data/node2:/server/pgtemp/data/node2
- /server/pgtemp/data/backup:/server/pgtemp/data/backup
restart: unless-stopped
启动
docker compose -f docker-compose-node2.yml up -d
sleep 20
docker logs pg_node2 --tail 30
Node2 加 dev 用户 HBA 规则
Node2 作为备库,dev 用户和数据库会从主库自动同步过来,不需要重复创建。只需要加 HBA 规则让应用能连接。
docker exec pg_node2 bash -c "
echo 'host all dev 0.0.0.0/0 md5' >> /server/pgtemp/data/node2/pgdata/pg_hba.conf
pg_ctl reload -D /server/pgtemp/data/node2/pgdata
"
六、查看集群状态
docker exec pg_monitor pg_autoctl show state
正常应看到:
node1 | primary | 192.168.2.16:5432 | read-write
node2 | secondary | 192.168.2.27:5432 | read-only
七、验证 dev 用户连接
# 连 Monitor
PGPASSWORD=boawayAdmin psql -h 192.168.2.23 -U dev -d postgres -c "SELECT current_user, version();"
# 连 Node1(主库,业务库 dev)
PGPASSWORD=boawayAdmin psql -h 192.168.2.16 -U dev -d dev -c "SELECT current_user, current_database();"
# 连 Node2(备库)
PGPASSWORD=boawayAdmin psql -h 192.168.2.27 -U dev -d dev -c "SELECT current_user, current_database();"
八、注意事项(踩坑精华)
- --hostname 必须写本机 IP
- 写 monitor IP → 注册失败
- 写 0.0.0.0 → 某些版本 HBA 异常
- 不要用 PGOPTIONS 传 unix_socket_directories
- 会报
cannot be changed without restarting - socket 目录问题用 XDG_RUNTIME_DIR + 数据卷解决
- 会报
- Monitor 必须先起,Node1 再起,Node2 最后
- 重建节点前,必须清 Monitor 元数据
DELETE FROM pgautofailover.node WHERE nodename='node2'; - 不要每节点手动建 socket 目录
- 一次性把 XDG_* 指到数据卷内,以后加节点不改宿主机
- pg_hba 改完一定 reload
SELECT pg_reload_conf(); - dev 用户只需在主库创建一次
- 备库会自动同步用户和数据库
- 但备库的 pg_hba 规则不会自动同步,需要手动加
- Monitor 也需要 dev 用户
- 方便应用通过 Monitor 查看集群拓扑
- Monitor 上没有业务数据库,只有
pg_auto_failover元数据库
- 每台机器只创建自己需要的目录
- Monitor 只建 monitor 目录
- Node1 只建 node1 目录
- Node2 只建 node2 目录
九、常见报错排查表
| 报错现象 | 根因 | 解决 |
|---|---|---|
duplicate key node_formationid_nodename_key |
Monitor 有旧注册记录 | 删 node 行后重建 |
Failed to find IP address for hostname |
bridge 网络 / hostname 错 | 改 host 网络 + 本机IP |
no pg_hba.conf entry for autoctl_node |
Monitor 没放行节点IP | 加 hostssl 规则 + reload |
unix_socket_directories cannot be changed |
PGOPTIONS 传参 | 去掉 PGOPTIONS |
state file not found |
XDG 目录没挂进卷 | 设 XDG_* 到 pgdata 下 |
register_node failed |
半初始化数据残留 | 清 pgdata + xdg + monitor记录 |
wait_standby -> catchingup 失败 |
本地 socket 连不上 | 确认 XDG_RUNTIME_DIR 存在 |
must be superuser to create user |
用 autoctl_node 建用户 | 切 postgres 用户执行 |
database dev does not exist(备库) |
流复制还没追上 | 等一会或查 replication lag |
十、日常运维命令
# 看实时状态
docker exec pg_monitor pg_autoctl watch
# 看连接串(应用用)
docker exec pg_monitor pg_autoctl show uri
# 模拟故障转移
docker stop pg_node1
# 观察 node2 被提升为 primary
# 原主恢复后重新加入
docker start pg_node1
docker exec pg_node1 pg_autoctl rejoin \
--pgdata /server/pgtemp/data/node1/pgdata
十一、应用连接建议
应用侧用多主机 + 读写分离:
# 读写(自动路由到当前 primary)
postgresql://dev:boawayAdmin@192.168.2.16:5432,192.168.2.27:5432/dev?target_session_attrs=read-write&sslmode=require
# 只读(指向 secondary)
postgresql://dev:boawayAdmin@192.168.2.16:5432,192.168.2.27:5432/dev?target_session_attrs=read-only&sslmode=require
留待后查,同时方便他人
联系我:ivesbao@163.com
联系我:ivesbao@163.com

浙公网安备 33010602011771号