咱们好,我是老 Z!

上篇文章完成了 MySQL 数据库在基于 KubeSphere 布置的 K8s 集群上的装置布置,布置办法采用了图形化界面这种办法。本文将会介绍怎么运用 GitOps 来布置 MySQL,布置进程触及的一切 YAML 文件都会运用 Git 进行版别办理,并寄存在 Git 库房中。因而,本文还会触及 GitOps 的根底操作。

原生 K8s 运用 GitOps 布置 MySQL

上篇文章咱们完成了经过 KubeSphere 布置单实例 MySQL,那么原生的 K8s 又该怎么操作?GitOps 又是什么、又该怎么完成?

什么是 GitOps(网文摘抄)

  • GitOps 是一套运用 Git 来办理根底架构和运用装备的实践,而 Git 指的是一个开源版控制体系。
  • GitOps 在运转进程中以 Git 为声明性根底架构和运用的单一事实来源。
  • GitOps 运用 Git 拉取恳求来主动办理根底架构的置备和布置。
  • Git 存储库包括体系的悉数状况,因而体系状况的修正痕迹既可检查也可审计。
  • GitOps 经常被用作 K8s 和云原生运用开发的运维模式,并且能够完成对 K8s 的继续布置。
  • GitOps 是一种继续交给的办法。它的核心思维是将运用体系的声明性根底架构和运用程序寄存在 Git 版别库中。

预备资源装备清单-思路整理

咱们知道玩 K8s 的必备技术便是要手写资源装备清单,一般运用 YAML 格式的文件来创立咱们预期的资源装备。

此时咱们也要手写 MySQL 的资源装备清单?我很慌,参数我记不全啊。

NO!NO!NO!投机取巧的时刻到了,前面卖的关子在这揭开了。

前面咱们现已经过 KubeSphere 的图形界面创立了 MySQL 的资源装备,而且 KubeSphere 一个很棒的功能便是能够直接在线修正资源的 YAML 文件。

咱们能够在创立资源的时分,直接修正 YAML 文件创立资源。也能够经过修正 YAML 的办法修正已有的资源。

当然啊,你不用图形界面,直接在 K8s 底层用指令行的办法去获取 YAML 格式的输出,再修正,也是能够的。

整理一下 MySQL 触及的资源装备清单包括的资源。

  • StatefulSet(有状况副本集)
  • Service(服务)
    • 集群内部(Headless)
    • 集群外部(自定义服务)
  • ConfigMap
  • Secret

接下来咱们就别离获取这些资源装备清单。

预备资源装备清单

ConfigMap

装备->装备字典,找到 mysql-cnf,点击右侧的三个竖点,点击修正 YAML

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

打开修正 YAML 页面,能够直接复制一切内容,也能够点击右上角的下载图标,下载文件 (也能够运用上传图标上传文件)。

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

获取的现网装备不能彻底的拿来就用,需求修正,把体系主动增加的一些元数据信息整理掉。

现网的 mysql-cfm.yaml

kind: ConfigMap
apiVersion: v1
metadata:
  name: mysql-cnf
  namespace: lstack
  annotations:
    kubesphere.io/creator: lstack
data:
  custom.cnf: |-
    [mysqld]
    #performance setttings
    lock_wait_timeout = 3600
    open_files_limit    = 65535
    back_log = 1024
    max_connections = 512
    max_connect_errors = 1000000
    table_open_cache = 1024
    table_definition_cache = 1024
    thread_stack = 512K
    sort_buffer_size = 4M
    join_buffer_size = 4M
    read_buffer_size = 8M
    read_rnd_buffer_size = 4M
    bulk_insert_buffer_size = 64M
    thread_cache_size = 768
    interactive_timeout = 600
    wait_timeout = 600
    tmp_table_size = 32M
    max_heap_table_size = 32M
    

修正后的 mysql-cfm.yaml

kind: ConfigMap
apiVersion: v1
metadata:
  name: mysql-cnf
  namespace: lstack
data:
  custom.cnf: |-
    [mysqld]
    #performance setttings
    lock_wait_timeout = 3600
    open_files_limit    = 65535
    back_log = 1024
    max_connections = 512
    max_connect_errors = 1000000
    table_open_cache = 1024
    table_definition_cache = 1024
    thread_stack = 512K
    sort_buffer_size = 4M
    join_buffer_size = 4M
    read_buffer_size = 8M
    read_rnd_buffer_size = 4M
    bulk_insert_buffer_size = 64M
    thread_cache_size = 768
    interactive_timeout = 600
    wait_timeout = 600
    tmp_table_size = 32M
    max_heap_table_size = 32M

Secret

装备->保密字典,找到 mysql-secret,点击右侧的三个竖点,点击修正 YAML

现网的 mysql-secret.yaml

kind: Secret
apiVersion: v1
metadata:
  name: mysql-secret
  namespace: lstack
  annotations:
    kubesphere.io/creator: lstack
data:
  MYSQL_ROOT_PASSWORD: UEA4OHcwcmQ=
type: Opaque

修正后的 mysql-secret.yaml

kind: Secret
apiVersion: v1
metadata:
  name: mysql-secret
  namespace: lstack
data:
  MYSQL_ROOT_PASSWORD: UEA4OHcwcmQ=
type: Opaque

这儿要说一句,Secret 里的值是用 base64 办法加密的,所以这儿的 MYSQL_ROOT_PASSWORD,要用实践的暗码用 base64 的办法加密。

  • base64 解密。

    [root@ks-k8s-master-0 ~]# echo "UEA4OHcwcmQ=" | base64 -d
    P@88w0rd
    
  • base 加密。

    [root@ks-k8s-master-0 ~]# echo -n "P@88w0rd" | base64
    UEA4OHcwcmQ=
    

