MySQL MHA 部署说明

本文说明 mha.yml 的支持边界和基础使用方式。

1. 支持边界

  • 当前仅按 CentOS 7 / Red Hat 7 环境维护
  • 目标架构:一主多从 + MHA Manager
  • 适用版本:MySQL 5.7
  • 切换范围:仅支持当前主库不可用后由 MHA Manager 触发的自动故障转移,不支持主库存活时的在线计划切换

mha.yml 属于传统高可用方案。对于新建集群,优先建议使用 MGR 或 InnoDB Cluster。

192.168.161.* 是 dbbot 默认三节点回归网段,不等同于传统 MHA 专项环境。若要验证 mha.yml,请单独准备 CentOS 7Red Hat 7,并使用 MySQL 5.7

2. inventory 与角色

mha.yml 仍然使用 [dbbot_mysql] 主机组,实际角色通过变量区分:

[dbbot_mysql]
192.0.2.131 ansible_user=root ansible_ssh_pass="'密码'"
192.0.2.132 ansible_user=root ansible_ssh_pass="'密码'"
192.0.2.133 ansible_user=root ansible_ssh_pass="'密码'"

3. 关键变量

编辑 mysql_ansible/playbooks/common_config.yml

mysql_version: "5.7.44"
mysql_port: 3306
fcs_allow_dbbot_default_passwd: true

说明:

  • mha.yml 只支持 MySQL 5.7,不能沿用默认的 MySQL 9.7.x 配置。
  • fcs_allow_dbbot_default_passwd: true 仅适合临时实验环境。如果继续使用 dbbot 公开默认密码,必须显式开启;生产环境应改成自定义密码并保持该开关为 false

编辑 mysql_ansible/playbooks/vars/var_mha.yml

master_ip: 192.0.2.131
slave_ips:
  - 192.0.2.132
  - 192.0.2.133
manager_ip: 192.0.2.133
vip: 192.0.2.130
vip_netmask: "32"
net_work_interface: ens33
mha_secondary_check_script: ""

说明:

  • manager_ip 不能与 master_ip 相同
  • manager_ip 应放在从库节点上
  • vipvip_netmasknet_work_interface 需要与实际网络环境一致
  • ens33 只是示例网卡名。执行 VIP 相关剧本前请先用 ip route get <网关地址>ip -o -4 addr show 确认真实网卡;CentOS 7 KVM 测试环境中常见网卡名也可能是 eth0
  • mha_secondary_check_script 默认为空,表示使用传统 MHA 默认行为。生产环境建议按网络拓扑配置多路径探测命令,降低 manager 单路径误判风险。

3.1 VIP sudo 权限

mha.yml 在每个数据库节点生成 /etc/sudoers.d/dbbot-mha-vip。该文件归 root:root 所有、权限为 0440,只允许 mysql_user(默认为 mysql)以 root 身份执行按当前变量完整展开的三条命令:

<mysql_user> ALL=(root) NOPASSWD: /usr/sbin/ip addr add <vip>/<prefix> dev <interface>
<mysql_user> ALL=(root) NOPASSWD: /usr/sbin/ip addr del <vip>/<prefix> dev <interface>
<mysql_user> ALL=(root) NOPASSWD: /sbin/arping -c 5 -U -I <interface> <vip>

master_ip_failover 使用 sudo -n;策略不匹配时,sudo 命令会立即返回失败,不会等待密码输入。MHA 在节点之间传输差异日志使用普通 scpssh_user 权限,不需要也不会获得 sudo scp。剧本不会授权无参数限制的 iparping

执行新版传统 MHA role 时,剧本会先安装并校验精确策略,再删除 /etc/sudoers 中由旧版 dbbot 生成的以下宽泛规则:

mysql ALL=(ALL) NOPASSWD: /usr/sbin/ip,/sbin/arping,/usr/bin/scp

可用 visudo -c 校验完整 sudo 配置;不要直接手工放宽受管策略。

4. 执行入口

cd /usr/local/dbbot/mysql_ansible/playbooks
ansible-playbook mha.yml

执行过程中按提示输入 confirm 后继续。

非交互执行请显式追加确认变量:

python3 /usr/local/dbbot/portable-ansible/ansible-playbook mha.yml -e dbbot_confirmation_input=confirm

