MySQL高阶讲座之:`MySQL`在`Kubernetes`中的有状态应用实践。

各位朋友,晚上好! 很高兴能和大家一起聊聊MySQL在Kubernetes(简称K8s)中的有状态应用实践。今天咱们不搞那些虚头巴脑的理论,直接上干货,用最接地气的方式,把MySQL在K8s里玩转的各种姿势给大家扒个精光。

一、 为什么要在K8s里跑MySQL?(先别急着说“为了装X”)

你可能会想,MySQL跑得好好的,干嘛非要放到K8s里折腾?这就像把自行车放到F1赛道,不是没事找事吗?其实不然。K8s能给MySQL带来很多好处:

  • 自动化运维: K8s可以自动部署、扩展、升级MySQL,省去人工运维的烦恼。想象一下,半夜收到告警,不用爬起来手动重启MySQL,K8s自动帮你搞定,是不是很爽?
  • 弹性伸缩: 当业务量增加时,K8s可以自动扩容MySQL实例,保证服务稳定。再也不用担心因为流量突增而导致数据库崩溃了。
  • 高可用性: K8s可以监控MySQL实例的状态,并在实例发生故障时自动进行故障转移。即使服务器宕机,也能保证数据库持续可用。
  • 资源利用率: K8s可以根据实际需求动态分配资源给MySQL实例,提高资源利用率。再也不用为每个MySQL实例预留大量的闲置资源了。
  • 环境一致性: K8s通过容器化技术,保证MySQL在不同环境(开发、测试、生产)中的运行环境一致。避免了“在我的机器上运行得好好的”这种尴尬情况。

总而言之,把MySQL放到K8s里,可以大大提高数据库的可用性、可伸缩性和可维护性,让咱们可以更专注于业务开发,而不是整天跟数据库故障作斗争。

二、 MySQL在K8s里的几种玩法

在K8s里跑MySQL,主要有以下几种方式:

  1. Deployment + Service: 这是最简单的方式,适合对数据持久化要求不高的场景。
  2. StatefulSet + PersistentVolumeClaim (PVC): 这是最常用的方式,适合需要持久化存储的场景。
  3. Operator: 这是最高级的玩法,可以实现更复杂的自动化运维功能。

下面咱们分别来看一下这几种方式的具体实现。

1. Deployment + Service

这种方式就像把MySQL当成一个无状态应用来对待。每个MySQL实例都是一样的,没有唯一的标识符,数据存储在容器的临时存储里。当容器重启时,数据就会丢失。

  • 适用场景:

    • 测试环境
    • 对数据持久化要求不高的临时应用
  • 优点:

    • 简单易用
  • 缺点:

    • 数据不可靠
    • 不适合生产环境
  • YAML示例:

    # mysql-deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: mysql
    spec:
      selector:
        matchLabels:
          app: mysql
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: mysql
        spec:
          containers:
          - image: mysql:5.7
            name: mysql
            env:
            - name: MYSQL_ROOT_PASSWORD
              value: "your_password" # 替换为你的root密码
            ports:
            - containerPort: 3306
              name: mysql
    
    # mysql-service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: mysql
    spec:
      ports:
      - port: 3306
        name: mysql
      selector:
        app: mysql
    • 解释:

      • Deployment 创建一个名为 mysql 的 Deployment,它会运行一个 MySQL 容器。
      • Service 创建一个名为 mysql 的 Service,它会将流量转发到 app=mysql 的 Pod 上。
      • MYSQL_ROOT_PASSWORD 环境变量设置 MySQL 的 root 用户密码。
  • 部署:

    kubectl apply -f mysql-deployment.yaml
    kubectl apply -f mysql-service.yaml

2. StatefulSet + PVC

