记录日常工作关于系统运维,虚拟化云计算,数据库,网络安全等各方面问题。

2020-11-02 使用K8s部署MySQL 双主集群

机器         角色                              
mysql-0                             master\slave   
mysql-1       slave\master

最近对线上集群做高可用升级,在对比了几个集群策略之后,综合现有资源、复杂度、可用度之后,选择了两个:

  • MySQL双主的互为备份的2节点集群
  • MySQL基于wsrep协议的Galera Cluster的mysql多主集群

初步处于复杂度考虑,选择了方案一。

方案一又有两个版本:

  • 利用keepalived做活跃监督
  • 利用k8s service做负载均衡,达到和活跃监督一样的效果

我们选择最简单的k8s service,先做测试。无论哪一种,首先都要实现双主的互为备份的2节点部署。

一、部署

选择 dockerhub上的MySQL:5.7.32作为基础镜像。依赖于镜像本身的启动命令,做修改,然后部署。

1.Dockerfile

以dockerhub上的mysql为基础镜像

From mysql:5.7.32
COPY my.cnf /etc/mysql/
COPY replication.sh /usr/local/bin/
COPY docker-entrypoint.sh /usr/local/bin/

ENV MYSQL_ROOT_PASSWORD=123456

RUN     chmod 755 /usr/local/bin/replication.sh && \
        chmod a+x /usr/local/bin/replication.sh && \
        chmod 755 /usr/local/bin/docker-entrypoint.sh && \
        chmod a+x /usr/local/bin/docker-entrypoint.sh && \
        chmod 755 /etc/mysql/my.cnf && \
        chmod a+x /etc/mysql/my.cnf && \
        chown -R mysql:mysql /usr/local/bin/replication.sh && \
        chown -R mysql:mysql /usr/sbin/mysqld && \
        chown -R mysql:mysql /etc/mysql/

ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 3306 33060
CMD ["mysqld"]

2.docker-entrypoint.sh

新增一个方法:mysql_replication

mysql_replication() {
    echo 'start to do the mysql replication'
    master_host=''
    if [[ $MY_POD_NAME = 'mysql-0' ]];then
        master_host='mysql-1.mysql.'${MY_POD_NAMESPACE}'.svc.cluster.local'
    else
        master_host='mysql-0.mysql.'${MY_POD_NAMESPACE}'.svc.cluster.local'
    fi
    echo 'add the master and slave roles, the master host is:' $master_host
    replication_user=${MYSQL_REPLICATION_USER:-replication}
    replication_password=${MYSQL_REPLICATION_PASSWORD:-replication_password}
    echo 'the replication user is: '$replication_user ', pass is: '$replication_password
    docker_process_sql --database=mysql <<-EOSQL
            CREATE USER '$replication_user'@'%' IDENTIFIED BY '$replication_password' ;
            GRANT REPLICATION SLAVE ON *.* TO '$replication_user'@'%' IDENTIFIED BY '$replication_password' ;
            FLUSH PRIVILEGES ;
        EOSQL
        
    echo 'created the replication user.'
    
    echo 'start to register to master: ' $master_host
    master_bin_fetch=`
    docker_process_sql --database=mysql <<-EOSQL
            show master status;
        EOSQL
    `
    echo 'fetch the master status.'
    title='File Position Binlog_Do_DB Binlog_Ignore_DB Executed_Gtid_Set'
    title_length=${#title}
    master_bin_info=${master_bin_fetch: $title_length+1}
    echo 'master bin info is: '$master_bin_info
    bin_name='mysql-bin.000002'
    bin_length=${#bin_name}
    bin_file==${master_bin_info: 0 :$bin_length+1}
    position_number=${master_bin_info: $bin_length+1}
    echo 'the master bin file is: '$bin_file ', the position number is: '$position_number
   #从本地文件读取最新的BIN_FILE,不过现在没有用了,作废了
   bin_file=`ls /var/log/mysql | grep mysql-bin.0 | sort -n | tail -1`
    echo 'the master bin file is: '$bin_file ', the position number is set to 0'
   #不设置MASTER_BIN_FILE和MASTER_LOG_POSITION,去除了master pod的区别设置,依赖MySQL自己去发现
    docker_process_sql --database=mysql <<-EOSQL
            STOP SLAVE;
            RESET SLAVE; 
            CHANGE MASTER TO master_host='$master_host', master_user='$replication_user', master_password='$replication_password';
            CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE = ('mysql.%');
            START SLAVE;
        EOSQL

3.my.cnf

这里有一个报错:

2020-11-02T07:35:58.108646Z 2 [ERROR] Slave SQL for channel '': Error 'Operation CREATE USER failed for 'replication'@'%'' on query. Default database: 'mysql'. Query: 'CREATE USER 'replication'@'%' IDENTIFIED WITH 'mysql_native_password' AS '*1A629BF5797BF6AE523D06B26B94561098D18F4C'', Error_code: 1396
2020-11-02T07:35:58.108692Z 2 [Warning] Slave: Operation CREATE USER failed for 'replication'@'%' Error_code: 1396
2020-11-02T07:35:58.108701Z 2 [ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'mysql-bin.000002' position 3071516.

是因为主从复制还带有master、slave中的User表,我们新增了用户,在log bin中写有日志,两个MySQL已启动就去同步log bin,造成原有用户已存在,同步失败的错误。

解决这个错误,就要忽略User表的变化,修改my.cnf中的replicate-ignore-db
或者修改REPLICATE_WILD_IGNORE_TABLE
这个还需要调研

# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

#
# The MySQL  Server configuration file.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

[mysqld]
#这里的ID只能是纯数子,多么痛的领悟
server-id=<%id%>
log-bin=/var/log/mysql/mysql-bin.log
replicate-ignore-db = mysql
log_bin_index       = /var/log/mysql/mysql-bin.log.index
relay_log           = /var/log/mysql/mysql-relay-bin
relay_log_index     = /var/log/mysql/mysql-relay-bin.index
#log-error=/usr/local/mysql/log/error.log
#log=/usr/local/mysql/log/mysql.log
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
#log-error      = /var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address   = 127.0.0.1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
sql_mode="IGNORE_SPACE,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

4.mysql.yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  replicas: 2
  updateStrategy:
    type: RollingUpdate
  serviceName: "mysql"
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeSelector:
        mysql: "true"
      securityContext:
        runAsUser: 0
      containers:
        - name: mysql
          image: test/mysql:mysql1
          env:
            - name: MY_POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: MY_POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
          imagePullPolicy: Never
          ports:
            - containerPort: 3306

---
kind: Service
apiVersion: v1
metadata:
  name: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql

二、测试

分别登陆到两个MySQL,使用

show slave status\G;

创建新的数据库

create database test;

观察新数据库有没有同步到另一个MySQL上面。



转载请标明出处【2020-11-02 使用K8s部署MySQL 双主集群】。

《www.micoder.cc》 虚拟化云计算,系统运维,安全技术服务.

网站已经关闭评论