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();"

八、注意事项(踩坑精华)

  1. --hostname 必须写本机 IP
    • 写 monitor IP → 注册失败
    • 写 0.0.0.0 → 某些版本 HBA 异常
  2. 不要用 PGOPTIONS 传 unix_socket_directories
    • 会报 cannot be changed without restarting
    • socket 目录问题用 XDG_RUNTIME_DIR + 数据卷解决
  3. Monitor 必须先起,Node1 再起,Node2 最后
  4. 重建节点前,必须清 Monitor 元数据
    DELETE FROM pgautofailover.node WHERE nodename='node2';
    
  5. 不要每节点手动建 socket 目录
    • 一次性把 XDG_* 指到数据卷内,以后加节点不改宿主机
  6. pg_hba 改完一定 reload
    SELECT pg_reload_conf();
    
  7. dev 用户只需在主库创建一次
    • 备库会自动同步用户和数据库
    • 但备库的 pg_hba 规则不会自动同步,需要手动加
  8. Monitor 也需要 dev 用户
    • 方便应用通过 Monitor 查看集群拓扑
    • Monitor 上没有业务数据库,只有 pg_auto_failover 元数据库
  9. 每台机器只创建自己需要的目录
    • 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
posted @ 2026-11-02 16:16  Hey,Coder!  阅读(3)  评论(0)    收藏  举报