Ceph+K8s 中间件实战 | 第 4 天:K8s 部署 MySQL 高可用集群(Ceph RBD 持久化 + 架构设计 + 登录巡检)

第 4/15 天 · Ceph+K8s 中间件实战系列

在 Day 2 和 Day 3 中,我们分别完成了 Ceph RBD 块存储和 CephFS 共享文件存储接入 K8s 的全部配置。从本篇开始,系列正式进入中间件部署阶段——我们将逐一在 K8s 上部署各类核心中间件,所有持久化存储统一对接 Ceph 后端。MySQL 作为最经典的关系型数据库,是绝大多数业务系统的数据底座。本篇将讲解如何在 K8s 上通过 Bitnami Helm Chart 部署 MySQL 高可用集群,使用 Ceph RBD StorageClass 提供持久化存储,并给出架构设计、部署实战、登录验证与日常巡检的完整流程。

K8s Logo

一、设计架构:MySQL on K8s 高可用体系

1.1 组件拓扑

在 K8s 上部署 MySQL 高可用集群,核心目标是实现数据持久化、读写分离与故障自动恢复。Bitnami MySQL Helm Chart 提供了 Primary + Secondary 的主从架构模式,结合 K8s 的 StatefulSet 与 Headless Service 实现稳定网络标识。整体组件拓扑如下:

组件 角色说明 数量/规格
MySQL Primary 主节点,负责读写操作,Binlog 同步到从节点 1 个
MySQL Secondary 从节点,负责只读负载,实时复制主节点数据 1-2 个
Headless Service 为 StatefulSet 提供稳定 DNS 名称(pod-0.mysql-headless) 1 个
ClusterIP Service 对外暴露统一访问入口,读写分离路由 1 个
PVC(Ceph RBD) 每个 Pod 独占一块 RBD Image,ReadWriteOnce 模式 每节点 1 个
ConfigMap 存放 MySQL 配置文件(my.cnf 自定义参数) 1 个
Secret 存储 root 密码、复制账户密码等敏感信息 1 个

1.2 数据流向

💻 代码示例

应用 Pod → ClusterIP Service → MySQL Primary(写)

↓ Binlog Replication

MySQL Secondary-0(读)

MySQL Secondary-1(读)

 

Primary PVC ←→ Ceph RBD Image ←→ Ceph OSD Pool

Secondary PVC ←→ Ceph RBD Image ←→ Ceph OSD Pool

写入请求通过 ClusterIP Service 路由到 Primary 节点,Primary 将变更写入 Binlog 后异步推送到 Secondary 节点重放。每个 MySQL Pod 通过 PVC 绑定独立的 Ceph RBD Image,RBD 的 ReadWriteOnce 模式天然保证单 Pod 独占挂载,避免多写冲突。

1.3 高可用机制

故障检测与切换:当 Primary Pod 所在节点宕机,K8s 会自动在健康节点重新拉起 StatefulSet Pod。由于数据持久化在 Ceph RBD 上,新 Pod 重新挂载同一 PVC 即可恢复数据。Primary 身份由 Chart 内置脚本检测:

  • Pod mysql-0 默认为 Primary,mysql-1、mysql-2 为 Secondary
  • 若 Primary Pod 被驱逐,StatefulSet 滚动重建保证 mysql-0 优先恢复
  • 从节点在 Primary 恢复后自动重新建立复制关系

数据冗余:Ceph RBD 后端默认三副本存储,即使单个 OSD 或节点故障,数据仍可从其他副本读取。MySQL 层面的主从复制提供了应用级数据冗余,Ceph 层面的多副本提供了存储级冗余,双重保障。

1.4 存储规划

存储层 类型 模式 用途
K8s StorageClass ceph-rbd-sc WaitForFirstConsumer 动态 Provisioning
PVC mysql-data ReadWriteOnce 每 Pod 独占数据卷
Ceph Pool k8s-rbd-pool 副本数 3 后端对象存储池
RBD Image mysql-data-mysql-0 动态创建 20Gi per Pod

二、部署实战:Bitnami MySQL Helm Chart

本篇使用 Bitnami 官方维护的 bitnami/mysql Helm Chart,该 Chart 原生支持 Primary+Secondary 架构、自定义 StorageClass、资源限制与密码管理。

2.1 添加 Bitnami Helm 仓库

💻 代码示例

# 添加 Bitnami 官方 Chart 仓库

helm repo add bitnami https://charts.bitnami.com/bitnami

 