StatefulSet

运用负载->作业负载->有状况副本集,找到 mysql,点击右侧的三个竖点,点击修正 YAML

现网的 mysql-sts.yaml

kind: StatefulSet
apiVersion: apps/v1
metadata:
  name: mysql
  namespace: lstack
  labels:
    app: mysql
  annotations:
    kubesphere.io/creator: lstack
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: mysql
      annotations:
        logging.kubesphere.io/logsidecar-config: '{}'
    spec:
      volumes:
        - name: host-time
          hostPath:
            path: /etc/localtime
            type: ''
        - name: volume-rca2zx
          configMap:
            name: mysql-cnf
            items:
              - key: custom.cnf
                path: custom.cnf
            defaultMode: 420
      containers:
        - name: lstack-mysql
          image: 'mysql:5.7.38'
          ports:
            - name: tcp-mysql
              containerPort: 3306
              protocol: TCP
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: MYSQL_ROOT_PASSWORD
          resources:
            limits:
              cpu: '2'
              memory: 4000Mi
            requests:
              cpu: 500m
              memory: 500Mi
          volumeMounts:
            - name: host-time
              mountPath: /etc/localtime
            - name: data
              mountPath: /var/lib/mysql
            - name: volume-rca2zx
              readOnly: true
              mountPath: /etc/mysql/conf.d/custom.cnf
              subPath: custom.cnf
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      dnsPolicy: ClusterFirst
      serviceAccountName: default
      serviceAccount: default
      securityContext: {}
      schedulerName: default-scheduler
  volumeClaimTemplates:
    - kind: PersistentVolumeClaim
      apiVersion: v1
      metadata:
        name: data
        namespace: lstack
        creationTimestamp: null
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 5Gi
        storageClassName: glusterfs
        volumeMode: Filesystem
      status:
        phase: Pending
  serviceName: mysql-1dpr
  podManagementPolicy: OrderedReady
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 0
  revisionHistoryLimit: 10

修正后的 mysql-sts.yaml

kind: StatefulSet
apiVersion: apps/v1
metadata:
  name: mysql
  namespace: lstack
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      volumes:
        - name: host-time
          hostPath:
            path: /etc/localtime
            type: ''
        - name: volume-cnf
          configMap:
            name: mysql-cnf
            items:
              - key: custom.cnf
                path: custom.cnf
            defaultMode: 420
      containers:
        - name: lstack-mysql
          image: 'mysql:5.7.38'
          ports:
            - name: tcp-mysql
              containerPort: 3306
              protocol: TCP
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: MYSQL_ROOT_PASSWORD
          resources:
            limits:
              cpu: '2'
              memory: 4000Mi
            requests:
              cpu: 500m
              memory: 500Mi
          volumeMounts:
            - name: host-time
              mountPath: /etc/localtime
            - name: data
              mountPath: /var/lib/mysql
            - name: volume-cnf
              mountPath: /etc/mysql/conf.d/custom.cnf
              subPath: custom.cnf
  volumeClaimTemplates:
    - metadata:
        name: data
        namespace: lstack
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 5Gi
        storageClassName: glusterfs
  serviceName: mysql-headless

Service

先创立 Headless 服务,运用负载->服务->,找到 mysql-xxxx(mysql),点击右侧的三个竖点,点击修正 YAML

现网的 mysql-headless.yaml

kind: Service
apiVersion: v1
metadata:
  name: mysql-1dpr
  namespace: lstack
  labels:
    app: mysql
  annotations:
    kubesphere.io/alias-name: mysql
    kubesphere.io/creator: lstack
    kubesphere.io/serviceType: statefulservice
spec:
  ports:
    - name: tcp-mysql
      protocol: TCP
      port: 3306
      targetPort: 3306
  selector:
    app: mysql
  clusterIP: None
  clusterIPs:
    - None
  type: ClusterIP
  sessionAffinity: None
  ipFamilies:
    - IPv4
  ipFamilyPolicy: SingleStack

修正后的 mysql-headless.yaml

kind: Service
apiVersion: v1
metadata:
  name: mysql-headless
  namespace: lstack
  labels:
    app: mysql
spec:
  ports:
    - name: tcp-mysql
      protocol: TCP
      port: 3306
      targetPort: 3306
  selector:
    app: mysql
  clusterIP: None
  type: ClusterIP

再看看自定义的 mysql-external 服务 ,运用负载->服务->,找到 mysql-external,点击右侧的三个竖点,点击修正 YAML

现网的 mysql-external.yaml

kind: Service
apiVersion: v1
metadata:
  name: mysql-external
  namespace: lstack
  labels:
    app: mysql-external
  annotations:
    kubesphere.io/creator: lstack
spec:
  ports:
    - name: tcp-mysql-external
      protocol: TCP
      port: 3306
      targetPort: 3306
      nodePort: 32529
  selector:
    app: mysql
  clusterIP: 10.233.36.71
  clusterIPs:
    - 10.233.36.71
  type: NodePort
  sessionAffinity: None
  externalTrafficPolicy: Cluster
  ipFamilies:
    - IPv4
  ipFamilyPolicy: SingleStack

这儿有一点要阐明 nodePort 这个参数,如果 K8s 集群可控,主张规划一套服务端口运用标准,每个需求 nodePort 的服务都指定固定的端口,这样有利于运维的标准化。

修正后的 mysql-external.yaml(留意 nodePort 参数没有指定)。

