一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

K8s集群下如何使用StatefulSet部署高可用MySQL 8.0?

时间:2026-09-03 19:09:47 编辑:袖梨 来源:一聚教程网

StatefulSet是唯一可行方案,因其提供稳定DNS、独立PVC和启停顺序保障;需动态注入错开的server_id与auto_increment参数;initContainer生成配置、Headless Service配对、探针校验复制状态缺一不可。

必须用 StatefulSet,不能用 Deployment —— 否则主从连接会断、GTID 定位失效、数据不一致却无报错。

为什么 StatefulSet 是唯一可行方案

Deployment 生成的 Pod 名带随机哈希(如 mysql-7d8f9b4c6-xyz12),重启后 DNS 记录失效,而 MySQL 主从依赖固定主机名做 CHANGE MASTER TO 和 GTID 自动定位;StatefulSet 提供三样不可替代的东西:

  1. mysql-0.mysql.namespace.svc.cluster.local 这类稳定 DNS,主从之间靠它互相发现
  2. 每个 Pod 绑定独立 PVC,重建后数据不丢、卷不混
  3. 启停严格按序(mysql-0 先就绪,mysql-1 才启动),避免从库连不上主库

server_id 和 auto_increment 必须动态注入且错开

硬编码 server_id=1 或漏配自增偏移,会导致双主写入冲突、START SLAVE 直接报 ERROR 3021 (HY000),甚至数据静默丢失。

  1. hostname 解析序号:进容器执行 hostname | sed 's/mysql-//' | sed 's/..*$//' 得到 01,再写入配置或传给 mysqld
  2. auto_increment_offsetauto_increment_increment 必须写在 [mysqld] 段里:mysql-0 设为 1,2mysql-1 设为 2,2
  3. 别信“启动后 SQL 设置就行”——Pod 重建后配置清空,只靠 SQL 不持久

ConfigMap + initContainer 是最稳的配置落地方式

my.cnf 放 ConfigMap 里静态挂载,看似简单,但无法适配不同 Pod 的 server_id 和角色;initContainer 在主容器启动前执行一次,才是可靠解法。

  1. initContainer 用 busybox 镜像,读取 /proc/1/cgroup 或解析 hostname 获取序号
  2. 生成带正确 server_id 的临时配置文件,复制到 /etc/mysql/conf.d/
  3. 主容器启动时直接加载该配置,不依赖环境变量或启动参数拼接
  4. 避免 Helm 中 {{ .Index | add 1 }} 这类模板逻辑泄露到运行时,降低调试复杂度

Headless Service 和探针配置容易被忽略的关键点

clusterIP: None 是 Headless Service 的标志,但它只是前提;真正起作用的是 StatefulSet 的 serviceName 字段必须和该 Service 名字一致,否则 DNS 不生效。

  1. livenessProbemysqladmin ping -h localhost 即可,但 readinessProbe 必须等复制线程就绪:mysql -e "SHOW SLAVE STATUSG" | grep -q "Slave_IO_Running: Yes"
  2. 主库不需要检查复制状态,但从库必须等 Slave_IO_RunningSlave_SQL_Running 都为 Yes 才标记就绪
  3. 没配对的探针会导致 Service 把流量导到尚未同步完成的从库,应用读到旧数据

最常被跳过的动作是验证两节点的 SELECT @@server_id, @@auto_increment_offset, @@auto_increment_increment; —— 不亲眼确认,等于没配。

热门栏目