# 更新本地 Chart 索引

helm repo update

 

# 搜索 mysql chart 确认可用

helm search repo bitnami/mysql

 

# 查看 chart 版本信息

helm show chart bitnami/mysql

2.2 编写 values.yaml 自定义配置

💻 代码示例

# mysql-values.yaml — Ceph RBD 持久化 MySQL 集群配置

architecture: replication # 主从复制模式

 

primary:

persistence:

enabled: true

storageClass: "ceph-rbd-sc" # 对接 Day 2 创建的 Ceph RBD StorageClass

accessModes:

– ReadWriteOnce

size: 20Gi

resources:

requests:

cpu: "500m"

memory: "512Mi"

limits:

cpu: "2000m"

memory: "2Gi"

mysqlUser: "appuser"

mysqlDatabase: "appdb"

 

secondary:

replicaCount: 2 # 2 个从节点

persistence:

enabled: true

storageClass: "ceph-rbd-sc"

accessModes:

– ReadWriteOnce

size: 20Gi

resources:

requests:

cpu: "500m"

memory: "512Mi"

limits:

cpu: "2000m"

memory: "2Gi"

 

auth:

rootPassword: "Ceph@K8s#2026" # 生产环境建议使用 Secret 注入

replicationPassword: "Repl#Pass2026"

 

metrics:

enabled: true # 开启 Prometheus 指标暴露

serviceMonitor:

enabled: false # 如已安装 Prometheus Operator 可开启

2.3 执行 Helm 部署

💻 代码示例

# 创建独立命名空间

kubectl create namespace middleware

 

# 部署 MySQL 集群

helm install mysql bitnami/mysql

–namespace middleware

-f mysql-values.yaml

–version 11.x.x

 

# 查看 Helm Release 状态

helm list -n middleware

 

# 等待 Pod 就绪(通常需要 1-3 分钟)

kubectl wait –for=condition=Ready pods -n middleware -l app.kubernetes.io/instance=mysql –timeout=300s

2.4 验证 Pod / Service / PVC 状态

💻 代码示例

# 查看 Pod 运行状态,确认 primary 和 secondary 全部 Running

kubectl get pods -n middleware -l app.kubernetes.io/instance=mysql -o wide

 

# 查看 Service 列表

kubectl get svc -n middleware -l app.kubernetes.io/instance=mysql

 

# 查看 PVC 绑定情况,确认 STORAGECLASS 为 ceph-rbd-sc

kubectl get pvc -n middleware -l app.kubernetes.io/instance=mysql

预期输出示例:

💻 代码示例

NAME READY STATUS RESTARTS AGE

mysql-primary-0 1/1 Running 0 3m

mysql-secondary-0 1/1 Running 0 2m

mysql-secondary-1 1/1 Running 0 2m

 

NAME TYPE CLUSTER-IP PORT(S) AGE

mysql-primary ClusterIP 10.96.23.45 3306/TCP 3m

mysql-secondary ClusterIP 10.96.23.67 3306/TCP 3m

mysql-primary-hl ClusterIP None 3306/TCP 3m

mysql-secondary-hl ClusterIP None 3306/TCP 3m

 

NAME STATUS VOLUME CAPACITY STORAGECLASS AGE

data-mysql-primary-0 Bound pvc-xxxx 20Gi ceph-rbd-sc 3m

data-mysql-secondary-0 Bound pvc-yyyy 20Gi ceph-rbd-sc 2m

data-mysql-secondary-1 Bound pvc-zzzz 20Gi ceph-rbd-sc 2m

K8s Logo

三、登录验证:连接 MySQL 集群

3.1 集群内部连接(Pod 内)

💻 代码示例

# 获取 root 密码

ROOT_PASSWORD=$(kubectl get secret –namespace middleware mysql -o jsonpath="{.data.mysql-root-password}" | base64 -d)

 

# 进入 Primary Pod 执行 MySQL 客户端

kubectl exec -it -n middleware mysql-primary-0 —

mysql -uroot -p"$ROOT_PASSWORD"

 

# 在 MySQL 命令行中验证主从复制状态

3.2 验证主从复制状态

💻 代码示例

— 在 Primary 节点执行,查看 Binlog 位置

SHOW MASTER STATUS;

 

— 查看从节点连接信息

SELECT host, user, port FROM mysql.user WHERE user='monitor' OR user='replicator';

 

— 在 Secondary 节点执行,查看复制状态