kind: Service
apiVersion: v1
metadata:
  name: mysql-external
  namespace: lstack
  labels:
    app: mysql-external
spec:
  ports:
    - name: tcp-mysql-external
      protocol: TCP
      port: 3306
      targetPort: 3306
  selector:
    app: mysql
  type: NodePort

将 MySQL 资源装备清单提交到 Git 库房。

经过上面的操作,咱们获取了 MySQL 的资源装备清单。

本人强迫症,喜爱分类寄存,所以我用了 4 个文件,mysql-headless.yamlmysql-sts.yaml 合并在一个文件当然你也能够放到一个装备文件里。

  • mysql-external.yaml
  • mysql-sts.yaml
  • mysql-secret.yaml
  • mysql-cfm.yaml

将资源装备清单提交到 Git 库房

挑选 GitHub 作为主库房,Gitee 作为同步库房 (人工)。

本系列文档一切 k8s 的资源装备清单文件运用了一个公共库房,出产环境主张每种服务创立一个装备库房,有利于更精细化的版别控制。

本文为了演示主备库房的运用,一切挑选了 Github 和 Gitee 两种 Git 服务,实践运用中为了更好的运用体会主张挑选 Gitee。

在 GitHub 新建一个库房,库房名称**k8s-yaml,增加一个 README 文件初始化库房,点击Create repository**,承认创立。

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

将代码库房 Clone 回本地。

$ git clone git@github.com:devops/k8s-yaml.git
$ ls k8s-yaml 
README.md

新创立一个文件夹,用自己喜爱的文本修正器 (推荐 vscode) 修正 MySQL 的资源装备清单,并将文件放入新创立的文件夹。

为了今后的扩展性,这儿创立了一个 single 命名的二级目录,寄存单实例的资源装备清单文件。

$ mkdir -p k8s-yaml/mysql/single
$ ls -l k8s-yaml/mysql/single
total 32
-rw-r--r--  1 z  staff   646  5 11 19:23 mysql-cfm.yaml
-rw-r--r--  1 z  staff   266  5 11 19:31 mysql-external.yaml
-rw-r--r--  1 z  staff   134  5 11 19:23 mysql-secret.yaml
-rw-r--r--  1 z  staff  1911  5 11 19:31 mysql-sts.yaml

将修正好的资源装备文件清单,提交到 GitHub。

$ cd k8s-yaml
$ git add .
$ git commit -am '增加MySQL single资源装备清单'
$ git push

在 GitHub 上检查,承认代码是否提交。

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

接下来将资源装备清单同步到 Gitee 备份库房。

  • 本文采用了手艺推送同步的办法 (个人习气)
  • Gitee 也支持主动同步 GitHub 的库房 (更快捷)

在 Gitee 新建一个库房,库房名称**k8s-yaml,类型默许私有**,点击创立

创立完成后可去库房设置中修正为开源。

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

创立完成后,因为咱们创立的时分,没挑选初始化库房的装备,所以,默许会显现一个协助页面,告知你该怎么提交代码到库房。

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

因为,咱们现已有了代码库房,所以咱们挑选已有库房的装备办法,将已有代码提交到 Gitee。

依据协助提示操作,要留意 origin 咱们要换成 gitee

$ git remote add gitee https://gitee.com/zdevops/k8s-yaml.git
$ git push -u gitee

在 Gitee 上检查,承认代码是否提交。

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

修正 Gitee 库房为开源 (可选)。

Gitee 库房->办理->库房设置->根本信息,最后面是否开源,挑选开源库房揭露须知,三个都勾选,点击保存

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

修正后,你的代码库房便是开源,一切人可见的了。

GitOps 初体会-在 K8s 集群上布置 MySQL

MySQL 资源装备清单现已寄存到了 Git 在线库房,接下来开启咱们的 GitOps 体会之旅。

登录 k8s 的 master 节点,履行后面的操作任务。

出产环境主张打造独立的运维办理节点进行整个集群的办理 , 能够参阅《基于 KubeSphere 玩转 k8s-运维办理节点打造手记》

装置 Git。

$ yum install git -y

创立 devops 目录,我挑选 /opt 目录作为 devops 的根目录。

$ mkdir /opt/devops
$ cd /opt/devops/

从 Gitee 下载 k8s-yaml 库房的代码。

$ git clone https://gitee.com/zdevops/k8s-yaml.git
$ ls k8s-yaml/
mysql  README.md

由所以同一个测验环境,先整理掉现有的 MySQL 服务。

$ kubectl get secrets -n lstack
NAME                  TYPE                                  DATA   AGE
default-token-x2gzv   kubernetes.io/service-account-token   3      31d
mysql-secret          Opaque                                1      2d20h

$ kubectl get configmaps -n lstack 
NAME               DATA   AGE
kube-root-ca.crt   1      31d
mysql-cnf          1      47h

$ kubectl get service -n lstack 
NAME                                                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
glusterfs-dynamic-afe88cf4-86b1-4215-833a-534c5f779a22   ClusterIP   10.233.13.188   <none>        1/TCP            2d
mysql-1dpr                                               ClusterIP   None            <none>        3306/TCP         2d
mysql-external                                           NodePort    10.233.36.71    <none>        3306:32529/TCP   47h

$ kubectl get statefulsets -n lstack 
NAME    READY   AGE
mysql   1/1     2d

