用 dbbot v0.14.0 并发部署三台 MySQL 9.7 EA 单机

用 dbbot v0.14.0 引入的自定义包能力,在三台 Rocky Linux 9.7 主机上并发部署 MySQL 9.7 EA 单机实例。这套环境会作为后续 9.7 系列文章的基准实验环境。

上一篇 把 dbbot 这个项目的定位说清楚了。这一篇开始走真正的实战:在三台机器上并发部署 3 套 MySQL 9.7 EA 单机实例

顺嘴提一句这次的小巧合 —— Rocky Linux 9.7 + MySQL 9.7,凑了个"双 9.7"。纯属凑数字图个乐子,刚好都是比较新的系统和数据库,也都在 dbbot 支持矩阵里 —— 后续我就用这"双 9.7"来做主力测试环境了。

这套环境之后会一直留着 —— 后续我会在它上面挨个看看 9.7 里那些值得 DBA 提前关注的变化。所以这一篇本质上是实验环境搭建篇,把"基准机器"先稳稳放好。

但有一个工程问题挡在前面:MySQL 9.7 现在还是 EA 包,不在 dbbot 的官方支持矩阵里。我们要先解决"矩阵外的包怎么走自动化"。

一、为什么 EA 包过去走不通自动化

很多 DBA 都熟悉这个套路:

  • Oracle 先放一个 EA 包出来,包名跟正式包不一样。
  • 公司内部可能又会基于 EA 重命名、重打包、加一层校验。
  • 已经写好的自动化脚本只认"支持矩阵里的官方包名",认不出来这个新文件。

最后只剩两条路:临时改 playbook,或者干脆手工分发二进制。能跑是能跑,但事后排查会很难看 —— 这台机器到底用了哪个包?checksum 校验过没?basedir 是不是覆盖了旧目录?复制关系是不是自动验过?所有这些都得靠人脑记。

dbbot 默认是不允许"包名我不认识"的部署进入主流程的,这是出于稳定性的克制。但完全堵死也不现实,DBA 总会遇到要验 EA、要验内部重打包的场景。

二、v0.14.0 开了哪条受控口子

v0.14.0 加了几个变量,明确告诉 playbook:“这次允许我用一个矩阵之外的 MySQL Server 主包”:

  • fcs_allow_custom_mysql_package —— 允许自定义。默认 false,必须显式打开
  • mysql_custom_package —— 指向本地下载目录里的安装包文件名,支持 .tar.gz.tar.xz
  • mysql_custom_package_checksum_type / mysql_custom_package_checksum —— checksum 校验仍然要做。
  • mysql_software_dir —— basedir 单独隔离,避免 EA 包覆盖旧目录。
  • mysql_version —— 真实版本依然要写明,不靠包名猜。

⚠️ 这不是关闭安全检查: 这个开关只覆盖 MySQL Server 主包名一项。版本判断、目标 OS 判断、部署拓扑判断仍然都在;InnoDB Cluster / Router 场景里的 MySQL Shell 和 Router 包也仍然来自支持矩阵,不能靠这个开关绕过。

这里面最容易被低估的是 mysql_software_dir强烈建议每次都给自定义包单独留 basedir,不要和正式包共用 9.7.0。我这次实测的三台机器上,原本已经有:

/database/mysql/base/9.7.0
/database/mysql/3306

部署完成后,每台机器上新增的是:

/database/mysql/base/9.7.0-EA
/database/mysql/3308

最终每台机器上 33063308 两个 systemd 服务可以同时 active,端口、目录都不打架。这就是分目录的好处 —— 出了问题,你一眼能看出来这个实例用的是正式包还是 EA。

三、本次实验环境

节点IP系统部署内容
node-1192.168.161.11Rocky Linux 9.7MySQL 9.7 EA 单机,端口 3308
node-2192.168.161.12Rocky Linux 9.7MySQL 9.7 EA 单机,端口 3308
node-3192.168.161.13Rocky Linux 9.7MySQL 9.7 EA 单机,端口 3308

三台机器之间没有复制关系 —— 这次只是把同一份 single_node.yml 并发跑到三台上,每台一个独立的 EA 实例。这样后面写不同特性文章时,可以拿其中一台单独折腾,不会牵连其他。

为什么用 3308?这三台机器上已经跑着 3306 的实例,我故意保留了,正好顺带验证 dbbot 多实例部署互不打架。

公开演示密码沿用 dbbot 默认值 (Dbbot_<user>@8888 / Dbbot_<linux_user>@9999),仅用于 lab;生产环境务必换成自己的 SSH key 和数据库密码。

1. 下载 dbbot v0.14.0

cd /tmp
dbbot_version="v0.14.0"
curl -fL -O "https://github.com/fanderchan/dbbot/releases/download/${dbbot_version}/dbbot-${dbbot_version}.tar.gz"
tar -zxvf "dbbot-${dbbot_version}.tar.gz" -C /usr/local/

