资讯专栏INFORMATION COLUMN

在K8S集群中一步步构建一个复杂的MySQL数据库

YancyYe / 3296人阅读

摘要:结束语本文揉合多项技术,构建了一个复杂且可做生产使用的范例,当然,此库是单实例数据库,倘若需构建数据库高可用方案,需部署如集群,其中自动作业备份范例仅使用备份,在生产环境不是很实用,我们需要考虑使用备份以及备份日志。

文档说明

​ 本文面向容器初学者,作者先简单的用MySQL官方镜像搭建一个可运行的单实例数据库,而后考虑生产或现实需求,一步一步完善并揉合K8S多个技术,从而构建一个复杂且可供生产用的MySQL单实例库。

简单部署

​ 如下所示,我们仅需设置root用户密码(环境变量MYSQL_ROOT_PASSWORD), 便可轻松的使用MySQL官方镜像构建一个MySQL数据库。

</>复制代码

  1. # kubectl create -f - <
  2. 注意:若你的K8S集群是minishiftopenshiftorigin,因其为安全考虑,不允许容器以root用户运行,而官方MySQL镜像却需root权限,故为使其能顺利运行,我们需将anyuid scc赋予default serviceaccount

  3. </>复制代码

    1. # oc adm policy add-scc-to-user anyuid -z default
  4. ​ 创建一Service以便集群内外均可访问数据库,其中集群外需通过nodePort设置的30006端口访问。

  5. </>复制代码

    1. # kubectl create -f - <
    2. ​ 接着,访问数据库并验证其运行正常:

    3. </>复制代码

      1. # kubectl get pod # 当前Pod名称
      2. NAME READY STATUS RESTARTS AGE
      3. mysql-5b5668c448-t44ml 1/1 Running 0 3h
      4. # 通过本机访问
      5. # kubectl exec -it mysql-5b5668c448-t44ml -- mysql -uroot -pChangeme
      6. mysql> select 1;
      7. +---+
      8. | 1 |
      9. +---+
      10. | 1 |
      11. +---+
      12. # 集群内部通过mysql service访问:
      13. # kubectl exec -it mysql-5b5668c448-t44ml -- mysql -uroot -pChangeme -hmysql
      14. mysql> select now();
      15. +---------------------+
      16. | now() |
      17. +---------------------+
      18. | 2018-05-21 07:19:14 |
      19. +---------------------+
      20. # 集群外部,可通过任何一个K8S节点访问数据库:
      21. # mysql -uroot -pChangeme -horigin-lb-01 -P30006
      22. mysql> show databases;
      23. +--------------------+
      24. | Database |
      25. +--------------------+
      26. | information_schema |
      27. | mysql |
      28. | performance_schema |
      29. | sys |
      30. +--------------------+
    4. 扩展部署
    5. 持久化存储
    6. ​ 若要确保MySQL重启后数据仍然存在,我们需为其配置可持久化存储,作者的实验环境配置了GlusterFS分布式存储,其支持K8S动态提供特性,故可执行如下命令创建PVC

    7. </>复制代码

      1. # kubectl create -f - <
      2. ​ 而后,调整Deploy并挂载卷:

      3. </>复制代码

        1. spec:
        2. containers:
        3. - image: mysql
        4. ...
        5. volumeMounts:
        6. - name: mysql-data
        7. mountPath: /var/lib/mysql
        8. volumes:
        9. - name: mysql-data
        10. persistentVolumeClaim:
        11. claimName: mysql
      4. 自定义配置文件
      5. ​ 通过创建cm并挂载到容器中,我们可自定义MySQL配置文件。如下所示,名为mysql-configcm包含一个custom.cnf文件:

      6. </>复制代码

        1. apiVersion: v1
        2. metadata:
        3. name: mysql-config
        4. data:
        5. custom.cnf: |
        6. [mysqld]
        7. default_storage_engine=innodb
        8. skip_external_locking
        9. lower_case_table_names=1
        10. skip_host_cache
        11. skip_name_resolve
        12. kind: ConfigMap
      7. ​ 将cm挂载到容器内:

      8. </>复制代码

        1. spec:
        2. ...
        3. containers:
        4. - image: mysql
        5. ...
        6. volumeMounts:
        7. - name: mysql-config
        8. mountPath: /etc/mysql/conf.d/
        9. ...
        10. volumes:
        11. - name: mysql-config
        12. configMap:
        13. name: mysql-config
        14. ...
      9. 加密铭感数据
      10. ​ 用户密码等铭感数据以Secret加密保存,而后被Deployment通过volume挂载或环境变量引用。如本例,我们创建rootapptest用户,将3个用户的密码加密保存:

      11. </>复制代码

        1. # echo -n Changeme | base64
        2. Q2hhbmdlbWU=
        3. # kubectl create -f - <
        4. Secret创建完成后,我们将用户明文密码从Deployment去除,采用环境变量方式引用Secret数据,参见如下Yaml修改,做了3个调整:

        5. 镜像初始化时自动创建MYSQL_DATABASE环境变量1设置的数据库;

        6. 镜像初始化时将MYSQL_DATABASE数据库赋予MYSQL_USER用户;

        7. root用户及MYSQL_USER用户,其密码均通过secretKeyRefsecret获取;

        8. </>复制代码

          1. spec:
          2. ...
          3. containers:
          4. - image: mysql
          5. name: mysql
          6. imagePullPolicy: IfNotPresent
          7. env:
          8. - name: MYSQL_ROOT_PASSWORD
          9. valueFrom:
          10. secretKeyRef:
          11. name: mysql-user-pwd
          12. key: mysql-root-pwd
          13. - name: MYSQL_PASSWORD
          14. valueFrom:
          15. secretKeyRef:
          16. name: mysql-user-pwd
          17. key: mysql-app-user-pwd
          18. - name: MYSQL_USER
          19. value: app
          20. - name: MYSQL_DATABASE
          21. value: appdb
        9. 容器健康检查
        10. K8S镜像控制器可通过livenessProbe判断容器是否异常,进而决定是否重建容器;而Service服务可通过readinessProbe判断容器服务是否正常,从而确保服务可用性。

        11. ​ 本例,作者配置的livenessProbereadinessProbe是一样的,即连续3次查询数据库失败,则定义为异常。对livenessProbereadinessProbe详细用法,不在本文的讨论范围内,可参考K8S官方文档:

        12. Configure Liveness and Readiness Probes

        13. Pod Lifecycle

        14. </>复制代码

          1. spec:
          2. containers:
          3. - image: mysql
          4. ...
          5. livenessProbe:
          6. exec:
          7. command:
          8. - /bin/sh
          9. - "-c"
          10. - MYSQL_PWD="${MYSQL_ROOT_PASSWORD}"
          11. - mysql -h 127.0.0.1 -u root -e "SELECT 1"
          12. initialDelaySeconds: 30
          13. timeoutSeconds: 5
          14. successThreshold: 1
          15. failureThreshold: 3
          16. readinessProbe:
          17. exec:
          18. command:
          19. - /bin/sh
          20. - "-c"
          21. - MYSQL_PWD="${MYSQL_ROOT_PASSWORD}"
          22. - mysql -h 127.0.0.1 -u root -e "SELECT 1"
          23. initialDelaySeconds: 10
          24. timeoutSeconds: 1
          25. successThreshold: 1
          26. failureThreshold: 3
          27. ...
        15. 容器初始化
        16. 假设,我们有这样的需求:“初始部署MySQL时,其已包应用所需的数据库、用户、权限、表结构与数据”。研究MySQL官方镜像的Dockerfile可知,数据库初始化时将自动执行目录/docker-entrypoint-initdb.d内的.sh.sql.sql.gz文件,鉴于此,我们可有如下两种方法:

        17. 基于官方镜像重新编写Dockerfile,将脚本copy到新镜像/docker-entrypoint-initdb.d目录,因需编译新镜像,故此方法不灵活;

        18. 初始化容器(initContainers)在常规容器(containers)前运行,故在初始化容器中可将脚本拷贝到共享目录,而后MySQL镜像挂载此目录到/docker-entrypoint-initdb.d,此方法灵活。

        19. 本例,作者采用初始化容器方案,功能如下:

        20. 初始化与常规容器共享名为mysql-initdbemptyDir,均被挂载到/docker-entrypoint-initdb.d目录;

        21. 初始化容器将.sql文件置于共享的/docker-entrypoint-initdb.d目录,其含初始化testdbappdb数据库;

        22. 为了避免MySQL数据库目录内的lost+found目录被误认为是数据库,初始化容器中将其删除;

        23. </>复制代码

          1. spec:
          2. initContainers:
          3. - name: mysql-init
          4. image: busybox
          5. imagePullPolicy: IfNotPresent
          6. env:
          7. - name: MYSQL_TEST_USER_PASSWORD
          8. valueFrom:
          9. secretKeyRef:
          10. name: mysql-user-pwd
          11. key: mysql-test-user-pwd
          12. command:
          13. - sh
          14. - "-c"
          15. - |
          16. set -ex
          17. rm -fr /var/lib/mysql/lost+found
          18. cat > /docker-entrypoint-initdb.d/mysql-testdb-init.sql < /docker-entrypoint-initdb.d/mysql-appdb-init.sql <
          19. 完整Deployment
          20. ​ 通过如上多步调整,MySQL数据库的Deplyment如下所示:


          21. </>复制代码

            1. apiVersion: extensions/v1beta1
            2. kind: Deployment
            3. metadata:
            4. labels:
            5. app: mysql
            6. name: mysql
            7. spec:
            8. replicas: 1
            9. selector:
            10. matchLabels:
            11. app: mysql
            12. template:
            13. metadata:
            14. labels:
            15. app: mysql
            16. spec:
            17. initContainers:
            18. - name: mysql-init
            19. image: busybox
            20. imagePullPolicy: IfNotPresent
            21. env:
            22. - name: MYSQL_TEST_USER_PASSWORD
            23. valueFrom:
            24. secretKeyRef:
            25. name: mysql-user-pwd
            26. key: mysql-test-user-pwd
            27. command:
            28. - sh
            29. - "-c"
            30. - |
            31. set -ex
            32. rm -fr /var/lib/mysql/lost+found
            33. cat > /docker-entrypoint-initdb.d/mysql-testdb-init.sql < /docker-entrypoint-initdb.d/mysql-appdb-init.sql <
            34. 创建此Deployment后,我们有如下组件:

            35. </>复制代码

              1. # kubectl get all,pvc,cm,secret
              2. # MySQL Deployment:
              3. NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
              4. deploy/mysql 1 1 1 1 1m
              5. # RS被Deployment调用,其是自动生成的
              6. NAME DESIRED CURRENT READY AGE
              7. rs/mysql-998977cdd 1 1 1 1m
              8. # Pod:
              9. NAME READY STATUS RESTARTS AGE
              10. po/mysql-998977cdd-v2ks2 1/1 Running 1 1m
              11. # Service:
              12. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
              13. svc/mysql NodePort 172.30.3.200 3306:30006/TCP 8h
              14. # Pvc:
              15. NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
              16. pvc/mysql Bound pvc-fe.. 1Gi ROX glusterfs-raid0 2m
              17. # Configmap:
              18. NAME DATA AGE
              19. cm/mysql-config 1 6h
              20. # Secret:
              21. NAME TYPE DATA AGE
              22. secrets/mysql-user-pwd Opaque 3 1h
            36. 定期自动备份
            37. ​ 考虑到数据安全性,我们定期备份数据库,在K8S集群中,我们可配置CronJob实现自动备份作业。首先,创建一个持久化存储供备份用:

            38. </>复制代码

              1. # kubectl create -f - <
              2. ​ 继而,配置实际的自动化作业任务,如下所示,每天凌晨0点将使用mysqldump备份appdb数据库。

              3. </>复制代码

                1. # kubectl create -f - < /mysql-backup/mysql-`date +"%Y%m%d"`.sql
                2. volumeMounts:
                3. - name: mysql-backup
                4. mountPath: /mysql-backup
                5. restartPolicy: OnFailure
                6. volumes:
                7. - name: mysql-backup
                8. persistentVolumeClaim:
                9. claimName: mysql-backup
                10. EOF
              4. 结束语
              5. ​ 本文揉合K8S多项技术,构建了一个复杂且可做生产使用的范例,当然,此库是单实例数据库,倘若需构建数据库高可用方案,需部署如MySQL HAPXC集群,其中自动作业备份范例仅使用mysqldump备份,在生产环境不是很实用,我们需要考虑使用xtrabackup备份以及mysqlbinlog备份日志。


              6. 参见docker-entrypoint.sh。 ↩

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/27304.html