# 整理
$ kubectl delete statefulsets mysql -n lstack
statefulset.apps "mysql" deleted
$ kubectl delete service mysql-external -n lstack
service "mysql-external" deleted
$ kubectl delete service mysql-1dpr -n lstack
service "mysql-1dpr" deleted
$ kubectl delete secrets mysql-secret -n lstack
secret "mysql-secret" deleted
$ kubectl delete configmaps mysql-cnf -n lstack
configmap "mysql-cnf" deleted

运用资源装备清单一键布置 MySQL。

$ cd /opt/devops/k8s-yaml/
$ ls
mysql  README.md

$ kubectl apply -f mysql/single/

验证成果,发现 StatefulSet 没有创立,分析问题。

$ kubectl get statefulsets -n lstack
No resources found in lstack namespace.

# 一开始我认为我遗漏了装备文件,ls看一眼,发现文件都在
$ ls
mysql  README.md
$ cd mysql/
$ ls
single
$ cd single/
$ ls
mysql-cfm.yaml  mysql-external.yaml  mysql-secret.yaml  mysql-sts.yaml

# 承认一下文件内容,发现文件也有内容
$ vi mysql-sts.yaml

# 再次履行,发现了端倪,为啥只有service/mysql-headless 的资源装备,没有statefulset
$ kubectl apply -f mysql-sts.yaml 
service/mysql-headless unchanged

# 再次承认,发现修正文件的时分遗漏了一点,当一个装备文件有多种资源定义时,不同资源的装备直接需求用"---"分隔。修正装备文件再次履行,发现履行成功。
$ vi mysql-sts.yaml
$ cd ..

$ kubectl apply -f single/

$ kubectl get statefulsets -n lstack -o wide
NAME    READY   AGE   CONTAINERS     IMAGES
mysql   1/1     31s   lstack-mysql   mysql:5.7.38
$ kubectl get pods -n lstack -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP              NODE              NOMINATED NODE   READINESS GATES
mysql-0   1/1     Running   0          35s   10.233.116.59   ks-k8s-master-2   <none>           <none>

回到咱们的 KubeSphere 的办理控制台,发现 mysql 的作业负载也能在界面中显现,这也验证了在原生 k8s 上的操作也会直接反应到 KubeSphere 的办理控制台。

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

二次体会 GitOps

正好借着上面呈现的问题,二次体会一下 GitOps。咱们直接在布置服务器上修正了 mysql-sts.yaml,且修正后的成果验证成功。

为了演示 GitOps 的更多场景,直接在布置服务器上修正,然后提交到在线代码库房。

实践作业中我都是在自己的办公电脑上修正,提交到在线代码库房,然后布置服务器拉取更新代码。

修正后的 mysql-sts.yaml,因为篇幅问题这儿只演示关键部分,StatefulSet 的完好装备见 Gitee 库房或是前文。

---
kind: StatefulSet
apiVersion: apps/v1
metadata:
  name: mysql
  namespace: lstack
  labels:
    app: mysql
...
---
kind: Service
apiVersion: v1
metadata:
  name: mysql-headless
  namespace: lstack
  labels:
    app: mysql
spec:
  ports:
    - name: tcp-mysql
      protocol: TCP
      port: 3306
      targetPort: 3306
  selector:
    app: mysql
  clusterIP: None
  type: ClusterIP

提交修正后的代码到代码库房。

# 修正后检查git库房的改变
$ git diff 
diff --git a/mysql/single/mysql-sts.yaml b/mysql/single/mysql-sts.yaml
index f775920..1eded9c 100644
--- a/mysql/single/mysql-sts.yaml
+++ b/mysql/single/mysql-sts.yaml
@@ -1,3 +1,4 @@
+---
 kind: StatefulSet
 apiVersion: apps/v1
 metadata:
@@ -68,6 +69,7 @@ spec:
         storageClassName: glusterfs
   serviceName: mysql-headless
+---
 kind: Service
 apiVersion: v1
 metadata:

# 本地提交代码改变
$ git commit -am '修复mysql statefulset装备不生效问题'

# push到在线代码库房,有一个warning能够疏忽,也能够按提示履行
$ git push

检查 Gitee 在线代码库房是否有改变。

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

在个人的办公电脑上,同步更新后的代码。

# 更新代码
$ git pull

# 同步更新后的代码到Github
$ git push -u origin

检查 GitHub 在线代码库房是否有改变。

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

再次体会 GitOps

模仿一个业务场景,再次体会一下 GitOps。

  • MySQL 上线运转后,因为业务量上涨,初始装备参数中的 max_connections 太小了,需求增大。

  • 装备参数调整完成后,更新线上装备,并重启服务 (出产环境数据库不要容易重启,这种需求能够用临时修正解决)。

  • 这儿仅仅模仿一个简单的例子,带咱们体会 GitOps,实践运用中一切的装备文件都主张运用 Git 进行版别控制。

修正本地 Git 库房 MySQL 资源装备清单中的 mysql-cfm.yaml 文件,修正 max_connections,从 512 变成 1024。

提交修正到 Git 在线库房。

# 提交本地修正
$ git commit -am '修正mysql-cnf中max_connections的值'

# 提交到Github
$ git push

# 同步到Gitee
$ git push -u gitee

登录运维办理节点,更新 Git 代码,并重新运转。

$ git pull

$ kubectl apply -f mysql/single/