如果命令行同时临时覆盖布尔变量,请使用 JSON extra-vars,避免 key=true 被解析为字符串:

python3 /usr/local/dbbot/portable-ansible/ansible-playbook mha.yml \
  -e dbbot_confirmation_input=confirm \
  -e '{"fcs_allow_dbbot_default_passwd": true}'

4.1 部署后修改 VIP

当前没有单独的传统 MHA VIP 重配置 Playbook。mha.yml 还会处理 MySQL、复制、SSH 和 MHA 部署,不应作为运行中集群只修改 VIP 的快捷入口;mha_unsafe_uninstall.yml 会删除 MySQL 数据目录,更不能用于该操作。

纯 VIP 变更不需要修改 /etc/masterha/app.cnf。该文件只引用 /usr/local/bin/master_ip_failover,不保存 VIP。节点成员或复制拓扑变化不属于本流程;这类变更必须另行完整重配置并同步更新 app.cnf。变更 VIP 时必须同步以下四类状态:

  1. 源配置 mysql_ansible/playbooks/vars/var_mha.yml
  2. 各数据库节点的 /usr/local/bin/master_ip_failover
  3. 各数据库节点的 /etc/sudoers.d/dbbot-mha-vip
  4. 数据库节点网卡上的实时 VIP

请在维护窗口按以下顺序操作:

开始前必须由网络管理系统、IPAM 或同等可信来源确认新 VIP 已预留,并确认相关二层网络中没有其他设备占用该地址。ping 无响应不能证明地址空闲;无法确认时不要继续切换。

  1. manager_ip 节点停止 MHA Manager,并确认进程已经退出:

    su - <mysql_user> -c 'masterha_stop --conf=/etc/masterha/app.cnf'
    pgrep -af 'masterha_manager.*--conf=/etc/masterha/app.cnf'
    
  2. 确认当前实际可写主库以及旧 VIP 的唯一持有节点。发生过故障切换后,不能假定它仍然是变量中的 master_ip

  3. 记录当前实时 VIP,备份源配置、failover 脚本和 sudoers,再更新 var_mha.yml。在所有数据库节点用临时文件准备新的 master_ip_failover 和精确 sudoers,分别执行 perl -c <临时脚本>visudo -cf <临时 sudoers>,验证通过后再替换正式文件;sudoers 必须保持 root:root 0440,替换后再执行 visudo -c

  4. root 从实际持有节点删除旧 VIP,在当前主库绑定新 VIP并发送 gratuitous ARP:

    /usr/sbin/ip addr del <old-vip>/<old-prefix> dev <old-interface>
    /usr/sbin/ip addr add <new-vip>/<new-prefix> dev <new-interface>
    /sbin/arping -c 5 -U -I <new-interface> <new-vip>
    
  5. 在全部数据库节点确认旧 VIP 为零份、新 VIP 只存在一份且位于当前主库。

  6. 在 Manager 节点完成检查并重新启动:

    su - <mysql_user> -c 'masterha_check_ssh --conf=/etc/masterha/app.cnf'
    su - <mysql_user> -c 'masterha_check_repl --conf=/etc/masterha/app.cnf'
    /usr/local/start_mha.sh
    su - <mysql_user> -c 'masterha_check_status --conf=/etc/masterha/app.cnf'
    

任何步骤失败时都应保持 Manager 停止,恢复旧的源配置、failover 脚本、sudoers 和实际 VIP,验证旧状态后再启动 Manager。

4.2 从库重启后的只读状态

传统 MHA 使用与单机、普通主从相同的异步复制基础配置,my.cnf 保持 super_read_only=OFFmha.yml 首次建立复制时会在从库运行时设置 super_read_only=ON,但该状态不会通过基础模板持久化;传统 MHA Manager 也不会在 mysqld 重启后自动修复从库只读状态。

每次数据库实例或主机重启后,在恢复业务流量前必须重新确认当前真实主库和所有从库。只在已经确认的从库上执行:

SHOW SLAVE STATUS\G
SELECT @@GLOBAL.read_only, @@GLOBAL.super_read_only;
SET GLOBAL super_read_only = ON;
SELECT @@GLOBAL.read_only, @@GLOBAL.super_read_only;