/usr/local/dbbot/bin/dbbotctl env setup
source ~/.bashrc
ansible-playbook --version

生产环境一定要固定版本,不要让 CI 跑 latest。同一份"上次跑通过的脚本",在两个 release 之间跑出来的结果可能就不一样。

2. 准备 MySQL 9.7 EA 包

9.7 EA 当前不在 dev.mysql.com/get/Downloads 的常规目录里,要去 snapshots 拿:

cd /usr/local/dbbot/mysql_ansible/downloads
curl -fL -O "https://downloads.mysql.com/snapshots/pb/mysql-9.7.0-csa/mysql-9.7.0-csa-linux-glibc2.28-x86_64.tar.xz"
md5sum mysql-9.7.0-csa-linux-glibc2.28-x86_64.tar.xz

本次实测的 MD5:

bf7a16834c99d447630fd917b5f32529  mysql-9.7.0-csa-linux-glibc2.28-x86_64.tar.xz

如果你拿到的是公司内部重打包文件 —— 比如镜像仓库里改过文件名的版本 —— 只需要把文件放到同一个下载目录,然后改变量里的 mysql_custom_package 和对应 checksum,不需要改 playbook。这点很重要:自动化脚本不能因为一次 EA 测试就退化成一次性脚本。

3. 写 inventory

/usr/local/dbbot/mysql_ansible/inventory/hosts.ini

[dbbot_mysql]
192.168.161.11 ansible_user=root ansible_ssh_pass="'Dbbot@2026'"
192.168.161.12 ansible_user=root ansible_ssh_pass="'Dbbot@2026'"
192.168.161.13 ansible_user=root ansible_ssh_pass="'Dbbot@2026'"

[all:vars]
ansible_python_interpreter=auto_silent

先做连通性检查:

cd /usr/local/dbbot/mysql_ansible/playbooks
ansible -i ../inventory/hosts.ini dbbot_mysql -m ping

三台返回 pong 再继续。自动化部署最忌讳带着 SSH、Python、sudo 这类基础问题往下冲 —— 后面剧本一旦报错,根因经常和报错信息隔了好几层,排查起来非常绕。

4. 写独立变量文件

不要为了一个 EA 测试去改默认变量。新建一个独立文件,部署时用 -e @vars/mysql-9-7-ea-single-node.yml 引入,这样这次实验和未来的标准部署互不污染。

/usr/local/dbbot/mysql_ansible/playbooks/vars/mysql-9-7-ea-single-node.yml

mysql_version: "9.7.0"
mysql_port: 3308
mysql_software_dir: "/database/mysql/base/9.7.0-EA"

fcs_auto_download_packages: false
fcs_allow_custom_mysql_package: true
mysql_custom_package: "mysql-9.7.0-csa-linux-glibc2.28-x86_64.tar.xz"
mysql_custom_package_checksum_type: "md5"
mysql_custom_package_checksum: "bf7a16834c99d447630fd917b5f32529"

fcs_allow_dbbot_default_passwd: true
dbbot_confirmation_input: "confirm"

变量刻意写得很短。除了端口、basedir、自定义包这几条这次必须改的,其他能用默认就用默认 —— 实验环境用 fcs_allow_dbbot_default_passwd: true 临时放行公开默认密码,部署后再按需改。

最值得盯住的还是这四行:

mysql_software_dir: "/database/mysql/base/9.7.0-EA"
fcs_allow_custom_mysql_package: true
mysql_custom_package: "mysql-9.7.0-csa-linux-glibc2.28-x86_64.tar.xz"
mysql_custom_package_checksum_type: "md5"

fcs_allow_custom_mysql_package 必须显式打开。mysql_custom_package 必须是本地文件名,不能带目录分隔符,后缀必须是 .tar.gz.tar.xz。这个限制看着啰嗦,其实是为了避免把任意路径塞进解压流程 —— 受控开关该管的事,还是要管住。

5. 一条命令并发部署三台

cd /usr/local/dbbot/mysql_ansible/playbooks
ansible-playbook \
  -i ../inventory/hosts.ini \
  single_node.yml \
  -e @vars/mysql-9-7-ea-single-node.yml

CI 或脚本场景建议用绿色版 Ansible 的显式路径,避免被环境里其他 Python / Ansible 干扰:

cd /usr/local/dbbot/mysql_ansible/playbooks
ANSIBLE_HOST_KEY_CHECKING=False \
python3 /usr/local/dbbot/portable-ansible/ansible-playbook \
  -i ../inventory/hosts.ini \
  single_node.yml \
  -e @vars/mysql-9-7-ea-single-node.yml

single_node.yml 跑在 [dbbot_mysql] 三台机器上,Ansible 默认就是按主机并发执行的,所以三台是同时往前推进的。

执行过程中可以看到 dbbot 走了自定义包分支:

TASK [Use custom MySQL Server package metadata (local)] ************************
ok: [192.168.161.11 -> localhost]
ok: [192.168.161.12 -> localhost]
ok: [192.168.161.13 -> localhost]