# 检查ConfigMap的改变
$ kubectl get configmaps mysql-cnf -n lstack -o yaml
apiVersion: v1
data:
  custom.cnf: |-
    [mysqld]
    #performance setttings
    lock_wait_timeout = 3600
    open_files_limit    = 65535
    back_log = 1024
    max_connections = 1024
    max_connect_errors = 1000000
    table_open_cache = 1024
    table_definition_cache = 1024
    thread_stack = 512K
    sort_buffer_size = 4M
    join_buffer_size = 4M
    read_buffer_size = 8M
    read_rnd_buffer_size = 4M
    bulk_insert_buffer_size = 64M
    thread_cache_size = 768
    interactive_timeout = 600
    wait_timeout = 600
    tmp_table_size = 32M
    max_heap_table_size = 32M
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"custom.cnf":"[mysqld]\n#performance setttings\nlock_wait_timeout = 3600\nopen_files_limit    = 65535\nback_log = 1024\nmax_connections = 1024\nmax_connect_errors = 1000000\ntable_open_cache = 1024\ntable_definition_cache = 1024\nthread_stack = 512K\nsort_buffer_size = 4M\njoin_buffer_size = 4M\nread_buffer_size = 8M\nread_rnd_buffer_size = 4M\nbulk_insert_buffer_size = 64M\nthread_cache_size = 768\ninteractive_timeout = 600\nwait_timeout = 600\ntmp_table_size = 32M\nmax_heap_table_size = 32M"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"mysql-cnf","namespace":"lstack"}}
  creationTimestamp: "2022-05-12T07:20:07Z"
  name: mysql-cnf
  namespace: lstack
  resourceVersion: "8928391"
  uid: 1b7322cf-f11e-445d-a2ba-b42a90ade469

# 重启mysql pod使装备生效
$ kubectl delete -f mysql/single/mysql-sts.yaml 

$ kubectl apply -f mysql/single/mysql-sts.yaml 

# 检查mysql容器内部装备是否更新
$ kubectl exec  mysql-0  -n lstack -- cat /etc/mysql/conf.d/custom.cnf
[mysqld]
#performance setttings
lock_wait_timeout = 3600
open_files_limit    = 65535
back_log = 1024
max_connections = 1024
max_connect_errors = 1000000
table_open_cache = 1024
table_definition_cache = 1024
thread_stack = 512K
sort_buffer_size = 4M
join_buffer_size = 4M
read_buffer_size = 8M
read_rnd_buffer_size = 4M
bulk_insert_buffer_size = 64M
thread_cache_size = 768
interactive_timeout = 600
wait_timeout = 600
tmp_table_size = 32M

牢记! 上面的例子仅仅让咱们体会 GitOps,出产环境不要容易重启数据库服务器,除非你知道自己在干什么。

现在经过验证,咱们的 MySQL 的装备可用且比较稳定,咱们把这个好的状况记载下来,防止今后修正改变弄坏了,再找不回本来正确的装备。

在咱们的个人电脑上给当时的 Git 代码打个 Tag,记载当时的状况 (也能够经过在线库房的办理界面操作)。

# 打tag -a tag姓名 -m tag描述
$ git tag -a v0.1  -m 'mysql version v0.1'

# 检查现有tag
$ git tag -l
v0.1

# 检查tag详细信息
$ git show v0.1
tag v0.1
Tagger: devops <devops@163.com>
Date:   Thu May 12 18:15:34 2022 +0800
mysql version v0.1
commit 180f97ac96da504a0b46eb4871ef423f64fde093 (HEAD -> main, tag: v0.1, origin/main, origin/HEAD, gitee/main)
Author: devops <devops@163.com>
Date:   Thu May 12 17:48:18 2022 +0800
    修正mysql-cnf中max_connections的值
diff --git a/mysql/single/mysql-cfm.yaml b/mysql/single/mysql-cfm.yaml
index e24d96d..50d1778 100644
--- a/mysql/single/mysql-cfm.yaml
+++ b/mysql/single/mysql-cfm.yaml
@@ -10,7 +10,7 @@ data:
     lock_wait_timeout = 3600
     open_files_limit    = 65535
     back_log = 1024
-    max_connections = 512
+    max_connections = 1024
     max_connect_errors = 1000000
     table_open_cache = 1024
     table_definition_cache = 1024
# 将tag推送到长途服务器
$ git push -u origin --tags
$ git push -u gitee --tags

# 线上服务器验证(图略)

运维办理服务器更新代码,并切换到指定 tag(留意!运用 Git 一定要养成每次操作前 git pull 这种习气)。

## 更新代码
$ git pull

## 切换到v0.1
$ git checkout -b v0.1

经过上面的几波操作,咱们能够看到,咱们一切的装备改变都采用了 Git 办理,完好的记载了装备的全生命周期办理,经过给库房打分支或是 tag,能够方便咱们切换到任意已记载状况。

高可用布置 MySQL(预留占坑)

暂时没有高可用布置的需求,因而不触及高可用模式的 MySQL 的布置,但是有一些考虑藏着占坑。

现在的做法

  • 不给自己找麻烦,有高可用需求直接买云服务商的 RDS。
  • 真实需求自己搭建,在 K8s 集群之外布置主从。

今后可能的方向

  • K8s 上的 MySQL 主从布置
  • Operator
  • Helm

遗留问题

此部分内容也是运维 MySQL 必备的技术,有些内容我也没有经历无法共享,有些内容会在 << 基于 KubeSphere 的 K8s 出产实践之路 >> 系列文档中介绍。

  • MySQL 数据库备份
  • MySQL 高可用布置
  • MySQL 安全加固
  • MySQL 调优

MySQL 功能 (基准) 测验

运维一定要做到对自己的运维环境心中有数,MySQL 上线前一定要进行功能 (基准测验),有助于了解咱们的数据库服务器能达到的抱负状况。本次介绍的仅仅皮毛,仅仅告知咱们一些根本入门的知识,更细节、更深化的内容请参阅其他更专业的文档。