相关文章

  • K8S集群中一步步构建一个复杂MySQL据库

    摘要:结束语本文揉合多项技术,构建了一个复杂且可做生产使用的范例,当然,此库是单实例数据库,倘若需构建数据库高可用方案,需部署如集群,其中自动作业备份范例仅使用备份,在生产环境不是很实用,我们需要考虑使用备份以及备份日志。 文档说明 ​ 本文面向容器初学者,作者先简单的用MySQL官方镜像搭建一个可运行的单实例数据库,而后考虑生产或现实需求,一步一步完善并揉合K8S多个技术,从而构建一...

    didikee 评论0 收藏0
  • K8S集群中一步步构建一个复杂MySQL据库

    摘要:结束语本文揉合多项技术,构建了一个复杂且可做生产使用的范例,当然,此库是单实例数据库,倘若需构建数据库高可用方案,需部署如集群,其中自动作业备份范例仅使用备份,在生产环境不是很实用,我们需要考虑使用备份以及备份日志。 文档说明 ​ 本文面向容器初学者,作者先简单的用MySQL官方镜像搭建一个可运行的单实例数据库,而后考虑生产或现实需求,一步一步完善并揉合K8S多个技术,从而构建一...

    songze 评论0 收藏0

发表评论

0条评论

YancyYe

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<