第3章 云原生应用实战-Kubernetes部署MySql主从

本文详细介绍了在Kubernetes中使用Helm部署MySQL主从集群的方法,包括创建目录结构、配置文件和执行helm命令,确保版本一致以避免问题。
摘要由CSDN通过智能技术生成

第3章 云原生应用实战-Kubernetes部署MySql主从

作者:王珂
邮箱:49186456@qq.com



前言

本节课程主要给大家讲解如何在Kubernetes中搭建一个MySql主从集群。在Kubernetes中部署一个应用我们通常会定义一个Yaml文件,然后将所有声明式API都写在这个Yaml中。但是这样会导致我们的Yaml文件特别庞大,不好维护。当然,我们也可以把不同的资源对象写在单独的Yaml文件中,这种方式有没有对应的规范约束呢?答案是Helm,我就会采用这种方式,具体详见正文。

一、部署MySql主从

1.1 Helm方式部署

我们通过自定helm方式部署MySql主从集群。

  1. mysql-ms目录结构

首先,我们创建一个文件目录叫做mysql-ms-8.0.21(8.0.21表示我们用的MySql版本为8.0.21),其中的文件结构如下:

mysql-ms-8.0.21

│ Chart.yaml
│ values.yaml

├─charts
└─templates
configmap.yaml
namespace.yaml
secret.yaml
service.yaml
statefulset.yaml

  1. 自定义helm文件
  • Chart.yaml
apiVersion: v2
name: mysql-ms
description: A Helm chart for MySql Master Slave Cluster

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
version: 1.0.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application.
appVersion: 8.0.21
  • values.yaml
# Default values for mysql-ms.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
  repository: mysql:8.0.21
  pullPolicy: IfNotPresent

imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""

serviceAccount:
  # Specifies whether a service account should be created
  create: true
  # Annotations to add to the service account
  annotations: {}
  # The name of the service account to use.
  # If not set and create is true, a name is generated using the fullname template
  name:

podSecurityContext: {}
  # fsGroup: 2000

securityContext: {}
  # capabilities:
  #   drop:
  #   - ALL
  # readOnlyRootFilesystem: true
  # runAsNonRoot: true
  # runAsUser: 1000

service:
  type: NodePort
  port: 30081

resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #   cpu: 100m
  #   memory: 128Mi
  # requests:
  #   cpu: 100m
  #   memory: 128Mi

nodeSelector: {}

tolerations: []

affinity: {}
  • namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: ns-mysql
  • configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: cm-mysql-ms
  namespace: ns-mysql
data:
  master.cnf: |
    [client]
    default-character-set=utf8mb4
    # Master配置
    [mysqld]
    character-set-server=utf8mb4
    lower-case-table-names=1
    skip-name-resolve
    log-bin=master-bin
  slave.cnf: |
    [client]
    default-character-set=utf8mb4
    # Slave配置
    [mysqld]
    character-set-server=utf8mb4
    lower-case-table-names=1 
    skip-name-resolve
    log-bin=slave-bin
    #super-read-only
    #replicate-ignore-db=mysql    
  • secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
  namespace: ns-mysql
type: Opaque
data:
  password: MTIzNDU2 # 123456
  # 主从账号
  replicationUser: cmVwbA== # repl
  replicationPassword: MTIzNDU2 # 123456
  • statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: sts-mysql-ms
  namespace: ns-mysql
