k8s set up mysql master-slave synchronization

1. mysql master image configuration

  first, we need to obtain the dockerfile file from the docker hub official website for subsequent modifications. The address is as follows:
  https://github.com/docker-library/mysql.git
   then copy one copy of the 8.0 folder and name the other 8.0_slave. Enter the 8.0 folder, where there is a Dockerfile Debian file, modified as Dockerfile

mv Dockerfile.debian Dockerfile

  my. Under the config folder CNF is the mysql configuration file. We need to add the following configuration

[mysql]
default-character-set=utf8 #Set the default character set of mysql client

[client]
default-character-set=utf8 #Set the default port used by mysql client when connecting to the server

[mysqld]
server-id = 1   
log-bin = master-bin
log_bin_index =  master-bin.index
max_connections=200 # Maximum connections allowed
max_connect_errors=10 # Number of connection failures allowed. This is to prevent someone from trying to attack the database system from the host
character-set-server=utf8 # The character set used by the server is UTF8 by default
default_authentication_plugin=mysql_native_password  # The "mysql_native_password" plug-in authentication is used by default
binlog_format=mixed
expire_logs_days        = 10         #binlog expiration cleanup time
max_binlog_size         = 100m       #binlog size of each log file
binlog_cache_size       = 4m         #binlog cache size
max_binlog_cache_size   = 512m       #Maximum binlog cache size

Where server id is the id of mysql master library, which must be unique and inconsistent with slave library. Log bin opens binlog and specifies the name of the binlog file.
  as we are located in Dongba District, we need to set the time zone. Add the following commands to the Dockerfile entry point just now
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENTRYPOINT ["docker-entrypoint.sh"]

  finally, we need to modify the docker entry point sh. In docker_ setup_ The following code is added at the end of the DB () function to create a slave user and configure permissions.

	if [ -n "$MYSQL_REPLICATION_USER" ] && [ -n "$MYSQL_REPLICATION_PASSWORD" ]; then
		mysql_note "Creating user $MYSQL_REPLICATION_USER"
		docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_REPLICATION_USER'@'%' IDENTIFIED WITH 'mysql_native_password' BY '$MYSQL_REPLICATION_PASSWORD';"
		docker_process_sql --database=mysql <<<"GRANT REPLICATION SLAVE ON *.* TO '$MYSQL_REPLICATION_USER'@'%';"
		docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES ;"
	fi

2. mysql slave image configuration

  first enter 8.0_slave folder. Similar to the master, there is a Dockerfile Debian file, modified as Dockerfile

mv Dockerfile.debian Dockerfile

  modify my. Under the config folder cnf.

[mysql]
default-character-set=utf8 # Set the default character set of mysql client

[client]
default-character-set=utf8# Set the default port used by mysql client when connecting to the server

[mysqld]
server-id = 10
log-bin = log/slave10-bin
log_bin_index =  log/slave10-bin.index
relay-log = log/slave10-relay-bin 
relay-log-index = log/slave10-relay-bin.index
max_connections=200 # Maximum connections allowed
max_connect_errors=10 # Number of connection failures allowed. This is to prevent someone from trying to attack the database system from the host
character-set-server=utf8 # The character set used by the server is UTF8 by default
default_authentication_plugin=mysql_native_password  # The "mysql_native_password" plug-in authentication is used by default
binlog_format=mixed
expire_logs_days        = 10         #binlog expiration cleanup time
max_binlog_size         = 100m       #binlog size of each log file
binlog_cache_size       = 4m         #binlog cache size
max_binlog_cache_size   = 512m       #Maximum binlog cache size	

The server id is the id of the mysql slave library, which must be unique and inconsistent with the master library just now. I set it to fixed 10 here. When there are multiple slaves, it can be fixed to 10,11,12, and the id of each slave must be inconsistent.
  modify the time zone. Add the following commands to the Dockerfile entry point just now
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENTRYPOINT ["docker-entrypoint.sh"]

  finally, we need to modify the docker entry point sh. In docker_ setup_ The following code is added at the end of the db() function to set the address of the master, the account and password for synchronization, and turn on the slave mode.

	if [ -n "$MYSQL_MASTER_SERVICE_HOST" ] && [ -n "$MYSQL_REPLICATION_USER" ]; then
			mysql_note "Connecting master_host: $MYSQL_MASTER_SERVICE_HOST, which user: $MYSQL_REPLICATION_USER, password: $MYSQL_REPLICATION_PASSWORD"
			docker_process_sql --database=mysql <<<"STOP SLAVE;"
			docker_process_sql --database=mysql <<<"CHANGE MASTER TO master_host='$MYSQL_MASTER_SERVICE_HOST', master_user='$MYSQL_REPLICATION_USER', master_password='$MYSQL_REPLICATION_PASSWORD' ;"
			docker_process_sql --database=mysql <<<"START SLAVE;"
	fi

You can see that there is a variable MySQL in the code we wrote above_ MASTER_ SERVICE_ Host, this phase variable is k8s automatically generated, so the master mysql service must be named MySQL master.

3. Generate docker image

Execute the command in the 8.0 folder to generate the master image

