直接copy /etc/my.cnf会失败,因mysql配置需动态适配主从角色、server-id、read_only等参数,硬编码文件易导致冲突;必须用template模块结合jinja2模板和inventory变量实现状态收敛。

为什么直接 copy /etc/my.cnf 会失败
Ansible 的 copy 模块能传文件,但 MySQL 配置不是“扔过去就完事”。常见失败点:目标路径被 systemd 或 mysqld 进程占用、SELinux 上下文未重置、文件属主不是 mysql 用户、配置中含主机名或 IP 等动态值——硬编码的 my.cnf 在从库上启动直接报错 server-id duplicated。
真正要同步的是「逻辑配置」,不是「静态文件」。必须用 template 模块 + Jinja2,让每台机器渲染出适配自身的配置。
- 确保
/etc/my.cnf是空文件或仅保留[mysqld]头部,避免与模板冲突 - 禁用 Ansible 默认的 backup 功能(
backup: no),否则每次运行都生成my.cnf.12345,干扰服务重启 - 用
notify: restart mysql而非直接shell: systemctl restart mysqld,保证 handler 只在配置真变化时触发
如何用 template 动态生成主从差异配置
核心是把角色信息(主/从/仲裁)从 inventory 映射到模板变量。比如在 hosts 中定义:
[mysql_master] db01 ansible_host=192.168.10.11 [mysql_slave] db02 ansible_host=192.168.10.12 db03 ansible_host=192.168.10.13
然后在 templates/my.cnf.j2 里写:
[mysqld]
server-id = {{ ansible_hostname | regex_replace('db(\d+)', '\1') | int }}
log-bin = /var/lib/mysql/mysql-bin
{% if inventory_hostname in groups['mysql_master'] %}
read_only = 0
skip-slave-start = 1
{% else %}
read_only = 1
relay-log = /var/lib/mysql/relay-bin
{% endif %}
-
server-id从主机名自动提取数字,避免手写错误 - 主库不设
read_only,但从库强制只读,防误写 - 从库加
relay-log路径,否则启动时报Failed to open the relay log
分发后如何验证配置生效且无语法错误
传完不等于跑通。MySQL 启动前会校验 my.cnf 语法,但 Ansible 不会自动捕获这个阶段的失败。必须显式加检查任务:
- 用
command: mysqld --validate-config --defaults-file=/etc/my.cnf,配合ignore_errors: yes和failed_when: result.rc not in [0, 1](MySQL 8.0+ 返回 1 表示无错误但有 warning) - 检查
/var/lib/mysql目录权限:stat模块确认属主是mysql:mysql,否则mysqld启动时静默失败 - 不要依赖
service: name=mysqld state=restarted的返回值——它只管发信号,不管进程是否真起来。加一个wait_for模块连 3306 端口 10 秒
滚动更新时怎么避免配置错位
集群里混着 MySQL 5.7 和 8.0?或者主库用 log-bin,从库用 binlog_format=ROW?硬写死模板会炸。得靠变量分层控制:
- 在
group_vars/mysql_master里定义:mysql_binlog_format: ROW;在group_vars/mysql_slave里覆盖为:mysql_binlog_format: STATEMENT - 用
when: mysql_version is version('8.0', '>=')控制是否启用caching_sha2_password插件 - 最危险的是
bind-address:主库通常设0.0.0.0,但从库必须限制为127.0.0.1或内网 IP,否则复制用户可能被外网暴力破解
配置同步这事,表面是文件搬运,实际是状态收敛——你得让 Ansible 知道每台机器「该长什么样」,而不是「该塞什么内容」。漏掉任意一层变量绑定或条件判断,后续所有复制、备份、监控都会连锁失效。











