美文网首页
基于kubernates的mysql主从复制部署

基于kubernates的mysql主从复制部署

作者: do_young | 来源:发表于2018-12-04 10:59 被阅读127次

    背景

    基于高可用或高性能的考虑,我们往往会将mysql进行分布式部署。MYSQL数据库分布式方案很多,我这里介绍一种我所开发的系统中,最常用的部署方式。
    这种方式具体实现的原理如下图所示:


    mysql-master-slave.png

    一般我使用这种方式用于数据库备份,以免数据库的物理文件损坏。或是可以使用从结点为主结点分担一些数据库读操作的负载压力。下面具体给出kubernates的相关配置。

    部署步骤

    制作镜像

    主要是因为默认的mysql的镜像时区不对,所以需要修改一下

    FROM mysql:latest
    MAINTAINER doyoung<11790379@qq.com>
    RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    RUN echo "Asia/Shanghai" >> /etc/timezone
    

    通过命令执行一下上面的Dockerfile:

    docker build -t going/go-nifty-mysql:latest .
    

    这里将新生成的镜像名称改为going/go-nifty-mysql:latest

    部署主结点

    主结点的deployment.yaml文件配置如下:

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: go-nifty-mysql-deployment
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          tier: mysql
      template:
        metadata:
          labels:
            tier: mysql
        spec:
          containers:
          - name: go-nifty-mysql-container
            image: going/go-nifty-mysql:latest
            imagePullPolicy: IfNotPresent
            ports:
            - containerPort: 3306
            env:
            - name: MYSQL_ROOT_PASSWORD
              value: "pssword"
            - name: lower_case_table_names
              value: "1"  #用于orm工具自动创建都为小写的表名
            volumeMounts:
            - mountPath: /var/lib/mysql
              name: mysqldb
            - mountPath: /etc/mysql/mysql.conf.d
              name: mysqlcfg
          volumes:
          - name: mysqldb
            hostPath:
              path: /root/project/xxx/database/data
          - name: mysqlcfg
            hostPath:
              path: /root/project/xxx/database/conf
    

    mysql的主结点是基于going/go-nifty-mysql:latest镜像创建的pod,其中主结点的配置文件及数据库实例文件都是通过mount的方式,映射到宿主机的 /root/project/xxx/database路径下的,所以需要在宿主机上创建 /root/project/xxx/database/data及 /root/project/xxx/database/conf两个子目录,创建完成以后,在/root/project/xxx/database/conf下创建文件mysqld.cnf,文件配置如下:

    [mysql]
    default-character-set = utf8
    
    [mysql.server]
    default-character-set = utf8
    
    [mysqld_safe]
    default-character-set = utf8
    
    [client]
    default-character-set = utf8
    
    [mysqld]
    log-bin=mysql-bin
    binlog-ignore-db=mysql
    server-id=1001
    pid-file        = /var/run/mysqld/mysqld.pid
    socket          = /var/run/mysqld/mysqld.sock
    datadir         = /var/lib/mysql
    character_set_server = utf8
    lower_case_table_names=1
    symbolic-links=0
    sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    

    其中最主要需要注意的配置就是server-id和log-bin两个参数。
    下面将主结点暴露为对外服务,这里的方案是将service定义为nodeType,这样外网的mysql数据库客户端连接数据库进行数据操作,比如导入初始化数据等(这里暂不考虑数据库的自动化,以后有时候再细化这块的内容)。
    所以service.yaml配置文件如下:

    apiVersion: v1
    kind: Service
    metadata:
      name: mysql-service
      namespace: default
    spec:
      type: NodePort
      ports:
      - port: 3306 
        targetPort: 3306
        name: mysql-port
        nodePort: 3306
      selector:
        tier: mysql
    

    将配置文件分别创建pod和service以后,就可以使用数据库的客户端连接数据库了。

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

    部署从结点

    从结点的deployment.yaml配置文件如下:

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: mysql-slave-deployment
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          tier: mysql-slave
      template:
        metadata:
          labels:
            tier: mysql-slave
        spec:
          containers:
          - name: mysql-slave-container
            image: going/go-nifty-mysql:latest
            imagePullPolicy: IfNotPresent
            ports:
            - containerPort: 3306
            env:
            - name: MYSQL_ROOT_PASSWORD
              value: "password"
            - name: lower_case_table_names
              value: "1"  
            volumeMounts:
            - mountPath: /var/lib/mysql
              name: mysqldb
            - mountPath: /etc/mysql/mysql.conf.d
              name: mysqlcfg
          volumes:
          - name: mysqldb
            hostPath:
              path: /root/project/xxx/database-slave/data
          - name: mysqlcfg
            hostPath:
              path: /root/project/xxx/database-slave/conf
    

    从结点pod的定义文件基本与主结点一样,只是从结点的配置及数据映射到了宿主机的 /root/project/xxx/database-slave路径下,从结点的mysqld.cnf文件配置如下:

    [mysql]
    default-character-set = utf8
    
    [mysql.server]
    default-character-set = utf8
    
    [mysqld_safe]
    default-character-set = utf8
    
    [client]
    default-character-set = utf8
    
    [mysqld]
    server-id=5001
    pid-file        = /var/run/mysqld/mysqld.pid
    socket          = /var/run/mysqld/mysqld.sock
    datadir         = /var/lib/mysql
    character_set_server = utf8
    lower_case_table_names=1
    symbolic-links=0
    sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    

    其中的server-id参数值不要与主结点的server-id值重复即可。
    下面是从结点的service.ymal配置文件:

    apiVersion: v1
    kind: Service
    metadata:
      name: mysql-slave-service
      namespace: default
    spec:
      type: NodePort
      ports:
      - port: 3307 
        targetPort: 3306
        name: mysql-slave-port
        nodePort: 3307
      selector:
        tier: mysql-slave
    

    如果从结点只是做备份,并不提供给应用做只读操作的服务的话。从结点的service也可以不用创建。
    完成以上配置以后,就可以创建pod和service了:

    kubectl create -f mysql-slave-deployment.yaml 
    kubectl create -f mysql-slave--service.yaml
    

    配置主结点

    下面的操作是需要进入到主结点的数据库实现中,创建一个只读用户,用于从结点从主结点中读取主结点数据变化的增量二进程文件。具体操作如下:
    通过kubectl get pod 命令找到主结点的pod实例名称:

    kubectl get pod | grep mysql
    mysql-deployment-7cbc7f69f-hf6rq          1/1       Running   0          17h
    

    通过kubectl exec 指令进入到容器中,并使用容器中的mysql客户端,登录到数据库的实例中:

     kubectl exec -it mysql-deployment-7cbc7f69f-hf6rq -- mysql -u root -ppassword
    

    正常登录数据库以后,你回看到熟悉的提示信息:

    mysql: [Warning] Using a password on the command line interface can be insecure.
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 9
    Server version: 5.7.20-log MySQL Community Server (GPL)
    
    Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
    
    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> 
    

    在数据库的命令行下执行以下指令:

    GRANT REPLICATION SLAVE ON *.* to 'reader'@'%' identified by 'readerpwd';
    

    执行完成以后指令以后,继续执行以下指令:

     show master status;
    

    记录下表格中的File列的文件名称后缀信息及Position数字信息,它将在从结点的配置中使用。

    +------------------+----------+--------------+------------------+-------------------+
    | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +------------------+----------+--------------+------------------+-------------------+
    | mysql-bin.000003 |      439 |              | mysql            |                   |
    +------------------+----------+--------------+------------------+-------------------+
    1 row in set (0.00 sec)
    

    到这里主结点就配置完了。

    配置从结点

    下面开始配置从结点,从结点的配置原理为,通过指令使用从结点的数据库实例使用主结点的只读用户从某一个增量文件开始同步主结点的增量数据。具体操作如下:
    通过kubectl get pod 命令找到从结点的pod实例名称:

    kubectl get pod | grep mysql-slave
    mysql-slave-deployment-767f67df94-znkjl   1/1       Running   0          17h
    

    通过kubectl exec 指令进入到容器中,并使用容器中的mysql客户端,登录到数据库的实例中:

     kubectl exec -it mysql-slave-deployment-767f67df94-znkjl -- mysql -u root -ppassword
    

    在命令行中执行以下指令:

    change master to master_host='mysql-service',master_user='reader',master_password='readerpwd',master_log_file='mysql-bin.000003',master_log_pos=439;
    

    其中的master_host参数使用的是主结点service名称,master_log_file和master_log_pos的参数值要与主结点中执行的【show master status】指令显示的值一致。
    再执行

    start slave;
    

    到这里从结点的配置就完成了。

    验证

    在主结点中创建一个数据库:

    create database slavetest;
    

    在从结点中查看一下新创建的数据库是否已经同步过来了:

     show databases;
    

    不出意外的话,你会发现新创建的slavetest数据库,已经同步到了从结点上来了。

    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | slavetest          | #<-------------------很高兴看到你^-^
    | sys                |
    +--------------------+
    5 rows in set (0.00 sec)
    

    相关文章

      网友评论

          本文标题:基于kubernates的mysql主从复制部署

          本文链接:https://www.haomeiwen.com/subject/itdfcqtx.html