功能 (基准) 测验东西装置

东西选型 (sysbench)

  • 云厂商展示自家数据库产品功能都用这个东西
  • 听说许多 DBA 也喜爱用

sysbench 东西装置

  • 装置东西
# 导入软件源
$ curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.rpm.sh | sudo bash
# 装置sysbench
$ yum install sysbench -y
  • 验证-履行指令检查版别
$ sysbench --version
sysbench 1.0.20

功能 (基准) 测验

测验方案

  • 测验参数

  • 目标
    线程 8/16/32
    单表数据量 100000
    表数量 16

    功能目标

    目标 阐明
    TPS Transactions Per Second ,即数据库每秒履行的业务数,以 commit 成功次数为准。
    QPS Queries Per Second ,即数据库每秒履行的 SQL 数(含 insert、select、update、delete 等)。
    RT Response Time ,呼应时刻。包括均匀呼应时刻、最小呼应时刻、最大呼应时刻、每个呼应时刻的查询占比。比较需求要点关注的是,前 95-99% 的最大呼应时刻。因为它决定了大多数情况下的短板。
    Concurrency Threads 并发量,每秒可处理的查询恳求的数量。

预备测验数据

运用咱们在 k8s 上创立的数据库,触及数据库操作指令,需求终端登录到容器内运转。

提前创立测验用数据库 sbtest,并赋予 root 从任意 IP 长途办理一切数据库的权限。

出产环境千万不要这么搞,一定要遵从最小化原则!

# bash
root@mysql-0:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.38 MySQL Community Server (GPL)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database sbtest;
Query OK, 1 row affected (0.02 sec)

mysql> grant all privileges on *.* to 'root'@'%' identified by 'P@88w0rd' with grant option;
Query OK, 0 rows affected, 1 warning (0.02 sec)
  • 测验数据库是否能连接
# 装置mysql客户端,下面的示例是在k8s节点上装置的,因为体系是最小化装置,一切会装置许多依靠。实践测验能够起一个mysql的pod或是用其他的mysql客户端东西。

$ yum install mysql -y

# 测验MySQL服务连通性 -h 是k8s节点的IP -P 是mysql外部服务的端口号

$ mysql -h 192.168.9.91 -P 32529 -u root -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.38 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> 
  • 预备测验数据
$ sysbench --db-driver=mysql --mysql-host=192.168.9.91 --mysql-port=32529 --mysql-user=root --mysql-password=P@88w0rd --mysql-db=sbtest --table-size=100000 --tables=16 --threads=8 --events=999999999 --report-interval=10 --time=100 /usr/share/sysbench/oltp_common.lua prepare
sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2)
Initializing worker threads...
Creating table 'sbtest6'...
Creating table 'sbtest2'...
Creating table 'sbtest8'...
Creating table 'sbtest3'...
Creating table 'sbtest7'...
Creating table 'sbtest5'...
Creating table 'sbtest1'...
Creating table 'sbtest4'...
Inserting 100000 records into 'sbtest3'
Inserting 100000 records into 'sbtest6'
Inserting 100000 records into 'sbtest1'
Inserting 100000 records into 'sbtest4'
Inserting 100000 records into 'sbtest7'
Inserting 100000 records into 'sbtest5'
Inserting 100000 records into 'sbtest2'
Inserting 100000 records into 'sbtest8'
Creating a secondary index on 'sbtest3'...
Creating table 'sbtest11'...
Inserting 100000 records into 'sbtest11'
Creating a secondary index on 'sbtest5'...
Creating a secondary index on 'sbtest1'...
Creating a secondary index on 'sbtest6'...
Creating a secondary index on 'sbtest4'...
Creating a secondary index on 'sbtest7'...
Creating a secondary index on 'sbtest2'...
Creating a secondary index on 'sbtest8'...
Creating table 'sbtest13'...
Inserting 100000 records into 'sbtest13'
Creating table 'sbtest9'...
Inserting 100000 records into 'sbtest9'
Creating table 'sbtest14'...
Creating table 'sbtest12'...
Inserting 100000 records into 'sbtest14'
Inserting 100000 records into 'sbtest12'
Creating table 'sbtest15'...
Inserting 100000 records into 'sbtest15'
Creating table 'sbtest16'...
Creating table 'sbtest10'...
Inserting 100000 records into 'sbtest16'
Inserting 100000 records into 'sbtest10'
Creating a secondary index on 'sbtest11'...
Creating a secondary index on 'sbtest13'...
Creating a secondary index on 'sbtest9'...
Creating a secondary index on 'sbtest12'...
Creating a secondary index on 'sbtest14'...
Creating a secondary index on 'sbtest15'...
Creating a secondary index on 'sbtest10'...
Creating a secondary index on 'sbtest16'...
  • 履行测验-8 线程测验
