1. 项目概述:K8s部署MySQL与Ceph存储整合方案

在云原生架构中,数据库与存储的容器化部署一直是企业级应用的关键环节。最近我在生产环境完成了MySQL on K8s with Ceph的完整部署方案,这个组合完美解决了有状态服务在K8s中的持久化存储难题。传统方案中,MySQL直接使用本地存储或云厂商提供的块存储服务,存在单点故障风险且扩展性受限。而Ceph作为开源的统一分布式存储系统,通过RBD(RADOS Block Device)为K8s提供高可用的块存储服务,使MySQL实例能够像无状态服务一样自由调度。

这个方案的核心价值在于:

  • 数据高可用:Ceph的多副本机制确保即使单个节点故障,MySQL数据也不会丢失
  • 弹性扩展:存储容量可随业务需求动态调整,无需停机迁移
  • 性能可控:Ceph支持SSD/NVMe缓存分层,能满足不同级别的IOPS需求
  • 运维标准化:所有资源通过K8s声明式API管理,降低运维复杂度

2. 环境准备与组件选型

2.1 基础环境要求

在开始部署前,需要确保以下基础环境就位:

# K8s集群节点建议配置(生产环境)
控制平面节点:4核CPU/8GB内存/100GB磁盘 x3(高可用部署)
工作节点:8核CPU/16GB内存/200GB磁盘(需预留Ceph OSD磁盘空间)
网络:万兆网络(Ceph对网络带宽敏感)

特别注意:Ceph OSD磁盘必须使用裸设备(未格式化的磁盘),不能使用已有文件系统的磁盘。建议为每个OSD准备单独的SSD或高性能HDD。

2.2 Ceph集群部署方案选择

目前主流的Ceph部署方式有三种:

  1. Rook Operator (推荐):

    • 优点:全自动化部署,与K8s深度集成,支持CRD管理
    • 缺点:对底层硬件抽象较多,调试复杂问题需要熟悉Operator逻辑
  2. Cephadm

    • 优点:官方维护,支持最新Ceph版本
    • 缺点:需要额外管理节点,与K8s集成度一般
  3. 手动部署

    • 优点:完全可控,适合定制化需求
    • 缺点:运维成本高,升级困难

对于K8s环境,我强烈推荐使用Rook部署方案。以下是Rook的核心组件:

graph TD
    Rook_Operator -->|管理| CephCluster
    CephCluster -->|包含| MONs
    CephCluster -->|包含| OSDs
    CephCluster -->|包含| MGRs
    Rook_Operator -->|提供| StorageClass

2.3 MySQL版本选择考量

MySQL在K8s中的部署需要考虑以下版本特性:

版本 容器化支持 Group Replication 内存管理 推荐场景
5.7 基础支持 需要额外配置 较简单 传统应用迁移
8.0 优化支持 原生支持 精细化 新建云原生应用

建议选择MySQL 8.0+版本,其对分布式场景的支持更完善。特别是以下特性非常有用:

  • 原子DDL操作
  • 改进的Group Replication
  • 更好的内存管理(新增memory_limit参数)

3. Ceph集群部署实战

3.1 通过Rook部署Ceph集群

首先创建Rook的命名空间和Operator:

kubectl create namespace rook-ceph
kubectl apply -f https://raw.githubusercontent.com/rook/rook/release-1.8/cluster/examples/kubernetes/ceph/operator.yaml

等待Operator就绪后,部署Ceph集群配置文件:

# cluster.yaml
apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
  name: rook-ceph
  namespace: rook-ceph
spec:
  dataDirHostPath: /var/lib/rook
  mon:
    count: 3
    allowMultiplePerNode: false
  cephVersion:
    image: ceph/ceph:v16.2.7
  storage:
    useAllNodes: false
    useAllDevices: false
    nodes:
    - name: "worker-node1"
      devices:
      - name: "sdb"  # 必须是裸设备
    - name: "worker-node2" 
      devices:
      - name: "sdb"
  dashboard:
    enabled: true

应用配置并验证状态:

kubectl apply -f cluster.yaml
# 检查部署状态
kubectl -n rook-ceph get pods -w

常见问题:如果OSD pods一直处于Pending状态,通常是因为:

  1. 指定设备已被占用(检查lsblk)
  2. 节点没有正确标签(需要添加rook.io/storage-node=true)
  3. 节点资源不足(特别是内存)

3.2 创建StorageClass供MySQL使用

Ceph通过RBD提供块存储服务,需要创建对应的StorageClass:

# storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: rook-ceph-block
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
  clusterID: rook-ceph
  pool: replicapool
  imageFormat: "2"
  imageFeatures: layering
  csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
  csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
  csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner
  csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
  csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
  csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