TASK [Check mysql-9.7.0-csa-linux-glibc2.28-x86_64.tar.xz checksum when configured (local)] ***
ok: [192.168.161.11 -> localhost]
ok: [192.168.161.12 -> localhost]
ok: [192.168.161.13 -> localhost]

TASK [../roles/mysql_server : Unarchive MySQL install package to /database/mysql/base/9.7.0-EA] ***
changed: [192.168.161.11]
changed: [192.168.161.12]
changed: [192.168.161.13]

最终 PLAY RECAP

192.168.161.11 : ok=86  changed=26  unreachable=0  failed=0
192.168.161.12 : ok=86  changed=26  unreachable=0  failed=0
192.168.161.13 : ok=86  changed=26  unreachable=0  failed=0

Playbook run took 0 days, 0 hours, 1 minutes, 32 seconds

三台 ok / changed 数完全对齐 —— 这正是单机并发部署该有的样子,每台跑同一份剧本,没有谁是"主"。post-deploy 检查也跟着跑完了:

MySQL instance post-check passed on 192.168.161.11.
MySQL instance post-check passed on 192.168.161.12.
MySQL instance post-check passed on 192.168.161.13.

92 秒,从空环境到三台独立的 9.7 EA 单机带 post-check —— 没有"任务跑完了,但不知道结果对不对"的灰色地带。

6. 验证结果

先看每台机器上的服务,原来的 3306 和新装的 3308 应该都是 active:

systemctl is-active mysql3306 mysql3308

三台都返回:

active active

挨台确认 3308 实例的版本、端口和目录:

/database/mysql/base/9.7.0-EA/bin/mysql \
  -h127.0.0.1 -P3308 -uadmin -pDbbot_admin@8888 \
  -NBe "select @@hostname, @@port, @@version, @@basedir, @@datadir;"

三台分别返回:

r9-01.iaas.local  3308  9.7.0  /database/mysql/base/9.7.0-EA/  /database/mysql/3308/data/
r9-02.iaas.local  3308  9.7.0  /database/mysql/base/9.7.0-EA/  /database/mysql/3308/data/
r9-03.iaas.local  3308  9.7.0  /database/mysql/base/9.7.0-EA/  /database/mysql/3308/data/

上面这条命令把 basedir、admin 用户和密码都贴在命令行里,演示场景一目了然,但日常登录其实不用这么累。dbbot 默认会给 mysql 用户生成快捷登录命令(参见 fcs_create_mysql_fast_login),思路和 PostgreSQL 那边 su - postgres 后直接 psql 进库一样:

su mysql
db3308

切到 mysql 用户、敲一个 db<port> 就直接进对应实例了,不用记 basedir 路径,也不用把密码写在命令行里。多端口实例并存时尤其顺手。

basedir 干净落在 9.7.0-EA,没有污染原来 3306 用的 9.7.0。这是上面强调"分目录"那段话的实际意义。

到这里,三套独立的 9.7 EA 3308 单机就稳稳跑起来了。更重要的是:变量文件、包名、checksum、端口、目录、执行日志都留下来了。哪天要复盘,一份变量文件就能解释清楚这台机器是怎么来的

自定义包能力的边界

简单收口一下,这个开关只覆盖 MySQL Server 主包这一项,其他都不变:

受影响说明
MySQL Server 主包名✅ 可以走自定义必须本地文件、必须 .tar.gz / .tar.xz
mysql_version❌ 不受影响真实版本仍要写明,不靠包名猜
目标 OS 判断❌ 不受影响不满足 9.7 的 glibc2.28 仍会失败
部署拓扑判断❌ 不受影响主从、MGR、IDC 各自的前置仍要满足
MySQL Shell / Router 包❌ 不受影响仍来自支持矩阵
checksum 校验✅ 配了就跑推荐每次都配

我个人的几条习惯:

  • 正式生产部署优先走支持矩阵里的标准包名和 checksum。
  • EA、内部测试、厂内重打包再打开 fcs_allow_custom_mysql_package
  • 自定义包一定单独设置 mysql_software_dir,不要和正式包共享 basedir。
  • checksum 能配就配,尤其是经过对象存储、制品库、跳板机多次转运的包。

三台 9.7 EA 实验机已就绪

写到这里,这套实验环境就稳稳挂在那里了:

  • 三台 Rocky Linux 9.7 主机,并发部署完成
  • 每台一个独立的 MySQL 9.7 EA 单机实例,端口 3308
  • basedir、datadir、binlog、配置都是 dbbot 默认布局
  • 旁边还顺带跑着 3306 的旧实例,多版本不打架

后续 9.7 系列的文章都会基于这套环境展开 —— 省得每篇文章都重新装一遍,也省得每次都解释一遍"为什么我能用 9.7 EA 跑这个测试"。三台机器互相独立,写不同特性时可以各跑各的,互不影响。下一篇就开始挖 9.7 里我比较关注的几个变化,从 release notes 写明的那些先聊起。