2025-10-12

Kubernetes MySQL 源库与副本:复制状态、路由和故障切换

理解 MySQL 源库与副本在 Kubernetes 中的部署结构,使用 MySQL 8.4 命令检查复制状态、路由和故障切换。

MySQL 复制不是多起几个 Pod。进入源库与副本拓扑后,身份、存储、读写路由、复制延迟和故障切换必须一起验证。本文使用 MySQL 8.4 的 source / replica 术语;旧版本文档里的 master / slave 命令不能直接照搬。

复制最基本的逻辑

  • 源库负责写入并产生 binary log
  • 副本拉取并重放 binary log
  • 客户端通常写源库,按一致性要求决定是否读副本

概念看起来并不复杂,真正麻烦的是:复制延迟起来后怎么办,主库挂了之后怎么办,客户端到底连到了谁。

为什么 Kubernetes 会让这件事更立体

在 Kubernetes 里,一个复制集通常会依赖:

  • StatefulSet 提供稳定序号身份
  • Headless Service 提供 Pod 级 DNS
  • 每个副本独立 PVC
  • 更谨慎的 readiness 和切主逻辑

先补齐 StatefulSet、Headless Service、PV 与 PVC 和 StorageClass 的基础,再处理数据库复制。

一开始最值得确认的四件事

在你真正去看 MySQL 复制状态前,先确认:

  1. 每个副本是不是都有自己独立的 PVC
  2. 每个副本的 DNS 身份是不是稳定
  3. readiness 是不是代表真实可用
  4. 客户端是否清楚哪个地址负责写、哪个负责读

这些基础没搭对,后面主从问题通常只会显得更乱。

复制延迟为什么最值得盯

主从系统最危险的地方在于:表面看起来一切都“活着”,其实复制已经悄悄落后了。Pod Running 不代表复制健康,Service 正常也不代表读出来的数据够新。

所以,复制延迟几乎总是最关键的信号之一。

最常见的延迟来源

  • 磁盘慢
  • CPU 被打满
  • 节点间网络抖动
  • 大事务
  • readiness / promote 逻辑设计不合理

真遇到问题时,第一反应通常应该先看 IO 和资源压力,而不是先去调一堆数据库参数。

路由问题和复制问题经常混在一起

很多时候,复制本身正常,流量却打错了地方。

典型模式:

  • 写流量进主库 Service
  • 读流量进从库 Service
  • 管理或复制链路用 Pod 级 DNS

如果 Service selector、DNS 名称或客户端连接串写错,症状会看起来像“一致性问题”,但根因其实是路由关系错了。

一套可复用的检查单

上线或排障时,我会优先确认:

  • 主从角色是不是明确区分了
  • 每个副本是不是一卷一实例
  • 读请求到底有没有真的走到从库
  • 主库挂了以后谁来升主
  • 旧主恢复后怎么重新加入

这些问题决定了这个系统是“看起来会跑”,还是“真的能扛事”。

先看这些命令通常最有帮助

kubectl get pods -n <ns> -o wide
kubectl get pvc -n <ns>
kubectl get svc -n <ns>
kubectl get endpointslice -n <ns> \
  -l kubernetes.io/service-name=<svc> -o wide
kubectl describe pod -n <ns> <pod>

先进入源库,确认实际版本和 binary log 坐标:

kubectl exec -it -n db mysql-source-0 -- mysql -uroot -p
SELECT VERSION();
SHOW BINARY LOG STATUS\G

再进入副本:

kubectl exec -it -n db mysql-replica-0 -- mysql -uroot -p
SHOW REPLICA STATUS\G

至少检查 Replica_IO_Running、Replica_SQL_Running、Seconds_Behind_Source、Last_IO_Error 和 Last_SQL_Error。Seconds_Behind_Source 为 0 只能说明采样时没有可见延迟,不能单独证明数据一致;为 NULL 时还要判断复制线程是否停止。MySQL 8.4 已移除 SHOW MASTER STATUS 和 SHOW SLAVE STATUS,旧集群应先执行 SELECT VERSION(),再使用该版本支持的命令。

真正的考验其实是 failover

复制最危险的错觉就是:“有副本,所以应该没问题。”

复制搭起来并不难,真正决定系统韧性的,是:

  • 主库挂了以后多久能升主
  • 客户端在切换期会怎样
  • 旧主怎么重新加入
  • 这期间会不会读到旧数据或丢数据

至少在 staging 里做一次受控切主,看看:

  • 提升主库要多久
  • 旧主重新加入要多久
  • 客户端中断窗口有多长
  • 实际一致性边界是什么

三个复制验收判断

Q: 有了主从复制,就等于高可用了吗? A: 不等于。复制只是基础能力,高可用还取决于切主逻辑、客户端路由和恢复流程是否真的可靠。

Q: 如果读出来的数据不新,第一步先查什么? A: 先看复制延迟,再看磁盘和 CPU 压力,然后确认读流量是不是确实进了从库,而不是进错了服务。

Q: 为什么 Kubernetes 没法自动帮我解决这些最难的问题? A: 因为 Kubernetes 管的是生命周期和调度,不是 MySQL 的主从协议、角色提升和业务一致性语义。

把数据库链路补完整

故障切换最低验收线

在 staging 中停止源库,记录副本提升时间、写入口切换时间、客户端错误窗口、旧源库重新加入方式和可能丢失的事务范围。只看到副本 Pod Running,不算完成故障切换验证。

参考链接