验收时应保证当前主库的 read_onlysuper_read_only 均为 0,每个从库均为 1,并重新执行 masterha_check_repl。不要根据旧的 master_ip 变量判断角色,也不要在当前真实主库上执行 SET GLOBAL super_read_only=ON

异步拓扑没有把 super_read_only=ON 写死到通用 my.cnf,是为了避免当前主库 crash 后在尚未发生故障切换时自行恢复为只读。重启后的从库只读状态属于运维巡检和恢复流程的一部分,当前剧本只保证首次部署状态。

4.3 切换能力边界与故障演练

dbbot 的传统 MHA 实现不支持 masterha_master_switch --master_state=alive 在线计划切换。部署后即使存在 /usr/local/bin/master_ip_online_change,并且 /etc/masterha/app.cnf 引用了该文件,也不代表该钩子可用;它不是 dbbot 的公开执行入口,不应在运行中的集群上调用。

当前支持的是故障触发路径:MHA Manager 发现当前主库 mysqld 持续不可用后,选择候选从库、执行故障转移并调用 master_ip_failover 迁移 VIP。只应在隔离的测试环境或已经批准的故障演练窗口验证该流程:

  1. 在 Manager 节点执行 masterha_check_sshmasterha_check_repl,确认 Manager 正在运行,并记录当前真实主库、复制状态和 VIP 持有节点。

  2. 停止业务写入或将演练环境与业务隔离,并确保旧主库不会在切换过程中自行恢复写入。dbbot 生成的 MySQL systemd unit 使用 Restart=on-failure;不要只对 mysqld 执行 kill -9 后便假定它会持续离线。若必须模拟进程 crash,应先采用经过批准的 fencing 或临时自动拉起阻断措施。

  3. 默认端口 3306 的受控演练可在当前真实主库执行以下命令,使 Manager 按故障路径处理:

    systemctl stop mysql3306
    

    非默认端口应使用实际的 mysql_service_name。不要在未隔离的生产环境直接执行该命令。

  4. 在 Manager 节点观察 /var/log/masterha/manager.log,等待故障转移结束。传统 MHA 完成一次故障转移后 Manager 会退出;不要在旧主库完成隔离、重建或重新接入前直接重启 Manager。

  5. 独立验收数据库和写入口:旧主库必须保持不可写或已被 fencing,新主库必须可写,其余从库复制正常;在所有数据库节点执行 ip -o -4 addr show,确认 VIP 只存在一份且位于新主库,并通过 VIP 完成实际连接和写入验证。

master_ip_failover 的输出或退出状态不能代替上述 VIP 实际验收。远程网络命令异常时,钩子结果不一定能可靠反映 VIP 是否迁移成功,因此每次故障切换后都必须检查所有节点的实时地址状态。需要主库存活状态下的计划切换时,应采用 dbbot 之外的受控人工流程,或选择明确支持在线切换的架构。

5. 卸载

mha_unsafe_uninstall.yml 会先停止传统 MHA manager、删除配置的 VIP 和 MHA 运行文件,再按当前 mysql_port 清理 MySQL 实例数据、日志和运行目录:

cd /usr/local/dbbot/mysql_ansible/playbooks
ansible-playbook mha_unsafe_uninstall.yml

执行过程中按提示输入 confirm。如需在非交互场景执行,请追加 -e dbbot_confirmation_input=confirm

默认不会删除 MHA RPM 包。如确需删除 mha4mysql-manager / mha4mysql-node RPM,可追加 -e '{"mha_uninstall_remove_packages": true}'

6. 注意事项

  • mha.yml 当前文档只覆盖 CentOS 7Red Hat 7 使用前提。
  • 不满足 CentOS 7 / Red Hat 7 与 MySQL 5.7 条件的三节点回归环境会被 mha.yml 前置校验拦截,属于预期行为。
  • 如果你在其他发行版上使用,需要先自行验证 Perl 依赖和 MHA RPM 兼容性。
  • 默认不配置 secondary_check_script。生产环境应结合网络拓扑补充 MHA 二次探测配置。
  • 失败后如需重跑,建议先确认 MHA Manager 配置、VIP 状态和 MySQL 实例状态,再决定是否清理残留文件。