$ sysbench --db-driver=mysql --mysql-host=192.168.9.91 --mysql-port=32529 --mysql-user=root --mysql-password=P@88w0rd --mysql-db=sbtest --table-size=100000 --tables=16 --threads=8 --events=999999999 --report-interval=10 --time=100  /usr/share/sysbench/oltp_read_write.lua run
sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2)
Running the test with following options:
Number of threads: 8
Report intermediate results every 10 second(s)
Initializing random number generator from current time
Initializing worker threads...
Threads started!
[ 10s ] thds: 8 tps: 88.46 qps: 1782.38 (r/w/o: 1249.19/355.46/177.73) lat (ms,95%): 267.41 err/s: 0.00 reconn/s: 0.00
[ 20s ] thds: 8 tps: 84.31 qps: 1678.47 (r/w/o: 1173.42/336.43/168.62) lat (ms,95%): 277.21 err/s: 0.00 reconn/s: 0.00
[ 30s ] thds: 8 tps: 70.20 qps: 1413.82 (r/w/o: 990.21/283.20/140.40) lat (ms,95%): 369.77 err/s: 0.00 reconn/s: 0.00
[ 40s ] thds: 8 tps: 47.30 qps: 946.00 (r/w/o: 662.20/189.20/94.60) lat (ms,95%): 484.44 err/s: 0.00 reconn/s: 0.00
[ 50s ] thds: 8 tps: 43.80 qps: 875.99 (r/w/o: 613.19/175.20/87.60) lat (ms,95%): 484.44 err/s: 0.00 reconn/s: 0.00
[ 60s ] thds: 8 tps: 60.70 qps: 1213.08 (r/w/o: 849.69/242.00/121.40) lat (ms,95%): 411.96 err/s: 0.00 reconn/s: 0.00
[ 70s ] thds: 8 tps: 53.90 qps: 1078.22 (r/w/o: 754.42/216.00/107.80) lat (ms,95%): 376.49 err/s: 0.00 reconn/s: 0.00
[ 80s ] thds: 8 tps: 56.49 qps: 1127.98 (r/w/o: 790.11/224.88/112.99) lat (ms,95%): 397.39 err/s: 0.00 reconn/s: 0.00
[ 90s ] thds: 8 tps: 50.60 qps: 1014.59 (r/w/o: 709.56/203.82/101.21) lat (ms,95%): 434.83 err/s: 0.00 reconn/s: 0.00
[ 100s ] thds: 8 tps: 54.70 qps: 1093.12 (r/w/o: 765.22/218.50/109.40) lat (ms,95%): 390.30 err/s: 0.00 reconn/s: 0.00
SQL statistics:
    queries performed:
        read:                            85582
        write:                           24452
        other:                           12226
        total:                           122260
    transactions:                        6113   (61.10 per sec.)
    queries:                             122260 (1221.96 per sec.)
    ignored errors:                      0      (0.00 per sec.)
    reconnects:                          0      (0.00 per sec.)
General statistics:
    total time:                          100.0494s
    total number of events:              6113
Latency (ms):
         min:                                   35.63
         avg:                                  130.89
         max:                                  951.86
         95th percentile:                      390.30
         sum:                               800129.59
Threads fairness:
    events (avg/stddev):           764.1250/4.14
    execution time (avg/stddev):   100.0162/0.01
  • 履行测验-16 线程测验
$ sysbench --db-driver=mysql --mysql-host=192.168.9.91 --mysql-port=32529 --mysql-user=root --mysql-password=P@88w0rd --mysql-db=sbtest --table-size=100000 --tables=16 --threads=16 --events=999999999 --report-interval=10 --time=100  /usr/share/sysbench/oltp_read_write.lua run
sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2)
Running the test with following options:
Number of threads: 16
Report intermediate results every 10 second(s)
Initializing random number generator from current time
Initializing worker threads...
Threads started!
[ 10s ] thds: 16 tps: 114.41 qps: 2310.22 (r/w/o: 1621.18/458.63/230.41) lat (ms,95%): 369.77 err/s: 0.00 reconn/s: 0.00
[ 20s ] thds: 16 tps: 106.35 qps: 2111.86 (r/w/o: 1474.74/424.41/212.71) lat (ms,95%): 383.33 err/s: 0.00 reconn/s: 0.00
[ 30s ] thds: 16 tps: 80.40 qps: 1612.01 (r/w/o: 1129.21/322.00/160.80) lat (ms,95%): 623.33 err/s: 0.00 reconn/s: 0.00
[ 40s ] thds: 16 tps: 63.40 qps: 1266.80 (r/w/o: 886.80/253.20/126.80) lat (ms,95%): 539.71 err/s: 0.00 reconn/s: 0.00
[ 50s ] thds: 16 tps: 57.20 qps: 1145.91 (r/w/o: 802.74/228.78/114.39) lat (ms,95%): 549.52 err/s: 0.00 reconn/s: 0.00
[ 60s ] thds: 16 tps: 69.91 qps: 1408.31 (r/w/o: 987.57/280.92/139.81) lat (ms,95%): 511.33 err/s: 0.00 reconn/s: 0.00
[ 70s ] thds: 16 tps: 78.00 qps: 1547.22 (r/w/o: 1080.51/310.70/156.00) lat (ms,95%): 484.44 err/s: 0.00 reconn/s: 0.00
[ 80s ] thds: 16 tps: 79.50 qps: 1599.87 (r/w/o: 1122.58/318.29/159.00) lat (ms,95%): 520.62 err/s: 0.00 reconn/s: 0.00
[ 90s ] thds: 16 tps: 67.80 qps: 1354.83 (r/w/o: 947.62/271.61/135.60) lat (ms,95%): 539.71 err/s: 0.00 reconn/s: 0.00
[ 100s ] thds: 16 tps: 73.90 qps: 1474.10 (r/w/o: 1030.80/295.50/147.80) lat (ms,95%): 502.20 err/s: 0.00 reconn/s: 0.00
SQL statistics:
    queries performed:
        read:                            110950
        write:                           31700
        other:                           15850
        total:                           158500
    transactions:                        7925   (79.00 per sec.)
    queries:                             158500 (1580.05 per sec.)
    ignored errors:                      0      (0.00 per sec.)
    reconnects:                          0      (0.00 per sec.)