reclaimPolicy: Retain
allowVolumeExpansion: true

关键参数说明:

  • pool : 使用的Ceph存储池,建议为数据库单独创建pool
  • reclaimPolicy : 生产环境建议设为Retain,避免误删PV导致数据丢失
  • allowVolumeExpansion : 启用存储卷扩容功能

4. MySQL在K8s中的部署方案

4.1 StatefulSet部署模型

MySQL作为有状态服务,必须使用StatefulSet进行部署。以下是核心配置要点:

# mysql-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: "mysql"
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: rootPassword
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "rook-ceph-block"
      resources:
        requests:
          storage: 20Gi

关键设计考量:

  1. 副本数 :生产环境建议至少3个副本以实现高可用
  2. 存储大小 :根据数据量预估,建议初始20GB并预留扩容空间
  3. 资源配置 :MySQL 8.0建议每个实例至少分配4核CPU和8GB内存

4.2 数据持久化验证

部署完成后,验证数据持久化是否正常工作:

# 连接到MySQL pod
kubectl exec -it mysql-0 -- mysql -uroot -p

# 创建测试数据库
CREATE DATABASE ceph_test;
USE ceph_test;
CREATE TABLE test_data (id INT PRIMARY KEY, value VARCHAR(255));
INSERT INTO test_data VALUES (1, 'persistence_test');

# 删除pod并验证数据
kubectl delete pod mysql-0
# 等待K8s重建pod后再次连接,检查数据是否存在

4.3 性能优化配置

在Ceph RBD上运行MySQL需要特别关注以下性能参数:

  1. Ceph端配置

    # 在Ceph配置中增加以下参数
    [osd]
    osd_op_num_threads_per_shard = 4
    osd_op_num_shards = 8
    rbd_cache = true
    rbd_cache_size = 256MB
    
  2. MySQL端配置

    # my.cnf关键参数
    [mysqld]
    innodb_buffer_pool_size = 4G  # 建议为系统内存的50-70%
    innodb_io_capacity = 2000
    innodb_io_capacity_max = 4000
    innodb_flush_neighbors = 0    # SSD环境下建议禁用
    innodb_flush_method = O_DIRECT
    
  3. K8s存储类参数优化

    parameters:
      mapOptions: lock_on_read,queue_depth=1024
      csi.volumeAttributes:
        mounter: rbd-nbd  # 使用内核模块提升性能
        disableInUseChecks: "true"
    

5. 高可用与备份方案

5.1 MySQL Group Replication配置

在K8s中实现MySQL高可用的最佳实践是使用Group Replication:

-- 在每个MySQL实例上执行
SET SQL_LOG_BIN=0;
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;

-- 在第一个节点上
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;

-- 在其他节点上
START GROUP_REPLICATION;

对应的K8s Service配置需要支持读写分离:

apiVersion: v1
kind: Service
metadata:
  name: mysql-read
spec:
  ports:
  - name: mysql
    port: 3306
  selector:
    app: mysql
  clusterIP: None

---
apiVersion: v1
kind: Service
metadata:
  name: mysql-write
spec:
  ports:
  - name: mysql
    port: 3306
  selector:
    app: mysql
    statefulset.kubernetes.io/pod-name: mysql-0  # 只指向主节点

5.2 基于Ceph快照的备份方案

利用Ceph的快照功能实现MySQL的时间点恢复:

# 创建快照
rbd snap create replicapool/csi-vol-<pv-id>@snap-$(date +%Y%m%d)

# 定期快照策略(CronJob示例)
apiVersion: batch/v1
kind: CronJob
metadata:
  name: mysql-snapshot
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: rbd-snap
            image: ceph/ceph:v16
            command:
            - /bin/sh
            - -c
            - |
              rbd snap create replicapool/csi-vol-$(kubectl get pvc mysql-data-mysql-0 -o jsonpath='{.spec.volumeName}')@snap-$(date +%Y%m%d)
              rbd snap ls replicapool/csi-vol-$(kubectl get pvc mysql-data-mysql-0 -o jsonpath='{.spec.volumeName}')

恢复数据时,可以基于快照创建新的PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-restore
spec:
  storageClassName: rook-ceph-block
  dataSource:
    name: snap-20230801
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

6. 监控与运维实践

6.1 监控体系搭建

完整的监控需要覆盖三个层面:

  1. Ceph集群监控

    • 通过Rook自带的Prometheus exporter暴露指标
    • 关键指标:OSD状态、存储池使用率、IOPS延迟
  2. MySQL监控

    • 使用mysqld_exporter采集数据库指标
    • 关键指标:查询延迟、连接数、缓冲池命中率
  3. K8s资源监控

    • 通过kube-state-metrics获取PVC/PV状态
    • 关键指标:存储卷容量、IOPS限制

