Skip to content

MySQL 高可用集群部署文档

环境:RKE2 v1.35.6(6 节点)|内部 Harbor 192.168.122.156:30000|NFS 192.168.122.1:/mnt/xfs/rancher/mysql 组件:MySQL 8.4.5 主从(1主2从)+ ProxySQL 2.7.3 读写分离(2副本)+ CronJob 每日备份 更新:2026-08-01

1. 架构

                ┌──────────────────────────────┐
  应用 ───────► │ ProxySQL ×2(读写分离入口)    │
                │ mysql-proxysql.mysql:3306    │
                └──────┬───────────┬───────────┘
              写(HG10) │           │ 读(HG20)
                       ▼           ▼
              ┌────────────┐  ┌──────────────────┐
              │ Primary ×1 │→│ Secondary ×2     │   MySQL 8.4.5 异步复制
              └────────────┘  └──────────────────┘


        NFS 192.168.122.1:/mnt/xfs/rancher/mysql(StorageClass: nfs-mysql)

  备份: CronJob 每天 02:00(北京) mysqldump --single-transaction → NFS,保留 7 天
组件副本高可用措施
mysql-primary1主从架构写节点天然单点,故障时手动提升从库(见操作文档)
mysql-secondary2跨节点反亲和,读流量 Service 负载均衡
mysql-proxysql2跨节点反亲和 + PDB(minAvailable=1)
mysql-nfs-provisioner1仅供给 PVC 时工作,短暂故障不影响运行
mysql-backupCronJob0 18 * * * UTC = 北京 02:00,保留 7 天

2. 镜像与 Chart(全部来自内部 Harbor)

国内环境无法直连 docker.io,所有物料经国内源(daocloud)同步至内部 Harbor:

内容内部地址来源
MySQL 镜像mysql/mysql:8.4.5-debian-12-r0docker.m.daocloud.io/bitnamilegacy/mysql
ProxySQL 镜像mysql/proxysql:2.7.3docker.m.daocloud.io/proxysql/proxysql
MySQL chartoci://…/charts/mysql:12.3.5oci://docker.m.daocloud.io/bitnamicharts/mysql
NFS provisioner chartoci://…/charts/nfs-subdir-external-provisioner:4.0.18Harbor 已有
NFS provisioner 镜像sig-storage/nfs-subdir-external-provisioner:v4.0.2Harbor 已有

节点已配置 registry mirror(* → Harbor),公开项目可匿名拉取,无需 imagePullSecret。

3. 前置准备

3.1 NFS 服务器导出(192.168.122.1)

bash
mkdir -p /mnt/xfs/rancher/mysql
echo '/mnt/xfs/rancher/mysql *(rw,sync,no_subtree_check,no_root_squash)' >> /etc/exports
exportfs -ra
showmount -e localhost   # 确认 /mnt/xfs/rancher/mysql 在导出列表

3.2 创建 Harbor 项目并同步物料

bash
# 创建公开项目 mysql(一次即可)
curl -u 'admin:xxx' -X POST 'http://192.168.122.156:30000/api/v2.0/projects' \
  -H 'Content-Type: application/json' -d '{"project_name":"mysql","public":true}'

# 镜像 + chart 一键同步(需本机 skopeo/helm,凭据从环境变量传入)
export HARBOR_USER=admin HARBOR_PASS='xxx'
./deploy.sh sync

4. 一键部署

交付目录 mysql/ 内容:

mysql/
├── deploy.sh                    # 一键部署脚本(all|sync|check)
├── mysql-values.yaml            # bitnami mysql chart 参数(主从、存储、探针)
├── nfs-provisioner-values.yaml  # 专用 StorageClass nfs-mysql 参数
├── proxysql.yaml                # ProxySQL 读写分离(Secret/Deployment×2/Service/PDB)
├── backup.yaml                  # 备份 PVC + CronJob(保留 7 天)
├── .secrets.env                 # 全部密码(勿提交公共仓库)
└── README.md / 部署文档.md / 操作文档.md
bash
export KUBECONFIG=~/.kube/config-122.31
cd mysql/
./deploy.sh          # 全量部署 + 验证

脚本执行序列:前置检查(NFS 导出)→ 命名空间 → NFS provisioner → MySQL 主从 → ProxySQL + 备份 → 状态验证。 全部为 helm upgrade --install / kubectl apply,可重复执行。

手动分步部署(等价命令)

bash
export KUBECONFIG=~/.kube/config-122.31

kubectl create ns mysql

helm install mysql-nfs-provisioner \
  oci://192.168.122.156:30000/charts/nfs-subdir-external-provisioner \
  --version 4.0.18 --plain-http -n mysql -f nfs-provisioner-values.yaml

helm install mysql oci://192.168.122.156:30000/charts/mysql \
  --version 12.3.5 --plain-http -n mysql -f mysql-values.yaml

kubectl apply -f proxysql.yaml -f backup.yaml

5. 部署后验证

bash
kubectl -n mysql get pods -o wide     # 6 个 Pod 全部 1/1 Running,分布在不同节点

# 主从复制:双从 IO/SQL 线程 Yes、延迟 0
kubectl -n mysql exec mysql-secondary-0 -c mysql -- mysql -uroot -p"$PW" \
  -e "SHOW REPLICA STATUS\G" | grep -E 'IO_Running|SQL_Running|Seconds_Behind'

# 读写分离:经 ProxySQL 写入落主库;SELECT 落在 read_only=1 的从库
kubectl -n mysql exec mysql-primary-0 -c mysql -- \
  mysql -h mysql-proxysql -uappuser -p"$APP_PW" appdb \
  -e 'SELECT @@server_id, @@read_only;'

# 备份:手动触发一次
kubectl -n mysql create job --from=cronjob/mysql-backup mysql-backup-manual-$(date +%s)

6. 关键设计决策与踩坑记录

  1. 独立 StorageClass nfs-mysql:集群默认 nfs SC 指向 /mnt/xfs/rancher/uat1, 为满足 /mnt/xfs/rancher/mysql 路径要求,单独部署第二个 provisioner 实例。
  2. InnoDB redo log 损坏(MY-012960):NFS 上 InnoDB 首次初始化需 1~2 分钟, 默认 livenessProbe 会在初始化中途杀死 Pod,留下损坏的 redo log,此后无限 CrashLoop。 修复:宽松 startupProbe(90×10s=15 分钟预算)+ 清空数据重建。切勿缩短探针。
  3. bitnami 镜像下线:docker.io/bitnami 版本化 tag 已下线,改用 bitnamilegacy/mysql (chart 12.3.5 默认 tag 8.4.5-debian-12-r0 在 legacy 仓库中存在), chart 需加 global.security.allowInsecureImages: true 跳过镜像校验。
  4. ProxySQL admin 仅允许 localhost:管理接口 6032 不接受远程连接(ProxySQL 安全设计), 管理操作需在 pod 内执行。
  5. MySQL 选 8.4 LTS 而非 9.x Innovation:生产环境优先 LTS。

7. 应用接入

mysql-proxysql.mysql.svc.cluster.local:3306   统一入口(自动读写分离)
账号 appuser / 密码见 .secrets.env / 默认库 appdb