直接用community.mysql.mysql_community_server模块部署最省事,它自动处理依赖、服务注册和配置加固,兼容RHEL/CentOS 7+与Ubuntu 20.04+,避免系统包名差异导致的安装失败,且内置初始化逻辑和root密码安全设置。

直接用 community.mysql.mysql_community_server 模块部署 MySQL 最省事,比手写编译安装脚本或硬套 yum/apt 任务更可靠——它专为 MySQL 社区版设计,自动处理依赖、服务注册、默认配置加固,且兼容 RHEL/CentOS 7+ 和 Ubuntu 20.04+。
用 community.mysql 模块替代原始 yum 任务
很多人一开始写 yum: name=mysql-server state=latest,结果在 CentOS 8+ 上失败(因为默认源里没有 mysql-server),或在 Ubuntu 上装成 MariaDB。根本原因是操作系统包名不统一,而 community.mysql 角色/模块做了抽象适配。
- 必须先安装 collection:
ansible-galaxy collection install community.mysql - Playbook 中调用时指定
name: community.mysql.mysql_community_server,不是mysql或mysql-server - 该模块会自动判断系统类型,安装对应二进制包(如 RHEL 系使用官方 RPM,Ubuntu 使用 APT 源里的
mysql-community-server) - 不推荐再用
shell或command手动执行mysqld --initialize——模块已内置初始化逻辑,且支持root_password参数安全设密
密码和 root 权限必须显式声明,不能依赖空密码或跳过验证
Ansible 连不上刚装好的 MySQL,90% 是因为没传 login_password,或误设 login_user: root 却没配密码。MySQL 5.7+ 默认禁用空密码 root 登录,且首次启动后 localhost 的 root 只能通过 socket 认证。
- 首次部署后连接 MySQL 必须用
login_unix_socket: /var/run/mysqld/mysqld.sock(RHEL)或/var/run/mysqld/mysqld.sock(Ubuntu) -
mysql_user模块操作前,需确保已用mysql_community_server的root_password参数设好初始密码 - 若要允许远程 root 登录,得额外加 task 调用
mysql_user模块显式授权:host: "%"+priv: "*.*:ALL",不能指望安装过程自动开 - 忽略
ignore_errors: True在数据库任务里——它会让密码错误静默失败,后续任务全崩
配置文件覆盖必须用 templates + notify,别直接 copy 覆盖 my.cnf
直接 copy: src=my.cnf dest=/etc/my.cnf 会清掉系统自带的 include 目录(如 /etc/my.cnf.d/),导致 MySQL 启动报错“unknown variable”。官方 RPM 包依赖这个结构加载额外配置。
- 正确做法:用
template: src=my.cnf.j2 dest=/etc/my.cnf.d/ansible.cnf,把自定义配置放进.d目录 - 模板中避免覆盖
[mysqld]全局段,只追加必要项(如bind-address,max_connections) - 修改配置后必须触发 handler:
notify: restart mysql,且 handler 中 service 名要匹配实际单元名(mysql或mysqld,CentOS 7 是后者) - 检查
systemctl list-unit-files | grep mysql确认服务名,否则service: name=mysqld state=restarted会报 “unit not found”
主从部署不要在单个 playbook 里硬编码 server-id
用 hostvars[inventory_hostname].server_id 动态取值,否则 clone 出来的多台机器 server-id 冲突,主从同步直接中断。
- 在 inventory 中为每台主机定义变量:
db1 ansible_host=192.168.1.10 server_id=101 - 模板
my.cnf.j2里写:server-id = {{ hostvars[inventory_hostname].server_id }} - 不要用
set_fact在 tasks 里算 server_id —— facts 是 host-local 的,跨主机不可见,无法用于 template 渲染 - GTID 模式下还需确保
enforce_gtid_consistency: ON和gtid_mode: ON同时生效,这两项必须写进配置文件,不能靠 SQL 命令临时设
真正麻烦的从来不是“怎么装”,而是“装完怎么让 Ansible 继续管得住”——比如 socket 路径差异、systemd 单元名变化、配置文件碎片化、GTID 开关的强耦合。这些点不提前对齐,playbook 表面跑通,一上生产就卡在第二步。











