最稳方式是用community.mysql.mysql_community_server模块部署,它自动适配系统、处理依赖、注册服务、加固配置并内置初始化;inventory须物理拆分mysql_masters和mysql_slaves组,server-id全局唯一,my.cnf权限必须为644。

直接用 community.mysql.mysql_community_server 模块部署最稳,别手写 yum 或 unarchive 任务——它自动适配 CentOS 7/8/9 的包源、处理依赖、注册服务、加固默认配置,还能内置初始化并设 root 密码。
inventory 必须物理拆分 mysql_masters 和 mysql_slaves 组
Ansible 不会推理角色,只认 group_names。把所有节点塞进 [dbservers] 再靠 when: inventory_hostname == 'db1' 分支,扩容改主机名就得同步扫几十处 YAML,漏一处就复制中断。
-
[mysql_masters]只放 1 台(MGR 场景可多台),用于写入 + 生成 binlog -
[mysql_slaves]放所有只读节点,用于拉取 relay log - 后续所有模板判断、任务分支、handlers 触发,统一用
{% if 'mysql_masters' in group_names %},不碰主机名或自定义变量
my.cnf.j2 模板必须动态控制 log-bin / read_only / skip-slave-start
MySQL 主从行为由配置加载时锁定,不是启动后靠 SQL 临时设的。写死或漏掉关键开关,轻则从库被误写,重则复制线程卡死在 Seconds_Behind_Master: NULL。
- 主库必须有:
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
mysql_user 模块连不上新实例?login_host 和 login_password 是关键
刚初始化的 MySQL 实例默认只允许 localhost socket 连接,mysql_user 模块若没显式指定连接方式,会尝试走 TCP 并失败,尤其在容器或非标准路径下。
- 用
login_host: 127.0.0.1强制走 TCP(绕过 socket 权限限制),配合login_port: 3306 - 确认
my.cnf中已注释掉skip-networking,否则 MySQL 启动即禁用 TCP - 首次连接 root 用户时,
login_password: ""必须显式传空字符串;不写或留空会触发Access denied - 若要远程访问,得额外用
mysql_user授予host: "%"和priv: "*.*:ALL",安装过程不会自动开
别用 copy 覆盖 /etc/my.cnf,用 template + notify 才安全
直接 copy: src=my.cnf dest=/etc/my.cnf 会清掉系统自带的 include 目录(如 /etc/my.cnf.d/),导致 MySQL 启动报错 unknown variable——官方 RPM 包依赖该结构加载额外配置。
- 必须用
template渲染my.cnf.j2,并在文件末尾保留!includedir /etc/my.cnf.d/ - 修改配置后通过
notify: restart mysql触发 handler,避免手动 reload 失效 - 初始化前确保
datadir为空,mysqld --initialize-insecure遇到非空目录直接退出,报错Directory not empty
真正容易崩的点不在语法,而在三处隐性耦合:inventory 分组是否物理隔离、server-id 是否全局唯一且未硬编码、my.cnf 权限是否为 644——这三者任意一个出错,集群大概率卡在连接失败或复制延迟为 NULL,日志里却找不到明确线索。