spec:
  serviceName: svc-mysql-read
  selector:
    matchLabels:
      app: mysql  
  replicas: 2
  template:
    metadata:
      labels:
        app: mysql
    spec:
      # 初始化容器
      initContainers:
      - name: init-mysql
        image: mysql:8.0.21
        command:
        - bash
        - "-c"
        - |
          set -ex
          # 从pod名称的序号生成server-id
          ordinal=`hostname | awk -F "-" '{print $4}'` || exit 1
          echo [mysqld] > /etc/mysql/conf.d/server-id.cnf
          # 因为server-id不能为0,因此给它加上了100
          echo server-id=$((100 + $ordinal)) >> /etc/mysql/conf.d/server-id.cnf
          # 如果ordinal序号为0,说明它是master节点,从configmap里把master节点的配置信息复制到/etc/mysql/conf.d/目录下
          if [ $ordinal -eq 0 ]; then
            cp /mnt/config-map/master.cnf /etc/mysql/conf.d
          else
            cp /mnt/config-map/slave.cnf /etc/mysql/conf.d
          fi
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: password
        - name: MYSQL_REPLICATION_USER
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: replicationUser
        - name: MYSQL_REPLICATION_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: replicationPassword
        volumeMounts:
        #- name: timezone
        #  mountPath: /etc/localtime
        - name: conf
          mountPath: /etc/mysql/conf.d
        - name: config-map
          mountPath: /mnt/config-map

      # 主容器
      containers:
      - name: mysql
        image: mysql:8.0.21
        ports:
        - name: mysql-port
          containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: password
        - name: MYSQL_REPLICATION_USER
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: replicationUser
        - name: MYSQL_REPLICATION_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: replicationPassword          
        volumeMounts:
        #- name: timezone
        #  mountPath: /etc/localtime
        - name: data
          mountPath: /var/lib/mysql
        - name: conf
          mountPath: /etc/mysql/conf.d
        - name: init-sql
          mountPath: /var/run/mysql
        resources:
          requests:
            cpu: 500m
        lifecycle:
          postStart:
            exec:
              command:
              - bash
              - "-c"
              - |
                set -ex
                cd /var/lib/mysql
                # 检查是否存在MySqlInitCompleted文件,如果不存在则进行初始化
                if [ ! -f mysqlInitLock ]; then
                  # 执行一条mysql命令,查看mysql是否准备就绪,如果没有就反复执行直到可以运行MySql命令
                  until mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "use mysql;select 1;"; do sleep 1; done
                  echo "MySql已经就绪"
                  # 判断是master还是slave
                  pod_seq=`hostname | awk -F "-" '{print $4}'`
                  if [ $pod_seq -eq 0 ]; then
                    # 当前为主节点
                    # 授予root可以远程登录
                    #mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "create user 'root'@'%' identified with mysql_native_password by '${MYSQL_ROOT_PASSWORD}';"
                    #mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "grant all privileges on *.* to 'root'@'%' with grant option;"                    
                    # 创建主从账号
                    mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "create user '${MYSQL_REPLICATION_USER}' identified with mysql_native_password by '${MYSQL_REPLICATION_PASSWORD}';"
                    mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "grant replication slave on *.* to '${MYSQL_REPLICATION_USER}'@'%';"                    
                    mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "flush privileges;"
                    mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "reset master;"
                  else
                    # 当前为从节点
                    # 设置slave连接master
                    mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e \
                    "change master to master_host='svc-mysql-write.ns-mysql', master_port=3306, \
                    master_user='${MYSQL_REPLICATION_USER}', master_password='${MYSQL_REPLICATION_PASSWORD}', \
                    master_log_file='master-bin.000001', master_log_pos=156;"
                    # 重置slave
                    mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "reset slave;"
                    # 开始同步
                    mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "start slave;"
                    # 改成只读模式
                    mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "set global read_only=1;"
                  fi
                  touch mysqlInitLock
                fi
        #livenessProbe:
        #  exec:
        #    command: ["mysqladmin", "ping", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]
        #  initialDelaySeconds: 30
        #  periodSeconds: 10
        #  timeoutSeconds: 5
        #readinessProbe:
        #  exec:
        #    command: ["mysqladmin", "ping", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]
        #  initialDelaySeconds: 5
        #  periodSeconds: 2
        #  timeoutSeconds: 1
      volumes:
      - name: config-map
        configMap:
          name: cm-mysql-ms         
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes:
        - "ReadWriteOnce"
      storageClassName: nfs-storage-class
      resources:
        requests:
          storage: 1Gi
  - metadata:
      name: conf
    spec:
      accessModes:
        - "ReadWriteOnce"
      storageClassName: nfs-storage-class
      resources:
        requests:
          storage: 50Mi
  - metadata:
      name: init-sql
    spec:
      accessModes:
        - "ReadWriteOnce"
      storageClassName: nfs-storage-class
      resources:
        requests:
          storage: 50Mi
  • service.yaml
apiVersion: v1
kind: Service
metadata:
  name: svc-mysql-write
  namespace: ns-mysql
spec:
  type: NodePort
  ports:
  - name: mysql-write-port
    port: 3306 # Service 端口
    nodePort: 32306 # 绑定到node的端口(对外暴露的端口)
  selector:
    app: mysql
    statefulset.kubernetes.io/pod-name: sts-mysql-ms-0 # 选择主节点
---
apiVersion: v1
kind: Service
metadata:
  name: svc-mysql-read
  namespace: ns-mysql
  labels:
    app: mysql
spec:
  type: NodePort
  ports:
  - name: mysql-read-port
    port: 3306
    nodePort: 32316
  selector:
    app: mysql
  1. 执行helm命令

创建主从集群

helm install mysql-ms ./mysql-ms-8.0.21

查看helm应用

helm list

卸载命令

helm uninstall mysql-ms

总结

以上就是在Kubernetes中搭建MySql集群的所有步骤,请大家安装版本时最好选择的版本与我保持一致,因为不同的版本可能会碰到一些意想不到的问题,避免踩坑。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值