示例Grafana监控面板配置:

-- MySQL关键查询
SELECT 
  SUM(COUNT_STAR) AS QPS,
  SUM(SUM_TIMER_WAIT)/SUM(COUNT_STAR)/1e9 AS avg_latency 
FROM performance_schema.events_statements_summary_by_digest 
WHERE DIGEST_TEXT NOT LIKE '%performance_schema%';

6.2 日常运维命令速查

Ceph常用命令

# 检查集群状态
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph -s

# 查看OSD使用情况
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph osd df

# 调整存储池副本数
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph osd pool set replicapool size 3

MySQL运维命令

# 快速检查Group Replication状态
kubectl exec -it mysql-0 -- mysql -uroot -p -e "SELECT * FROM performance_schema.replication_group_members"

# 手动故障转移(当主节点失效时)
kubectl exec -it mysql-1 -- mysql -uroot -p -e "SELECT group_replication_set_as_primary('mysql-1.mysql.default.svc.cluster.local:3306')"

6.3 性能调优实战案例

案例1:解决高并发写入延迟问题

现象:MySQL在业务高峰期出现写入延迟增加,Ceph监控显示OSD队列深度持续高位。

解决方案:

  1. 调整Ceph OSD线程数:
    ceph tell osd.* injectargs '--osd_op_num_threads_per_shard 8'
    
  2. 优化MySQL事务提交频率:
    innodb_flush_log_at_trx_commit = 2  # 平衡性能与持久性
    sync_binlog = 1000
    
  3. 增加RBD缓存大小:
    parameters:
      rbd_cache_size: "512MB"
    

案例2:存储卷扩容操作

当MySQL数据增长需要扩容PVC时:

# 1. 编辑PVC定义
kubectl edit pvc mysql-data-mysql-0
# 修改spec.resources.requests.storage为所需大小

# 2. 在Ceph端确认扩容
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- rbd info replicapool/csi-vol-<pv-id>

# 3. 在MySQL内部确认文件系统已扩容
kubectl exec -it mysql-0 -- df -h /var/lib/mysql

7. 故障排查与问题解决

7.1 常见问题速查表

问题现象 可能原因 解决方案
MySQL pod一直CrashLoopBackOff 数据目录权限问题 设置initContainer修正权限
Ceph OSD无法启动 设备已被占用 使用lsblk检查设备,清理残留分区
存储卷无法扩容 StorageClass未允许扩容 修改allowVolumeExpansion: true
Group Replication无法同步 网络策略限制 检查Calico/NetworkPolicy配置
RBD挂载超时 内核模块缺失 节点安装rbd-nbd工具

7.2 数据恢复实战

当误删重要数据时,可以通过以下步骤恢复:

  1. 从最近的快照创建新PVC
  2. 启动临时MySQL实例挂载该PVC
  3. 使用mysqldump导出需要的数据
  4. 将数据导入生产数据库

具体操作:

# 1. 创建恢复用的PVC
kubectl apply -f mysql-restore.yaml

# 2. 启动临时MySQL实例
kubectl run mysql-restore --image=mysql:8.0 --restart=Never \
  --overrides='{"spec":{"volumes":[{"name":"mysql-data","persistentVolumeClaim":{"claimName":"mysql-restore"}}],"containers":[{"name":"mysql","image":"mysql:8.0","volumeMounts":[{"name":"mysql-data","mountPath":"/var/lib/mysql"}]}]}}'

# 3. 导出数据
kubectl exec -it mysql-restore -- mysqldump -uroot -p dbname > dump.sql

# 4. 导入生产库
kubectl cp dump.sql mysql-0:/tmp/
kubectl exec -it mysql-0 -- mysql -uroot -p dbname < /tmp/dump.sql

7.3 关键日志收集

当出现问题时,需要收集以下关键日志:

  1. Ceph相关

    kubectl -n rook-ceph logs deploy/rook-ceph-operator
    kubectl -n rook-ceph logs deploy/rook-ceph-osd-0
    
  2. MySQL相关

    kubectl logs mysql-0
    kubectl exec -it mysql-0 -- cat /var/log/mysql/error.log
    
  3. 存储插件日志

    kubectl -n rook-ceph logs deploy/csi-rbdplugin-provisioner
    

对于复杂问题,建议同时收集以下信息:

  • kubectl describe pod/mysql-0
  • kubectl get events --sort-by=.metadata.creationTimestamp
  • Ceph状态输出: ceph -s ceph osd df

更多推荐