基于kubernetes的mysql主从复制部署

背景

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


基于kubernetes的mysql主从复制部署_第1张图片
mysql-master-slave.png

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

部署步骤

制作镜像

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

FROM mysql:latest
MAINTAINER doyoung<[email protected]>
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)

你可能感兴趣的:(基于kubernetes的mysql主从复制部署)