General statistics:
    total time:                          100.3103s
    total number of events:              7925
Latency (ms):
         min:                                   41.24
         avg:                                  202.44
         max:                                 1198.81
         95th percentile:                      511.33
         sum:                              1604328.52
Threads fairness:
    events (avg/stddev):           495.3125/4.03
    execution time (avg/stddev):   100.2705/0.03
  • 履行测验-32 线程测验
$ sysbench --db-driver=mysql --mysql-host=192.168.9.91 --mysql-port=32529 --mysql-user=root --mysql-password=P@88w0rd --mysql-db=sbtest --table-size=100000 --tables=16 --threads=32 --events=999999999 --report-interval=10 --time=100  /usr/share/sysbench/oltp_read_write.lua run
sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2)
Running the test with following options:
Number of threads: 32
Report intermediate results every 10 second(s)
Initializing random number generator from current time
Initializing worker threads...
Threads started!
[ 10s ] thds: 32 tps: 140.10 qps: 2825.04 (r/w/o: 1981.25/560.39/283.39) lat (ms,95%): 450.77 err/s: 0.00 reconn/s: 0.00
[ 20s ] thds: 32 tps: 124.41 qps: 2515.49 (r/w/o: 1763.43/503.24/248.82) lat (ms,95%): 549.52 err/s: 0.00 reconn/s: 0.00
[ 30s ] thds: 32 tps: 95.90 qps: 1887.10 (r/w/o: 1316.70/378.60/191.80) lat (ms,95%): 733.00 err/s: 0.00 reconn/s: 0.00
[ 40s ] thds: 32 tps: 81.80 qps: 1656.59 (r/w/o: 1164.89/328.10/163.60) lat (ms,95%): 707.07 err/s: 0.00 reconn/s: 0.00
[ 50s ] thds: 32 tps: 82.60 qps: 1638.41 (r/w/o: 1143.51/329.70/165.20) lat (ms,95%): 657.93 err/s: 0.00 reconn/s: 0.00
[ 60s ] thds: 32 tps: 94.34 qps: 1905.84 (r/w/o: 1336.62/380.65/188.58) lat (ms,95%): 623.33 err/s: 0.00 reconn/s: 0.00
[ 70s ] thds: 32 tps: 87.86 qps: 1739.86 (r/w/o: 1215.31/348.73/175.82) lat (ms,95%): 634.66 err/s: 0.00 reconn/s: 0.00
[ 80s ] thds: 32 tps: 84.40 qps: 1705.48 (r/w/o: 1196.49/340.20/168.80) lat (ms,95%): 759.88 err/s: 0.00 reconn/s: 0.00
[ 90s ] thds: 32 tps: 80.50 qps: 1580.71 (r/w/o: 1101.70/318.00/161.00) lat (ms,95%): 612.21 err/s: 0.00 reconn/s: 0.00
[ 100s ] thds: 32 tps: 81.40 qps: 1661.90 (r/w/o: 1167.00/332.10/162.80) lat (ms,95%): 707.07 err/s: 0.00 reconn/s: 0.00
SQL statistics:
    queries performed:
        read:                            133924
        write:                           38264
        other:                           19132
        total:                           191320
    transactions:                        9566   (95.33 per sec.)
    queries:                             191320 (1906.56 per sec.)
    ignored errors:                      0      (0.00 per sec.)
    reconnects:                          0      (0.00 per sec.)
General statistics:
    total time:                          100.3457s
    total number of events:              9566
Latency (ms):
         min:                                   51.94
         avg:                                  335.14
         max:                                 1405.78
         95th percentile:                      657.93
         sum:                              3205913.85
Threads fairness:
    events (avg/stddev):           298.9375/5.15
    execution time (avg/stddev):   100.1848/0.14

MySQL 容器功能监控图。

在 Kubernetes 中基于 StatefulSet 部署 MySQL(下)

整理测验数据 (为了确保数据更精准,主张每次测验前都整理数据,预备数据,测验)。

$ sysbench --db-driver=mysql --mysql-host=192.168.9.91 --mysql-port=32529 --mysql-user=root --mysql-password=P@88w0rd --mysql-db=sbtest --table-size=100000 --tables=16 --threads=32 --events=999999999 --report-interval=10 --time=100  /usr/share/sysbench/oltp_read_write.lua cleanup
sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2)
Dropping table 'sbtest1'...
Dropping table 'sbtest2'...
Dropping table 'sbtest3'...
Dropping table 'sbtest4'...
Dropping table 'sbtest5'...
Dropping table 'sbtest6'...
Dropping table 'sbtest7'...
Dropping table 'sbtest8'...
Dropping table 'sbtest9'...
Dropping table 'sbtest10'...
Dropping table 'sbtest11'...
Dropping table 'sbtest12'...
Dropping table 'sbtest13'...
Dropping table 'sbtest14'...
Dropping table 'sbtest15'...
Dropping table 'sbtest16'...

测验成果

成果汇总对比。

压测线程数量 TPS QPS 延迟
8 61 1221 130
16 79 1580 202
32 95 1906 335

主张依据测验成果,调优!

总结

本文详细介绍了 Git 常用操作、怎么将代码在多个在线代码库房中存储并保持同步,还介绍了 GitOps 的根本概念并演示了怎么用 GitOps 理念在原生 K8s 上布置 MySQL 服务。最后,演示了 MySQL 常用功能测验东西 sysbench 的装置和根底运用。

我多年的一些运维经历和运维思路贯穿了全文。

本文由博客一文多发渠道 OpenWrite 发布!