离线环境用 Ansible 部署 MySQL 集群完全可行,但必须提前打包 MySQL 二进制包、系统依赖 rpm、Python 运行时、community.mysql 集合、SSL 证书,并禁用所有在线操作;hosts 清单须用直连 IPv4 地址,playbook 中需显式配置端口、用户、防火墙及唯一 server_id。

离线环境用 Ansible 部署 MySQL 集群完全可行,但关键不在 Ansible 本身能否运行,而在于所有依赖(MySQL 二进制包、系统依赖、Python 模块、Ansible 模块如 mysql_query)是否提前打包到位。没做完整离线准备,部署中途一定会卡在 yum install 或 pip install 上。
离线包必须包含哪些内容
缺一不可,漏掉任意一类都会导致 playbook 中断:
-
MySQL安装包:必须是对应版本的二进制 tar 包(如mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz),不能是 rpm —— rpm 会触发系统级依赖检查,离线时无法解决libaio等依赖; - 基础系统依赖:提前在目标系统上用
yum install --downloadonly下好libaio, numactl, perl-Data-Dumper等 rpm 包,并带上它们的依赖树; - Ansible 运行时依赖:目标节点需有 Python 3.6+,若无 pip,需离线安装
setuptools、pyyaml、paramiko、psycopg2-binary(哪怕不用 PostgreSQL,某些 MySQL 模块会间接引用); - Ansible 自身模块补丁:默认
mysql_query模块不支持 MySQL 8.0 的 caching_sha2_password 认证,需额外提供 patched 版本或改用community.mysql.mysql_query并确保community.mysqlcollection 已离线导入; - 证书与密钥:若启用 SSL 复制,
ca.pem、server-cert.pem、server-key.pem必须预置在 roles/files/ 下,且 playbook 中不能调用在线生成命令(如openssl req)。
hosts 文件里不能写域名或未解析 IP
离线环境通常无 DNS,hosts 清单中所有 IP 必须是直连可达的 IPv4 地址。常见错误:
- 写成
db-01.example.com→ 报错Failed to connect to the host via ssh; - 写成内网不可达的 Docker 网桥 IP(如
172.18.0.2)→ SSH 连接超时; - 主从角色混用同一 IP(如伪集群模式下用
127.0.0.1)→mysql_replication模块因无法区分实例而失败; - 未显式指定
ansible_ssh_port和ansible_user→ 默认走 22 端口和当前用户,若目标机改过 ssh 端口或只开放了admin用户,直接拒绝连接。
playbook 中禁止任何在线操作
以下写法在离线环境必然失败,必须全部替换或删除:
-
shell: yum install mysql-community-server -y→ 改为unarchive解压本地 tar 包 +copy配置文件 +command初始化mysqld --initialize-insecure; -
get_url: url=https://dev.mysql.com/get/...→ 提前下载到files/目录,改用copy模块分发; -
mysql_user模块中设置host: "%"但未关闭防火墙 → 离线环境往往保留 iptables,需加任务iptables: action: flush或明确放行mysql_port; - 模板
my.cnf.j2中写bind_address = 0.0.0.0却没配skip-networking=OFF→ 启动后 MySQL 监听失效,mysql_replication连不上自己; - 使用
community.mysql.mysql_replication但没在collections/requirements.yml声明,也未执行ansible-galaxy collection install -r requirements.yml --offline→ 报错couldn't resolve module/action 'community.mysql.mysql_replication'。
真正麻烦的不是脚本怎么写,而是确认每个节点的 /etc/my.cnf 是否被其他进程(比如 systemd 的 mysql.service 模板)覆盖,以及 server_id 是否在所有实例间唯一 —— 这两个点一旦出错,主从延迟会卡在 0 秒不动,日志里却只显示 Waiting for master to send event,非常难定位。


















