14.8.5 与Keepalived/HAProxy协同高可用

在复杂生产环境中,ProxySQL通常需要与Keepalived或HAProxy配合,形成多层高可用。典型拓扑为:客户端连接VIP→Keepalived主备切换→HAProxy四层负载→ProxySQL多实例集群→后端MySQL主从。这样可同时解决入口可用性、连接分发与代理层故障切换问题。Keepalived负责VIP漂移,HAProxy负责连接级负载与健康检查,ProxySQL负责SQL级路由与故障隔离。

原理草图(入口高可用 + 代理高可用 + 后端高可用):

文章图片

部署与安装(示例)#

以两台节点(node1、node2)部署 Keepalived + HAProxy + ProxySQL 为例:

# node1/node2 安装(以 Debian/Ubuntu 为例)
sudo apt-get update
sudo apt-get install -y keepalived haproxy proxysql

# 查看版本
keepalived -v
haproxy -v
proxysql --version

Keepalived 配置(/etc/keepalived/keepalived.conf)#

vrrp_script chk_haproxy {
    script "/usr/local/bin/chk_haproxy.sh"
    interval 2
    weight -20
}

vrrp_instance VI_1 {
    state MASTER               # 备节点改为 BACKUP
    interface eth0
    virtual_router_id 51
    priority 120               # 备节点调低,如 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        10.10.10.100/24
    }
    track_script {
        chk_haproxy
    }
}

健康检查脚本(/usr/local/bin/chk_haproxy.sh):

#!/bin/bash
# 检测 HAProxy 3306 端口是否可用
nc -z 127.0.0.1 3306
if [ $? -ne 0 ]; then
  exit 1
fi
exit 0
sudo chmod +x /usr/local/bin/chk_haproxy.sh
sudo systemctl restart keepalived
sudo systemctl enable keepalived

HAProxy 配置(/etc/haproxy/haproxy.cfg)#

global
    log /dev/log local0
    maxconn 4096

defaults
    mode tcp
    log global
    timeout connect 5s
    timeout client  1m
    timeout server  1m

frontend mysql_in
    bind *:3306
    default_backend proxysql_pool

backend proxysql_pool
    option tcp-check
    tcp-check connect port 6033   # ProxySQL admin端口探测
    server proxysql1 10.10.10.11:3306 check
    server proxysql2 10.10.10.12:3306 check
sudo systemctl restart haproxy
sudo systemctl enable haproxy

ProxySQL 最小可用示例(在每台 ProxySQL 上执行)#

-- 连接 admin 端口
mysql -u admin -padmin -h 127.0.0.1 -P6032

-- 后端 MySQL 节点
INSERT INTO mysql_servers(hostgroup_id, hostname, port) VALUES
(10,'10.10.20.11',3306),
(20,'10.10.20.12',3306);

-- 监控账户
UPDATE global_variables SET variable_value='monitor' WHERE variable_name='mysql-monitor_username';
UPDATE global_variables SET variable_value='monitor_pwd' WHERE variable_name='mysql-monitor_password';

-- 载入并持久化
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;

关键命令解释与联动检查#

# 查看 VIP 漂移
ip a | grep 10.10.10.100

# 检查 HAProxy 后端健康
echo "show servers state" | socat stdio /var/run/haproxy.sock

# ProxySQL 后端状态
mysql -u admin -padmin -h 127.0.0.1 -P6032 -e "SELECT * FROM runtime_mysql_servers;"
  • ip a:确认 VIP 是否在本机。
  • show servers state:确认 HAProxy 是否将 ProxySQL 正常转发。
  • runtime_mysql_servers:确认 ProxySQL 后端主从是否健康。

故障排查清单(含示例)#

1) VIP 未漂移

journalctl -u keepalived -n 100 --no-pager
# 重点看脚本失败或权限问题

2) HAProxy 无法探测 ProxySQL

nc -zv 10.10.10.11 3306
nc -zv 10.10.10.11 6033
# 若6033不可用,检查ProxySQL admin端口是否监听
ss -lntp | grep 6033

3) ProxySQL 未切换后端

SELECT * FROM mysql_servers;
SELECT * FROM runtime_mysql_servers;
SHOW GLOBAL VARIABLES LIKE 'mysql-monitor%';

runtimedisk 不一致,需执行 LOAD ... TO RUNTIMESAVE ... TO DISK

演练与练习#

  • 练习1:验证 VIP 漂移
    1. 关闭主节点 HAProxy:systemctl stop haproxy
    2. 观察 VIP 是否漂移:ip a | grep 10.10.10.100
    3. 预期效果:VIP 自动漂移到备节点,应用连接不中断。

  • 练习2:验证 ProxySQL 故障摘除
    1. 停止其中一台 ProxySQL:systemctl stop proxysql
    2. 查看 HAProxy 后端状态:echo "show stat" | socat stdio /var/run/haproxy.sock
    3. 预期效果:对应后端标记为 DOWN,流量转移到另一台 ProxySQL。

  • 练习3:MySQL 主库故障
    1. 停止 MySQL 主库:systemctl stop mysql
    2. 观察 ProxySQL 后端:SELECT * FROM runtime_mysql_servers;
    3. 预期效果:主库被标记不可用,写流量切换到新主库(需配合 MHA/Orchestrator 或人工切主)。

协同设计要点#

  • Keepalived 只监控 HAProxy,避免与 ProxySQL 决策冲突。
  • HAProxy 只做连接级健康探测,ProxySQL 负责 SQL 级路由与后端故障隔离。
  • ProxySQL 内部开启配置同步,保证多实例一致性:
LOAD ADMIN VARIABLES TO RUNTIME;
SAVE ADMIN VARIABLES TO DISK;
-- 配置集群(示例)
UPDATE global_variables SET variable_value='10.10.10.11:6032' WHERE variable_name='admin-cluster_mysql_servers';
LOAD ADMIN VARIABLES TO RUNTIME;
SAVE ADMIN VARIABLES TO DISK;

通过上述部署与演练,实现入口高可用、代理高可用、后端高可用三层解耦,降低单点风险并提升扩展性。