1.启动顺序:Master 的Pod 必须先于 Slave 的 Pod 起来; 2.如果某个Pod挂掉了,应该自动重新启动一个Pod,这个新建的Pod应该沿用原来的数据; 3.Master 与 Slave 的配置文件不同,特别是server_id; 4.Master 与 Slave 在服务启动之后还需要执行一些命令,它们也不一样,具体为: 1)Master需要执行授权命令,授权的用户名和密码希望用户自己来配置,而不是写死; 2)Slave需要执行CHANGE MASTER命令,需要知道Master的地址。
解决以上问题,那么项目就可以成功部署,下面让我们来一个个解决:
statefulsetName-N
其中N为编号,从0开始。例如,StatefulSet名称为 mysql
,那么第一个启动的Pod名称必为 mysql-0
。mysql-1
仍然沿用原来的 mysql-1
的数据。这个问题我们可以使用PV和PVC来解决。PodName.ServiceName
。例如,如果Service名称为mysqlsvc,那么master的DNS名称为 mysql-0.mysqlsvc
,这个名称是不会变化的。当Master完成授权工作后,Slave可通过授权帐号查询到binlog文件名及位置信息(注意授权时要给 replication client
权限才可以查询)。有了解决思路,下面开始部署项目。
1、编写MySQL配置文件
[root@master cnf]# cat my.cnf [mysqld] log-bin = binlog server-id = 1 gtid_mode = on enforce_gtid_consistency = 1 log_slave_updates = 1 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
2、编写initContainer执行脚本
[root@master cnf]# cat my.sh #!/bin/bash pod_seq=`hostname | awk -F"-" '{print $2}'` conf=/cnf if [ $pod_seq -eq 0 ];then cp $conf/my.cnf /mysql cp $conf/init.sh /mysql else id=$((pod_seq+1)) sed -ri "/server/c server-id = $id" /mysql/my.cnf fi
3、编写postStart执行脚本
[root@master cnf]# cat init.sh #!/bin/bash pod_seq=`echo $POD_NAME |awk -F"-" '{print $2}'` while : ;do if [ $pod_seq -eq 0 ] ; then mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "show databases" && mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "grant replication slave on *.* to '$REPLIC_USER'@'%' identified by '$REPLIC_PASSWORD' && REPLIC_USER sleep 1 else mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "show databases" && mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "change master to master_host='mysql-0.mysqlsvc',master_user='$REPLIC_USER',master_password='$REPLIC_PASSWORD',master_auto_position=1;" && mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "start slave" && break sleep 1 fi done
4、构建镜像及上传镜像
[root@master cnf]# cat Dockerfile FROM alpine COPY my.cnf my.sh init.sh /cnf/ [root@master cnf]# docker build -t registry.cn-shenzhen.aliyuncs.com/jun-lin/my-cnf:[tag] . [root@master cnf]# docker pull registry.cn-shenzhen.aliyuncs.com/jun-lin/my-cnf:[tag]
编写yaml文件:
vim secret
--- apiVersion: v1 kind: Secret metadata: name: mysql namespace: default type: Opaque data: root_pass: bGVlZG9u # 用base64转码后的字符 rep_user: c2xhdmU= rep_pass: c2xhdmVwYXNz
vim mysql
apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql spec: serviceName: mysqlsvc replicas: 3 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: initContainers: - image: registry.cn-shenzhen.aliyuncs.com/jun-lin/my-cnf:v7 name: cnf command: ["sh","/cnf/my.sh"] volumeMounts: - mountPath: /mysql name: conf-volume containers: - name: mysql image: mysql:5.7 imagePullPolicy: IfNotPresent env: - name: SVC_NAME value: mysqlsvc - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql key: root_pass - name: REPLIC_USER valueFrom: secretKeyRef: name: mysql key: rep_user - name: REPLIC_PASSWORD valueFrom: secretKeyRef: name: mysql key: rep_pass - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name lifecycle: postStart: exec: command: ["sh","/etc/mysql/mysql.conf.d/init.sh"] ports: - containerPort: 3306 name: mysql volumeMounts: - name: sql mountPath: /var/lib/mysql - name: conf-volume mountPath: /etc/mysql/mysql.conf.d volumes: - name: conf-volume nfs: server: 192.168.127.129 path: "/conf" volumeClaimTemplates: - metadata: name: sql spec: storageClassName: mysql #此处为你部署的SC accessModes: - ReadWriteOnce resources: requests: storage: 1Gi --- apiVersion: v1 kind: Service metadata: name: mysqlsvc labels: app: mysql spec: selector: app: mysql clusterIP: None ports: - name: mysql port: 3306
pv
[root@master pv]# cat pv01.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv01 spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: mysql nfs: path: /mysql server: 192.168.127.129
这里使用的nfs挂载(省略)
通过以上文件创建出集群,等一段时间后查看:
[root@master yaml]# kubectl get po NAME READY STATUS RESTARTS AGE mysql-0 1/1 Running 0 68s mysql-1 1/1 Running 0 51s mysql-2 1/1 Running 0 26s
随便连接一台Slave查看主从状态:
[root@master yaml]# kubectl exec -it mysql-1 bash root@mysql-1:/# mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "show slave status\G" mysql: [Warning] Using a password on the command line interface can be insecure. *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: mysql-0.mysqlsvc Master_User: slave Master_Port: 3306 Connect_Retry: 60 Master_Log_File: binlog.000003 Read_Master_Log_Pos: 478 Relay_Log_File: mysql-1-relay-bin.000003 Relay_Log_Pos: 685 Relay_Master_Log_File: binlog.000003 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 478 Relay_Log_Space: 3075591 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1 Master_UUID: 58cd7b75-38f6-11eb-af61-da9f9717a2b4 Master_Info_File: /var/lib/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: 58cd7b75-38f6-11eb-af61-da9f9717a2b4:1-6 Executed_Gtid_Set: 58cd7b75-38f6-11eb-af61-da9f9717a2b4:1-6, 666af852-38f6-11eb-bd33-aeab33df8f07:1-5 Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version:
部署成功