PostgreSQL容器化部署流复制主从+Keepalive高可用
·
主库 (192.168.0.121)
从库 (192.168.0.116)
镜像
osixia/keepalived 2.0.20 593459a9e605 6 years ago 72.9MB
registry.cn-hangzhou.aliyuncs.com/qingcloudtech/postgresql latest 01da659724f5 2 years ago 327MB
部署 Keepalived
在主库 (192.168.0.121) 执行:
# 1. 停止并删除旧容器
docker stop keepalived-master 2>/dev/null
docker rm keepalived-master 2>/dev/null
# 2. 确认配置文件存在
cat > /data/keepalived/keepalived.conf <<'EOF'
global_defs {
router_id PG_MASTER_121
enable_script_security
}
vrrp_script chk_postgresql {
script "/scripts/check_pg.sh"
interval 2
weight -20
fall 3
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_postgresql
}
virtual_ipaddress {
192.168.0.200/24 dev eth0 label eth0:vip
}
}
EOF
# 3. 确认检查脚本存在
cat > /data/keepalived/scripts/check_pg.sh <<'EOF'
#!/bin/bash
timeout 2 bash -c 'echo > /dev/tcp/127.0.0.1/5432' 2>/dev/null
exit $?
EOF
chmod +x /data/keepalived/scripts/check_pg.sh
# 4. ⚠️ 关键修复:挂载到正确的路径 /usr/local/etc/keepalived/
docker run -d --name keepalived-master \
--restart always \
--network host \
--cap-add=NET_ADMIN \
--privileged \
-v /data/keepalived/keepalived.conf:/usr/local/etc/keepalived/keepalived.conf \
-v /data/keepalived/scripts:/scripts \
osixia/keepalived:2.0.20
# 5. 等待 10 秒
sleep 10
# 6. 检查 VIP 是否绑定
ip addr show eth0 | grep 192.168.0.200
在从库 (192.168.0.116) 执行:
# 1. 停止并删除旧容器
docker stop keepalived-slave 2>/dev/null
docker rm keepalived-slave 2>/dev/null
# 2. 创建配置文件 (注意 state=BACKUP, priority=90)
mkdir -p /data/keepalived/scripts
cat > /data/keepalived/keepalived.conf <<'EOF'
global_defs {
router_id PG_SLAVE_116
enable_script_security
}
vrrp_script chk_postgresql {
script "/scripts/check_pg.sh"
interval 2
weight -20
fall 3
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_postgresql
}
virtual_ipaddress {
192.168.0.200/24 dev eth0 label eth0:vip
}
}
EOF
# 3. 创建检查脚本
cat > /data/keepalived/scripts/check_pg.sh <<'EOF'
#!/bin/bash
timeout 2 bash -c 'echo > /dev/tcp/127.0.0.1/5432' 2>/dev/null
exit $?
EOF
chmod +x /data/keepalived/scripts/check_pg.sh
# 4. ⚠️ 关键修复:挂载到正确的路径
docker run -d --name keepalived-slave \
--restart always \
--network host \
--cap-add=NET_ADMIN \
--privileged \
-v /data/keepalived/keepalived.conf:/usr/local/etc/keepalived/keepalived.conf \
-v /data/keepalived/scripts:/scripts \
osixia/keepalived:2.0.20
# 5. 等待 10 秒
sleep 10
# 6. 检查 VIP (从库此时不应该有 VIP)
ip addr show eth0 | grep 192.168.0.200
检查主库 VIP
# 在主库执行
ip addr show eth0
查看 Keepalived 日志确认配置加载正确
# 在主库执行
docker logs keepalived-master | grep -E "(Virtual IP|192.168.0.200|MASTER)"
测试数据库连接
PGPASSWORD=Admin@123 psql -h 192.168.0.200 -U my_app_user -d my_app_db -c "SELECT pg_is_in_recovery();"
主库已经完成,现在需要在 从库 (192.168.0.116) 上部署 Keepalived。
# 1. 创建目录
mkdir -p /data/keepalived/scripts
# 2. 创建 Keepalived 配置文件 (注意:state=BACKUP, priority=90)
cat > /data/keepalived/keepalived.conf <<'EOF'
global_defs {
router_id PG_SLAVE_116
enable_script_security
}
vrrp_script chk_postgresql {
script "/scripts/check_pg.sh"
interval 2
weight -20
fall 3
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_postgresql
}
virtual_ipaddress {
192.168.0.200/24 dev eth0 label eth0:vip
}
}
EOF
# 3. 创建健康检查脚本
cat > /data/keepalived/scripts/check_pg.sh <<'EOF'
#!/bin/bash
timeout 2 bash -c 'echo > /dev/tcp/127.0.0.1/5432' 2>/dev/null
exit $?
EOF
chmod +x /data/keepalived/scripts/check_pg.sh
# 4. 启动 Keepalived 容器 (注意挂载路径是 /usr/local/etc/keepalived/)
docker run -d --name keepalived-slave \
--restart always \
--network host \
--cap-add=NET_ADMIN \
--privileged \
-v /data/keepalived/keepalived.conf:/usr/local/etc/keepalived/keepalived.conf \
-v /data/keepalived/scripts:/scripts \
osixia/keepalived:2.0.20
# 5. 等待 10 秒
sleep 10
# 6. 检查从库此时不应该有 VIP
ip addr show eth0 | grep 192.168.0.200
执行后,从库应该看不到 192.168.0.200(因为主库优先级更高)。
修复!
在主库 (192.168.0.121) 执行
# 1. 停止并删除现有 Keepalived 容器
docker stop keepalived-master && docker rm keepalived-master
# 2. 修改配置文件(移除 enable_script_security)
cat > /data/keepalived/keepalived.conf <<'EOF'
global_defs {
router_id PG_MASTER_121
}
vrrp_script chk_postgresql {
script "/scripts/check_pg.sh"
interval 2
weight -20
fall 3
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_postgresql
}
virtual_ipaddress {
192.168.0.200/24 dev eth0 label eth0:vip
}
}
EOF
# 3. 重新启动 Keepalived
docker run -d --name keepalived-master \
--restart always \
--network host \
--cap-add=NET_ADMIN \
--privileged \
-v /data/keepalived/keepalived.conf:/usr/local/etc/keepalived/keepalived.conf \
-v /data/keepalived/scripts:/scripts \
osixia/keepalived:2.0.20
# 4. 等待 10 秒
sleep 10
# 5. 验证 Keepalived 状态
echo "=== 主库 Keepalived 日志 ==="
docker logs keepalived-master 2>&1 | tail -20
echo "=== 主库 VIP 状态 ==="
ip addr show eth0 | grep 192.168.0.200
在从库 (192.168.0.116) 执行
# 1. 停止并删除现有 Keepalived 容器
docker stop keepalived-slave && docker rm keepalived-slave
# 2. 修改配置文件(移除 enable_script_security)
cat > /data/keepalived/keepalived.conf <<'EOF'
global_defs {
router_id PG_SLAVE_116
}
vrrp_script chk_postgresql {
script "/scripts/check_pg.sh"
interval 2
weight -20
fall 3
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_postgresql
}
virtual_ipaddress {
192.168.0.200/24 dev eth0 label eth0:vip
}
}
EOF
# 3. 重新启动 Keepalived
docker run -d --name keepalived-slave \
--restart always \
--network host \
--cap-add=NET_ADMIN \
--privileged \
-v /data/keepalived/keepalived.conf:/usr/local/etc/keepalived/keepalived.conf \
-v /data/keepalived/scripts:/scripts \
osixia/keepalived:2.0.20
# 4. 等待 10 秒
sleep 10
# 5. 验证 Keepalived 状态
echo "=== 从库 Keepalived 日志 ==="
docker logs keepalived-slave 2>&1 | tail -20
echo "=== 从库 VIP 状态 ==="
ip addr show eth0 | grep 192.168.0.200 || echo "✓ 正常:从库当前没有 VIP"
修复后重新测试故障切换
等主库和从库都修复完成后,在 主库 执行:
# 1. 先启动 PostgreSQL(如果还在停止状态)
docker start postgresql-master
# 2. 等待 10 秒让主库恢复 MASTER 状态
sleep 10
# 3. 确认 VIP 在主库
echo "=== 确认 VIP 在主库 ==="
ip addr show eth0 | grep 192.168.0.200
# 4. 再次模拟故障
echo "=== 再次模拟故障:停止 PostgreSQL ==="
docker stop postgresql-master
# 5. 等待 15 秒让 Keepalived 检测并切换
sleep 15
# 6. 检查主库状态(应该降级)
echo "=== 主库 Keepalived 日志(应该看到 FAULT 或 BACKUP)==="
docker logs keepalived-master 2>&1 | tail -20
echo "=== 主库 VIP 状态(应该没有 VIP)==="
ip addr show eth0 | grep 192.168.0.200 || echo "✓ 主库已释放 VIP"
然后 登录从库 检查:
# 从库应该有 VIP 了
echo "=== 从库 VIP 状态(应该有 VIP)==="
ip addr show eth0 | grep 192.168.0.200
echo "=== 从库 Keepalived 日志(应该看到 MASTER)==="
docker logs keepalived-slave 2>&1 | tail -20
检查从库是否接管 VIP
请 登录从库 (192.168.0.116) 执行:
# 1. 检查从库是否有 VIP(应该有了!)
echo "=== 从库 VIP 状态 ==="
ip addr show eth0 | grep 192.168.0.200
# 2. 查看从库 Keepalived 日志
echo "=== 从库 Keepalived 日志 ==="
docker logs keepalived-slave 2>&1 | tail -20
# 3. 测试从库 PostgreSQL 是否可连接
echo "=== 测试从库 PostgreSQL 连接 ==="
timeout 2 bash -c 'echo > /dev/tcp/192.168.0.116/5432' && echo "✓ 从库 PostgreSQL 可连接" || echo "✗ 从库 PostgreSQL 不可连接"
然后恢复主库并验证 VIP 漂回
在 主库 (192.168.0.121) 执行:
# 1. 恢复主库 PostgreSQL
echo "=== 恢复主库 PostgreSQL ==="
docker start postgresql-master
# 2. 等待 15 秒让主库优先级恢复并抢占 VIP
echo "=== 等待 15 秒让 VIP 漂回主库... ==="
sleep 15
# 3. 验证 VIP 回到主库
echo "=== 主库 VIP 状态(应该有 VIP)==="
ip addr show eth0 | grep 192.168.0.200
# 4. 查看主库 Keepalived 日志
echo "=== 主库 Keepalived 日志 ==="
docker logs keepalived-master 2>&1 | tail -20
# 5. 验证数据库可写
echo "=== 验证数据库可写 ==="
docker exec -it postgresql-master bash -c "PGPASSWORD=Admin@123 psql -h 127.0.0.1 -U my_app_user -d my_app_db -c 'SELECT pg_is_in_recovery();'"
现在测试 VIP 漂回(恢复主库)
请在 主库 (192.168.0.121) 执行:
# 1. 恢复主库 PostgreSQL
echo "=== 恢复主库 PostgreSQL ==="
docker start postgresql-master
# 2. 等待 15 秒让主库优先级恢复并抢占 VIP
echo "=== 等待 15 秒让 VIP 漂回主库... ==="
sleep 15
# 3. 验证 VIP 回到主库
echo "=== 主库 VIP 状态(应该有 VIP)==="
ip addr show eth0 | grep 192.168.0.200
# 4. 查看主库 Keepalived 日志
echo "=== 主库 Keepalived 日志 ==="
docker logs keepalived-master 2>&1 | tail -20
然后在 从库 (192.168.0.116) 执行:
# 1. 验证从库 VIP 已释放
echo "=== 从库 VIP 状态(应该没有 VIP)==="
ip addr show eth0 | grep 192.168.0.200 || echo "✓ 从库已释放 VIP"
# 2. 查看从库 Keepalived 日志
echo "=== 从库 Keepalived 日志 ==="
docker logs keepalived-slave 2>&1 | tail -15
监控告警
# 建议添加监控脚本,检测 Keepalived 状态变化
cat > /usr/local/bin/check_ha.sh <<'EOF'
#!/bin/bash
VIP="192.168.0.200"
if ip addr show eth0 | grep -q $VIP; then
echo "本机持有 VIP"
else
echo "警告:本机未持有 VIP"
fi
EOF
chmod +x /usr/local/bin/check_ha.sh
bash /usr/local/bin/check_ha.sh
更多推荐


所有评论(0)