在容器服务 Serverless 版上部署有状态的高可用MySQL集群

高可用是分布式应用的重要要求,在ACK Serverless集群中,您可以通过K8s原生调度语义实现分布式应用的跨可用区打散,以达到高可用部署的要求。本文档介绍如何在容器服务 Serverless 版上部署有状态的高可用MySQL集群。

前提条件

步骤一:从Github拉取用于创建K8s资源的YAML文件

  1. 执行以下命令,克隆代码库。

    git clone https://github.com/AliyunContainerService/serverless-k8s-examples.git
  2. 执行以下命令,进入工作目录,并查看目录下YAML文件列表。

    cd serverless-k8s-examples/stateful-mysql
    ls -al

    预期输出:

    README.md		secret.yaml		stateful-mysql.yaml	 storageclass.yaml

    其中secret.yaml用于创建Secret,storageclass.yaml用于创建StorageClass,stateful-mysql.yaml用于创建MySQL StatefulSet。

步骤二:创建NameSpace、Secret、StorageClass

  1. 执行以下命令,创建命名空间mysql

    kubectl create namespace mysql

    预期输出:

    namespace/mysql created
  2. 执行以下命令,创建MySQL Secret,用于存储MySQL密码。

    kubectl apply -n mysql -f secret.yaml

    预期输出:

    secret/mysql-secret created

    以下为该Secret的YAML文件。

    展开查看YAML文件

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: fast-storageclass
    provisioner: diskplugin.csi.alibabacloud.com
    parameters:
      type: cloud_auto,cloud_essd,cloud_ssd # 使用该配置,按优先级自适应选择云盘类型,最终创建的云盘类型受节点实例、所在可用区云盘支持情况等因素影响。
      fstype: ext4
      diskTags: "a:b,b:c"
      encrypted: "false"
      performanceLevel: PL1
      volumeExpandAutoSnapshot: "forced" # 该设置仅在创建的云盘类型为cloud_essd时生效。
      provisionedIops: "40000"
      burstingEnabled: "false"
    volumeBindingMode: WaitForFirstConsumer # 表示推迟云盘创建直到Pod创建,可实现云盘在Pod所在可用区创建。
    reclaimPolicy: Retain
    allowVolumeExpansion: true
  3. 执行以下命令,创建StorageClass。

    kubectl apply -f storageclass.yaml

    预期输出:

    storageclass.storage.k8s.io/fast-storageclass created

    以下为该StorageClass的YAML文件。

    展开查看YAML文件

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: fast-storageclass
    provisioner: diskplugin.csi.alibabacloud.com
    parameters:
      type: cloud_auto,cloud_essd,cloud_ssd # 使用该配置,按优先级自适应选择云盘类型,最终创建的云盘类型受节点实例、所在可用区云盘支持情况等因素影响。
      fstype: ext4
      diskTags: "a:b,b:c"
      encrypted: "false"
      performanceLevel: PL1
      volumeExpandAutoSnapshot: "forced" # 该设置仅在创建的云盘类型为cloud_essd时生效。
      provisionedIops: "40000"
      burstingEnabled: "false"
    volumeBindingMode: WaitForFirstConsumer # 表示推迟云盘创建直到Pod创建,可实现云盘在Pod所在可用区创建。
    reclaimPolicy: Retain
    allowVolumeExpansion: true