docker build -t mysql_master:v0.1 .

At 8.0_ Execute instructions in the slave folder to generate a slave image

docker build -t mysql_slave:v0.1 .

4. k8s configuration

Create MySQL in your favorite folder_ master. yaml

apiVersion: v1
kind: Namespace
metadata:
  name: database
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-master
  namespace: database
  labels:
    app: mysql-master
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql-master
---
apiVersion: apps/v1                 #Version of apiserver
kind: Deployment                                      #Replica controller deployment, manage pod and RS
metadata:
  namespace: database
  name: mysql-master                                            #The name of the deployment, which is globally unique
spec:
  replicas: 1                                                #Expected number of Pod copies
  selector:
    matchLabels:                                         #Define label of RS
      app: mysql-master                                             #Pod s that meet the target have this tag
  strategy:                                                  #Define upgrade policy
    type: RollingUpdate                               #Rolling upgrade and step-by-step replacement strategy
  template:                                                #Create a copy (instance) of the Pod based on this template
    metadata:
      labels:
        app: mysql-master                                       #Label of Pod copy, corresponding to Selector of RS
    spec:
      containers:                                          #Definition of container in Pod
      - name: mysql                                     #Name of the container
        image: mysql_master:v0.1                         #docker image corresponding to container
        ports:
        - containerPort: 3306                         #Container exposed port number
        env:                                                   #Environmental capacity written into the container
        - name: MYSQL_ROOT_PASSWORD   #Defines a variable for the root password of mysql
          value: "123456"
        - name: MYSQL_REPLICATION_USER   #Defines a variable for the root password of mysql
          value: "rep1ication"
        - name: MYSQL_REPLICATION_PASSWORD   #Defines a variable for the root password of mysql
          value: "123456"

Create mysql_slave.yaml

apiVersion: v1
kind: Service
metadata:
  name: mysql-slave
  namespace: database
  labels:
    app: mysql-slave
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql-slave
---
apiVersion: apps/v1                 #Version of apiserver
kind: Deployment                                      #Replica controller deployment, manage pod and RS
metadata:
  namespace: database
  name: mysql-slave                                            #The name of the deployment, which is globally unique
spec:
  replicas: 1                                                #Expected number of Pod copies
  selector:
    matchLabels:                                         #Define label of RS
      app: mysql-slave                                             #Pod s that meet the target have this tag
  strategy:                                                  #Define upgrade policy
    type: RollingUpdate                               #Rolling upgrade and step-by-step replacement strategy
  template:                                                #Create a copy (instance) of the Pod based on this template
    metadata:
      labels:
        app: mysql-slave                                       #Label of Pod copy, corresponding to Selector of RS
    spec:
      containers:                                          #Definition of container in Pod
      - name: mysql                                     #Name of the container
        image: mysql_slave:v0.1                           #docker image corresponding to container
        ports:
        - containerPort: 3306                         #Container exposed port number
        env:                                                   #Environmental capacity written into the container
        - name: MYSQL_ROOT_PASSWORD   #Defines a variable for the root password of mysql
          value: "123456"
        - name: MYSQL_REPLICATION_USER   #Defines a variable for the root password of mysql
          value: "rep1ication"
        - name: MYSQL_REPLICATION_PASSWORD   #Defines a variable for the root password of mysql
          value: "123456"

Finally, check whether the condition of the pod in k8s is normal. It should be noted that for convenience, I have not set persistent storage for the pod. Persistent storage is required in normal environments. Persistence can be achieved by setting / var/lib/mysql of the external storage container.

kubectl apply -f mysql_master.yaml 
kubectl apply -f mysql_salve.yaml 

5. Inspection and test

(1) Inspection results

Enter the pod corresponding to the slave and enter mysql

mysql -uroot -p
show slave status\G;

If Slave_IO_Running,Slave_ SQL_ The running status is yes, indicating that the master-slave mysql configuration is completed.
If it fails, you need to use the kubectl describe command to view the log of the slave pod. Generally, the most likely problem is that the master mysql sets the slave account. Using commands in mysql

select user,host from mysql.user; //The result should have an account rep1ication
show grants for 'rep1ication'@'%'; 
//The result is grant usage slave on ** To 'rep1ication' @ '%' is an error
//The result is grant replication slave on ** To 'rep1ication' @ '%' is correct

(2) Testing

Enter the pod corresponding to the master and enter mysql

kubectl exec -it mysql-master-pe18a /bin/bash
mysql -uroot -p
create database test; use test; create table test_tb(id int(3),name char(10)); 
insert into test_tb values(001,'ok');
insert into test_tb values(002,'ok');

Then check whether there is data in the pod of the slave

mysql -uroot -p
use test;
select * form test_tb;

6. Image, configuration file download

Image address: there are two in total, one is master and the other is slave
https://registry.hub.docker.com/r/evilskyman/mysql_master
https://registry.hub.docker.com/r/evilskyman/mysql_slave
Dockerfile and yaml files
https://gitee.com/evilskyman/mysql-test

Keywords: Database MySQL Docker Kubernetes

Added by andrewburgess on Thu, 10 Feb 2022 16:19:38 +0200