Ansible部署一主多从MySQL的核心是inventory分组物理隔离、my.cnf.j2模板基于group_names动态判断角色、server-id全局唯一不可硬编码,三者任一出错将导致Seconds_Behind_Master: NULL或ERROR 2003连接失败。

直接上结论:Ansible 部署一主多从 MySQL,核心不是“跑通 Playbook”,而是 inventory 分组必须物理隔离、my.cnf.j2 模板必须靠 group_names 动态判断角色、server-id 必须全局唯一且不可硬编码——这三处错任意一个,集群大概率卡在 Seconds_Behind_Master: NULL 或直接报 ERROR 2003 (HY000): Can't connect to MySQL server。
inventory 必须硬拆 mysql_masters 和 mysql_slaves 组
Ansible 不会猜哪台是主、哪台是从,它只认你写进 group 名字里的字符串。用 [dbservers] 一把抓再靠 when: inventory_hostname == 'db1' 判断,扩容时改主机名就得同步改几十处条件,极易漏。
-
[mysql_masters]只放 1 台(MGR 场景下可多台),用于写入 + 生成 binlog -
[mysql_slaves]放所有只读节点,用于拉取 relay log - 不要用变量模拟角色,比如
slave: true这类键值对;Ansible 的group_names是唯一可靠的上下文来源 - 后续所有模板渲染、任务分支、handlers 触发,都基于
{% if 'mysql_masters' in group_names %},而不是主机名或自定义变量
my.cnf.j2 模板里必须动态控制 log-bin、read_only 和 skip-slave-start
MySQL 主从行为由配置文件加载时决定,不是启动后靠 SQL 临时设的。写死参数或漏开关,会导致从库被写入、主库复制线程自启、或从库根本拉不到日志。
- 主库必须有:
log-bin = /data/mysql/binlog/mysql-bin、binlog-format = ROW、skip-slave-start = 1 - 从库必须有:
read_only = ON、relay-log = /data/mysql/relaylog/relay-bin、skip-slave-start = 0 -
server-id必须全局唯一:主库用100,从库用201、202这类递增值;不能全写1,否则复制直接失败 -
/etc/my.cnf文件权限必须是644,否则mysqld启动时静默拒绝读取,日志只报Failed to open config file,不提示权限问题
mysqld --initialize-insecure 对用户和目录属主极其敏感
MySQL 8.0+ 已弃用 mysql_install_db,改用 mysqld --initialize-insecure 初始化数据目录。这个命令不校验密码,但会严格检查运行用户和路径权限。
- 命令必须由
mysql用户执行,不能用root直接跑 -
/data/mysql目录属主必须是mysql:mysql,且不能有写权限给 group 或 other - 初始化前务必确保
datadir为空,否则命令直接退出并报错Directory not empty - 初始化完成后,
mysqld服务首次启动必须用mysql用户,否则无法读取ibdata1等文件
最容易被忽略的是 skip-slave-start 的取值逻辑和 /etc/my.cnf 的权限。前者设反会导致从库误启复制线程并报 Could not find first log file name in binary log index file;后者设错会让服务连进程都不起来,排查时容易绕远路去查 SELinux 或端口占用。


