步骤三:配置Pod可用区打散,创建MySQL StatefulSet

  1. 执行以下命令,创建MySQL StatefulSet。本示例将创建一个通过配置虚拟节点Pod可用区打散,在多个可用区上均匀分布的StatefulSet。关于如何配置虚拟节点Pod可用区打散,请参见实现ECI Pod可用区打散以及亲和调度

    kubectl apply -n mysql -f stateful-mysql.yaml

    预期输出:

    statefulset.apps/dbc1 created

    以下为该StatefulSet的YAML文件。

    展开查看YAML文件

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: dbc1
      labels:
        app: mysql
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: mysql
      serviceName: mysql
      template:
        metadata:
          labels:
            app: mysql
        spec:
          topologySpreadConstraints:
            - maxSkew: 1
              topologyKey: "topology.kubernetes.io/zone"
              whenUnsatisfiable: DoNotSchedule
              labelSelector:
                matchLabels:
                  app: mysql
          affinity:
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                - labelSelector:
                    matchExpressions:
                      - key: app
                        operator: In
                        values:
                          - mysql
                  topologyKey: "kubernetes.io/hostname"
          containers:
            - name: mysql
              image: registry.cn-hangzhou.aliyuncs.com/kubeway/hub:mysql-server_8.0.28
              command:
                - /bin/bash
              args:
                - -c
                - >-
                  /entrypoint.sh
                  --server-id=$((20 +  $(echo $HOSTNAME | grep -o '[^-]*$') + 1))
                  --report-host=${HOSTNAME}.mysql.mysql.svc.cluster.local
                  --binlog-checksum=NONE
                  --enforce-gtid-consistency=ON
                  --gtid-mode=ON
                  --default-authentication-plugin=mysql_native_password
              env:
                - name: MYSQL_ROOT_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: mysql-secret
                      key: password
                - name: MYSQL_ADMIN_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: mysql-secret
                      key: admin-password
                - name: MYSQL_ROOT_HOST
                  value: "%"
              ports:
                - name: mysql
                  containerPort: 3306
                - name: mysqlx
                  containerPort: 33060
                - name: xcom
                  containerPort: 33061
              resources:
                limits:
                  cpu: "500m"
                  ephemeral-storage: "1Gi"
                  memory: "1Gi"
                requests:
                  cpu: "500m"
                  ephemeral-storage: "1Gi"
                  memory: "1Gi"
              volumeMounts:
                - name: mysql
                  mountPath: /var/lib/mysql
                  subPath: mysql
              readinessProbe:
                exec:
                  command:
                    - bash
                    - "-c"
                    - |
                      mysql -h127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e'SELECT 1'
                initialDelaySeconds: 5
                periodSeconds: 2
                timeoutSeconds: 1
              livenessProbe:
                exec:
                  command:
                    - bash
                    - "-c"
                    - |
                      mysqladmin -uroot -p$MYSQL_ROOT_PASSWORD ping
                initialDelaySeconds: 30
                periodSeconds: 10
                timeoutSeconds: 5
      updateStrategy:
        rollingUpdate:
          partition: 0
        type: RollingUpdate
      volumeClaimTemplates:
        - metadata:
            name: mysql
            labels:
              app: mysql
          spec:
            storageClassName: fast-storageclass
            volumeMode: Filesystem
            accessModes:
              - ReadWriteOnce
            resources:
              requests:
                storage: 25Gi

步骤四:验证MySQL集群中的Pod部署情况

  1. 执行以下命令,验证StatefulSet是否已成功创建。

    kubectl get statefulset -n mysql

    预期输出:

    NAME   READY   AGE
    dbc1   3/3     7m21s
  2. 执行以下命名,查看Pod详细信息。

    kubectl -n mysql get po -o wide

    预期输出:

    NAME     READY   STATUS    RESTARTS   AGE     IP             NODE                            NOMINATED NODE   READINESS GATES
    dbc1-0   1/1     Running   0          2m28s   10.1.214.213   virtual-kubelet-cn-hangzhou-j   <none>           <none>
    dbc1-1   1/1     Running   0          106s    10.3.146.113   virtual-kubelet-cn-hangzhou-h   <none>           <none>
    dbc1-2   1/1     Running   0          64s     10.4.232.78    virtual-kubelet-cn-hangzhou-g   <none>           <none>

    其中NODE列为Pod所在节点,节点名称中包含可用区的信息。从节点名称中可以看到Pod被打散到不同的可用区中。

相关文档