这种方式是K8s官方推荐的运行有状态应用的方式。每个MySQL实例都有一个唯一的标识符,数据存储在持久卷(Persistent Volume)上。当容器重启时,数据不会丢失。

  • 适用场景:

    • 生产环境
    • 需要持久化存储的应用
  • 优点:

    • 数据可靠
    • 支持自动故障转移
  • 缺点:

    • 配置相对复杂
  • YAML示例:

    # mysql-statefulset.yaml
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: mysql
    spec:
      selector:
        matchLabels:
          app: mysql
      serviceName: mysql
      replicas: 3 # 调整副本数量
      template:
        metadata:
          labels:
            app: mysql
        spec:
          terminationGracePeriodSeconds: 10 # 优雅停止时间
          containers:
          - name: mysql
            image: mysql:5.7
            env:
            - name: MYSQL_ROOT_PASSWORD
              value: "your_password" # 替换为你的root密码
            ports:
            - containerPort: 3306
              name: mysql
            volumeMounts:
            - name: mysql-data
              mountPath: /var/lib/mysql
      volumeClaimTemplates:
      - metadata:
          name: mysql-data
        spec:
          accessModes: [ "ReadWriteOnce" ]
          resources:
            requests:
              storage: 10Gi # 调整存储大小
    
    # mysql-service.yaml (Headless Service)
    apiVersion: v1
    kind: Service
    metadata:
      name: mysql
    spec:
      clusterIP: None # Headless Service的关键
      selector:
        app: mysql
    • 解释:

      • StatefulSet 创建一个名为 mysql 的 StatefulSet,它会运行 3 个 MySQL 实例。
      • serviceName: mysql 指定用于访问 StatefulSet 的 Service 的名称。
      • volumeClaimTemplates 定义了用于存储 MySQL 数据的 PersistentVolumeClaim 的模板。每个 MySQL 实例都会创建一个自己的 PersistentVolumeClaim,并挂载到 /var/lib/mysql 目录下。
      • Headless Service clusterIP: None 这是Headless Service 的关键,它不会分配 Cluster IP,而是将每个Pod的DNS记录直接暴露出来。
      • terminationGracePeriodSeconds 设置了 Pod 的优雅停止时间,避免数据丢失。
  • 部署:

    kubectl apply -f mysql-service.yaml
    kubectl apply -f mysql-statefulset.yaml
  • 注意:

    • 你需要先配置好K8s的存储提供者(例如:hostPathNFSCephGlusterFS等)。
    • accessModes 的选择取决于你的存储提供者。ReadWriteOnce 表示卷可以被单个节点以读写方式挂载。
    • storage 的大小应该根据你的实际需求进行调整。

3. Operator