SHOW REPLICA STATUSG

 

— 关键指标确认:

— Slave_IO_Running: Yes

— Slave_SQL_Running: Yes

— Seconds_Behind_Master: 0

 

— 创建测试数据库验证数据同步

CREATE DATABASE IF NOT EXISTS test_ha;

USE test_ha;

CREATE TABLE t1 (id INT PRIMARY KEY, msg VARCHAR(100));

INSERT INTO t1 VALUES (1, 'Ceph RBD MySQL HA Test');

 

— 切换到 Secondary Pod 验证数据已同步

— kubectl exec -it -n middleware mysql-secondary-0 — mysql -uroot -p"$ROOT_PASSWORD" -e "SELECT * FROM test_ha.t1;"

3.3 集群外部连接验证

💻 代码示例

# 端口转发到本地验证(临时调试)

kubectl port-forward -n middleware svc/mysql-primary 3306:3306 &

 

# 使用本地 MySQL 客户端连接

mysql -h 127.0.0.1 -P 3306 -uroot -p"$ROOT_PASSWORD" -e "SELECT @@hostname, @@version;"

 

— 确认连接到 Primary 节点,版本号正确

四、日常巡检:MySQL 集群运维命令

4.1 健康检查

💻 代码示例

# 检查所有 Pod 状态及运行时间

kubectl get pods -n middleware -l app.kubernetes.io/instance=mysql

 

# 检查 Pod 详细事件(排查启动失败)

kubectl describe pod -n middleware mysql-primary-0

 

# 检查 PVC 绑定状态与容量

kubectl get pvc -n middleware -l app.kubernetes.io/instance=mysql

 

# 检查 Ceph RBD Image 是否在 Ceph 端正常创建

# 在 Ceph 容器或节点上执行

rbd ls -p k8s-rbd-pool | grep mysql

4.2 日志查看

💻 代码示例

# 查看 Primary 节点 MySQL 日志(错误日志)

kubectl logs -n middleware mysql-primary-0 –tail=100

 

# 查看 Secondary 节点日志

kubectl logs -n middleware mysql-secondary-0 –tail=100

 

# 实时跟踪日志输出

kubectl logs -n middleware mysql-primary-0 -f

 

# 查看 Helm Release 部署历史

helm history mysql -n middleware

4.3 性能监控

💻 代码示例

# 进入 MySQL 查看连接数与运行线程

kubectl exec -it -n middleware mysql-primary-0 —

mysql -uroot -p"$ROOT_PASSWORD" -e "

SHOW STATUS LIKE 'Threads_connected';

SHOW STATUS LIKE 'Slow_queries';

SHOW STATUS LIKE 'Innodb_buffer_pool_wait_free';

SHOW VARIABLES LIKE 'max_connections';

"

 

# 查看 MySQL 复制延迟

kubectl exec -it -n middleware mysql-secondary-0 —

mysql -uroot -p"$ROOT_PASSWORD" -e "SHOW REPLICA STATUSG" |

grep -E "Seconds_Behind_Master|Slave_IO_Running|Slave_SQL_Running"

4.4 容量巡检

💻 代码示例

# 查看 PVC 实际使用量(需要 metrics-server)

kubectl get pvc -n middleware -l app.kubernetes.io/instance=mysql

-o custom-columns=NAME:.metadata.name,STATUS:.status.phase,CAPACITY:.status.capacity.storage

 

# 在 MySQL 内查看数据库大小

kubectl exec -it -n middleware mysql-primary-0 —

mysql -uroot -p"$ROOT_PASSWORD" -e "

SELECT table_schema AS 'Database',

ROUND(SUM(data_length+index_length)/1024/1024, 2) AS 'Size (MB)'

FROM information_schema.tables

GROUP BY table_schema;

"

 

# 在 Ceph 端查看 Pool 容量使用

# ceph df | grep k8s-rbd-pool

五、常见问题

Q1:PVC 一直 Pending,无法绑定 Ceph RBD?

常见原因:① Ceph RBD StorageClass 名称与 values.yaml 中的 storageClass 不一致;② CSI Driver 未正确安装或缺少 Ceph Monitor 地址;③ Ceph Pool 不存在或权限不足。排查命令:kubectl describe pvc <name> -n middleware 查看 Events 信息,确认 StorageClass 存在(kubectl get sc),以及 CSI Driver 运行正常(kubectl get pods -n ceph-csi-rbd)。

Q2:Secondary 节点复制延迟过大(Seconds_Behind_Master > 60)?

