1. 为什么需要这种组合?

想象一下这样的场景:你的电商平台在"双十一"凌晨突然数据库宕机,所有交易数据丢失,同时每秒有上万用户无法提交订单。这正是需要MySQL主从架构提供实时数据冗余,而Kubernetes的StatefulSet能保证数据库实例永远在线的根本原因。这种组合就像给数据库上了双重保险,既满足业务高可用需求,又符合云原生时代的部署规范。

2. 基础环境准备

2.1 示例使用的技术栈

# 版本声明(置于首个代码块顶部)
# Kubernetes v1.25+
# Docker 20.10+
# MySQL 8.0.30+
# 存储类:rook-cephfs (生产推荐) 或 hostPath (测试使用)

2.2 创建专属命名空间

apiVersion: v1
kind: Namespace
metadata:
  name: db-prod
  labels:
    tier: database

3. StatefulSet核心配置解剖

3.1 主从架构设计蓝图

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-cluster
  namespace: db-prod
spec:
  serviceName: "mysql-svc"
  replicas: 3  # 1主2从
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      # 设置初始化容器处理主从配置
      initContainers:
      - name: init-mysql
        image: mysql:8.0
        command: ["bash", "/init/init.sh"]
        volumeMounts:
        - name: init-script
          mountPath: /init
      # 主要容器配置
      containers:
      - name: mysql
        image: mysql:8.0
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: rootPassword
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
        # 重要健康检查配置
        livenessProbe:
          exec:
            command: ["mysqladmin", "ping", "-uroot", "-p$(MYSQL_ROOT_PASSWORD)"]
          initialDelaySeconds: 30
          periodSeconds: 10
      volumes:
      - name: init-script
        configMap:
          name: mysql-init-script
  volumeClaimTemplates:
  - metadata:
      name: mysql-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "rook-cephfs"
      resources:
        requests:
          storage: 50Gi

3.2 主从初始化关键脚本

#!/bin/bash
# 存放于ConfigMap中的初始化脚本
set -ex

# 获取Pod索引编号(StatefulSet核心特性)
HOSTNAME=$(hostname -s)
INDEX=${HOSTNAME##*-}

# 主节点处理逻辑
if [ $INDEX -eq 0 ]; then
  echo "正在初始化主库..." 
  # 生成主库专用配置文件
  cat > /etc/mysql/conf.d/master.cnf <<EOF
[mysqld]
server-id=1
log-bin=mysql-bin
binlog_format=ROW
gtid_mode=ON
enforce_gtid_consistency=ON
EOF

# 从节点处理逻辑
else
  echo "正在配置第${INDEX}个从库"
  # 获取主库IP(通过Headless Service)
  MASTER_HOST=$(dig mysql-svc-0.mysql-svc.db-prod.svc.cluster.local +short)
  
  # 生成从库配置文件
  cat > /etc/mysql/conf.d/slave.cnf <<EOF
[mysqld]
server-id=$((INDEX+1))
relay-log=mysql-relay
read_only=1
super_read_only=1
EOF

  # 等待主库就绪
  until mysql -h ${MASTER_HOST} -uroot -p${MYSQL_ROOT_PASSWORD} -e 'SELECT 1'; do
    echo "等待主库响应..."
    sleep 5
  done

  # 配置主从复制
  mysql -uroot -p${MYSQL_ROOT_PASSWORD} <<SQL
CHANGE MASTER TO
  MASTER_HOST='${MASTER_HOST}',
  MASTER_USER='repl',
  MASTER_PASSWORD='${REPLICATION_PASSWORD}',
  MASTER_AUTO_POSITION=1;
START SLAVE;
SQL
fi

4. 配套服务的艺术

4.1 Headless Service设计

apiVersion: v1
kind: Service
metadata:
  name: mysql-svc
  namespace: db-prod
spec:
  clusterIP: None  # 关键设置!
  selector:
    app: mysql
  ports:
  - name: mysql
    port: 3306

4.2 外部访问网关(可选)

apiVersion: v1
kind: Service
metadata:
  name: mysql-proxy
spec:
  type: LoadBalancer
  selector:
    app: mysql
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306

5. 你必须知道的技术细节

5.1 网络标识的稳定性奥秘

每个Pod会获得固定DNS名称:

  • mysql-cluster-0.mysql-svc.db-prod.svc.cluster.local
  • mysql-cluster-1.mysql-svc.db-prod.svc.cluster.local
  • mysql-cluster-2.mysql-svc.db-prod.svc.cluster.local

这种命名规则意味着:

  1. 重启Pod不会改变DNS地址
  2. 可以精确指定连接到主节点(索引为0的Pod)
  3. 应用代码可以直接引用固定域名

5.2 数据持久化精要

存储配置采用了volumeClaimTemplates,它具备以下特性:

  • 每个Pod自动创建独立的PVC
  • PVC命名规则:<volumeClaimTemplateName>-<statefulsetName>-<ordinal>
  • 支持动态卷供应(需预配StorageClass)
  • 数据卷与Pod实例生命周期解耦

6. 技术优势与限制

6.1 三大核心优势

  1. 有序部署:确保主节点(编号0)先启动完成
  2. 稳定网络标识:应用程序无需处理IP变动
  3. 自动故障转移:Pod故障后自动重建并挂载原数据卷

6.2 当前方案的局限性

  1. 主节点故障需手工切换(可配合Kubernetes Operator解决)
  2. 原生方案不处理数据备份(需结合Velero等工具)
  3. 批量写入性能受限于存储方案

7. 典型应用场景

7.1 最适配的用例

  • 需要事务支持的电商订单系统
  • 金融交易流水记录系统
  • 在线教育平台的课程信息管理
  • 社交平台的用户关系数据存储

7.2 不推荐场景

  • 临时测试环境(可用Deployment简化部署)
  • PB级时序数据存储(考虑专用时序数据库)
  • 需要多主架构的场景(需使用Galera Cluster)

8. 部署注意事项

8.1 存储选择金标准

  • 生产环境必须使用支持RWO的存储类
  • 推荐:Ceph RBD、Portworx、Local PV
  • 避免:hostPath(无法保证数据持久性)

8.2 安全配置要点

# Secret创建示例(需提前准备)
apiVersion: v1
kind: Secret
metadata:
  name: mysql-secrets
type: Opaque
data:
  rootPassword: BASE64编码值
  replicationPassword: BASE64编码值

8.3 监控方案搭配

推荐组合:

  1. Prometheus + mysqld_exporter
  2. 自定义Kubernetes事件监控
  3. 慢查询日志分析(需挂载额外卷)

9. 故障排查指南

9.1 常见问题速查表

现象 检查方向 诊断命令
从库不同步 主从连接状态 SHOW SLAVE STATUS\G
Pod启动失败 存储卷状态 kubectl describe pvc
主节点失联 DNS解析检查 nslookup mysql-svc-0.mysql-svc
性能瓶颈 资源使用率 kubectl top pod

9.2 关键日志查看

# 查看指定Pod的初始化日志
kubectl logs mysql-cluster-0 -c init-mysql

# 实时追踪主节点日志
kubectl logs -f mysql-cluster-0 --tail=100

10. 总结与展望

通过本文的实践,我们已经完整实现了:

  1. 基于StatefulSet的自动编排主从架构
  2. 稳定的网络标识与存储配置
  3. 生产级的安全加固方案
  4. 完整的监控与排错体系

未来的演进方向可能包括:

  • 结合Operator实现自动故障转移
  • 集成多活架构扩展写能力
  • 智能查询路由中间件的集成