Operator是一种高级的K8s扩展机制,它可以自动化部署、配置和管理复杂的应用。针对MySQL,已经有一些成熟的Operator可以使用,例如:Percona Operator for MySQLMySQL Operator for Kubernetes等。

  • 适用场景:

    • 对自动化运维要求高的生产环境
    • 需要复杂配置和管理的应用
  • 优点:

    • 高度自动化
    • 简化运维工作
  • 缺点:

    • 学习成本高
    • 配置复杂
  • 以 Percona Operator for MySQL 为例:

    Percona Operator for MySQL 简化了在 Kubernetes 上部署和管理 Percona Server for MySQL 的过程。它提供:

    • 自动部署: 通过简单的 YAML 文件定义 MySQL 集群,Operator 自动完成部署。

    • 自动扩展: 轻松扩展集群的副本数量,应对流量增长。

    • 自动备份与恢复: 配置备份策略,Operator 定期备份数据,并在需要时快速恢复。

    • 自动升级: 无缝升级 MySQL 版本,减少停机时间。

    • 监控与告警: 集成 Prometheus 和 Grafana,提供详细的监控指标和告警功能。

    • 安装步骤 (简化版):

      1. 安装 Operator Lifecycle Manager (OLM): OLM 是一个帮助你在 Kubernetes 上安装、升级和管理 Operator 的框架。

        kubectl create -f https://operatorhub.io/install/olm.yaml
      2. 创建 OperatorGroup: OperatorGroup 定义了 Operator 可以管理的命名空间。

        apiVersion: operators.coreos.com/v1
        kind: OperatorGroup
        metadata:
          name: mysql-operator-group
          namespace: mysql-ns # 替换为你的命名空间
        spec:
          targetNamespaces:
          - mysql-ns # 替换为你的命名空间
        kubectl apply -f operatorgroup.yaml
      3. 创建 Subscription: Subscription 告诉 OLM 从 OperatorHub.io 安装 Percona Operator for MySQL。

        apiVersion: operators.coreos.com/v1alpha1
        kind: Subscription
        metadata:
          name: percona-server-mysql-operator
          namespace: mysql-ns # 替换为你的命名空间
        spec:
          channel: stable # 选择稳定通道
          name: percona-server-mysql-operator
          source: operatorhubio-catalog
          sourceNamespace: olm
        kubectl apply -f subscription.yaml
      4. 创建 PerconaServerForMySQL 集群: 使用 YAML 文件定义 MySQL 集群的配置。

        apiVersion: psmdb.percona.com/v1
        kind: PerconaServerForMySQL
        metadata:
          name: my-cluster # 替换为你的集群名称
          namespace: mysql-ns # 替换为你的命名空间
        spec:
          crVersion: 1.12.0 # 检查最新的 CR 版本
          secretsName: my-cluster-secrets
          size: 3 # 副本数量
          image: percona/percona-server-mysql:5.7 # 选择 MySQL 镜像
          pmm:
            enabled: false # 禁用 PMM 监控 (可选)
          backup:
            enabled: false # 禁用备份 (可选)
        kubectl apply -f mysql-cluster.yaml
    • 解释:

      • 需要先安装 Operator Lifecycle Manager (OLM)
      • 通过 Subscription 订阅 Percona Operator for MySQL
      • 通过 PerconaServerForMySQL CRD (Custom Resource Definition) 定义 MySQL 集群的配置。
      • size 指定集群的副本数量。
      • image 指定 MySQL 的镜像。
      • pmmbackup 分别用于配置 PMM 监控和备份。
  • 注意:

    • Operator 的安装和配置相对复杂,需要仔细阅读官方文档。
    • 不同的 Operator 有不同的配置方式和功能,需要根据实际需求进行选择。

三、 MySQL在K8s里的一些注意事项

在K8s里跑MySQL,需要注意以下几点:

  1. 存储: 选择合适的存储提供者,并根据实际需求配置存储大小和访问模式。
  2. 网络: 确保K8s集群的网络能够访问到MySQL实例。可以使用Service或者Ingress来暴露MySQL服务。
  3. 安全: 使用Secret来存储MySQL的密码等敏感信息。
  4. 监控: 使用Prometheus等监控工具来监控MySQL实例的状态。
  5. 备份: 定期备份MySQL数据,以防止数据丢失。
  6. 资源限制: 为MySQL实例设置合理的资源限制(CPU、内存),以防止资源耗尽。
  7. 健康检查: 配置 liveness 和 readiness 探测,确保 K8s 能够正确判断 MySQL 实例的健康状态。

四、 MySQL在K8s里的最佳实践

  1. 使用StatefulSet + PVC: 这是最常用的方式,适合需要持久化存储的场景。
  2. 使用Operator: 如果对自动化运维要求高,可以考虑使用Operator。
  3. 配置合理的资源限制: 为MySQL实例设置合理的资源限制(CPU、内存),以防止资源耗尽。
  4. 定期备份数据: 使用mysqldump或者其他备份工具定期备份MySQL数据。
  5. 监控MySQL实例的状态: 使用Prometheus等监控工具来监控MySQL实例的状态。
  6. 使用Secret存储敏感信息: 使用Secret来存储MySQL的密码等敏感信息。
  7. 定期更新MySQL镜像: 及时更新MySQL镜像,以获取最新的安全补丁和功能。
  8. 优雅停止: 配置 terminationGracePeriodSeconds,确保 MySQL 实例在停止前能够完成清理工作,避免数据丢失。

五、 总结

今天给大家介绍了MySQL在K8s里的几种玩法,以及一些注意事项和最佳实践。希望大家能够从中受益,并在实际工作中灵活运用。记住,没有最好的方案,只有最适合自己的方案。选择哪种方式取决于你的实际需求和技术水平。

最后,祝大家在K8s里玩转MySQL,早日实现自动化运维,解放双手!

感谢大家!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注