主因通常是网络带宽不足或从节点 I/O 性能瓶颈。排查步骤:① 检查从节点资源是否达到 limit 上限(kubectl top pod);② 检查 Ceph RBD IOPS 是否受限(Ceph 端 rbd perf image iotop);③ 优化 MySQL 参数如增大 innodb_buffer_pool_size、relay_log_size。在网络抖动场景可临时调大 slave_net_timeout。

Q3:Primary Pod 重建后从节点无法自动重连?

确认 Chart 版本是否支持自动复制重建。较老版本需手动执行 CHANGE REPLICATION SOURCE TO ...。建议升级到最新 bitnami/mysql Chart,新版本 Init Container 会自动检测 Primary 变更并重新建立复制关系。同时确保 Headless Service DNS 解析正常:kubectl run dns-test --rm -it --image=busybox -- nslookup mysql-primary-0.mysql-primary-hl.middleware.svc.cluster.local。

六、总结

本篇完成了 MySQL 高可用集群在 K8s 上的部署,核心要点回顾:

  1. 架构设计:采用 Bitnami Chart 的 Primary + Secondary 主从复制架构,每个 Pod 独占 Ceph RBD PVC,双重数据冗余保障
  2. 存储对接:values.yaml 中 storageClass: ceph-rbd-sc 实现动态 Provisioning,无需手动预创建 RBD Image
  3. 部署方式:全程使用 Helm Chart,一条 helm install 命令完成集群部署,版本可追溯、配置可版本化管理
  4. 验证与巡检:通过 SHOW REPLICA STATUS 确认复制链路,通过 kubectl get pvc 确认存储绑定,通过 Ceph rbd ls 确认后端 Image

Ceph RBD 的 ReadWriteOnce 特性天然契合 MySQL 单 Pod 独占挂载的需求,是块存储中间件持久化的首选方案。后续篇章中,Redis、MongoDB 等中间件同样会复用这一 StorageClass 体系。

七、下期预告

第 5 天:K8s 部署 Redis Cluster 集群(Ceph RBD + 架构设计 + 巡检命令)——将从 MySQL 的磁盘型持久化转向 Redis 的内存型缓存架构,讲解 Redis Cluster 分片原理、使用 bitnami/redis-cluster Helm Chart 部署 6 节点集群(3 主 3 从),以及 Ceph RBD 持久化 AOF/RDB 持久化文件的配置。敬请关注!

八、系列目录

  • ✅ 第 1 天:Ceph 分布式存储回顾与 K8s 存储体系概述
  • ✅ 第 2 天:K8s 接入 Ceph RBD 块存储(CSI Driver + StorageClass 配置实战)
  • ✅ 第 3 天:K8s 接入 CephFS 共享文件存储(多读场景与性能调优)
  • 📌 第 4 天:K8s 部署 MySQL 高可用集群(Ceph RBD 持久化 + 架构设计 + 登录巡检)(本文)
  • 🔜 第 5 天:K8s 部署 Redis Cluster 集群(Ceph RBD + 架构设计 + 巡检命令)
  • 🔜 第 6 天:K8s 部署 Redis Sentinel 哨兵模式(高可用架构 + 登录验证)
  • 🔜 第 7 天:K8s 部署 MinIO 对象存储集群(分布式架构 + 运维巡检)
  • 🔜 第 8 天:K8s 部署 MongoDB 副本集集群(Ceph RBD + 架构设计 + 登录)
  • 🔜 第 9 天:K8s 部署 Nacos 注册配置中心(集群架构 + 登录巡检)
  • 🔜 第 10 天:K8s 部署 Zookeeper 集群(分布式协调架构 + 运维命令)
  • 🔜 第 11 天:K8s 部署 Elasticsearch 集群(Ceph RBD + 架构设计 + 巡检)
  • 🔜 第 12 天:K8s 部署 Kafka 集群(Ceph RBD + 消息队列架构 + 运维)
  • 🔜 第 13 天:K8s 部署 GitLab 代码托管平台(Ceph RBD 持久化 + 架构 + 巡检)
  • 🔜 第 14 天:K8s 部署 ClickHouse 列式数据库集群(Ceph RBD + 架构设计)
  • 🔜 第 15 天:K8s 中间件统一监控与运维巡检总结(Prometheus + Grafana 全景)
微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像 - 恒星
欢迎您留下宝贵的见解!
提交
头像 - 恒星

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容