文章目录
- 一、k8s中实现mysql主备
- 1.1 环境信息
- 1.2 部署nfs-provisioner
- 1.2.1 安装nfs
- 1.2.2 部署nfs-provisioner
- 1.3 安装mysql
- 1.4 备库上查看是否同步
一、k8s中实现mysql主备
1.1 环境信息
机器 | 操作系统 | ip | mysql版本 | k8s版本 | storageClass |
---|---|---|---|---|---|
master1 | CentOS7.8 | 192.168.0.20 | mysql5.7.42 | 1.27.1 | nfs |
node1 | CentOS7.8 | 192.168.0.21 | mysql5.7.42 | 1.27.1 | nfs |
1.2 部署nfs-provisioner
说明:
使用statefulSet部署双机MySQL,所以需要提供storageClass,这里使用nfs-provisioner。
1.2.1 安装nfs
这里nfs安装在node1节点上
mkdir /mnt/nfs && sh nfs_install.sh /mnt/nfs 192.168.0.0/24
nfs_install.sh
#!/bin/bash### How to install it? ###
### 安装nfs-server,需要两个参数:1、挂载点 2、允许访问nfs-server的网段 ###### How to use it? ###
### Client节点`yum -y install nfs-utils rpcbind`,然后挂载nfs-server目录到本地 ###
### 如:echo "192.168.0.20:/mnt/data01 /mnt/data01 nfs defaults 0 0" >> /etc/fstab && mount -a ###mount_point=$1
subnet=$2function nfs_server() {systemctl stop firewalldsystemctl disable firewalldsetenforce 0sed -i 's/^SELINUX.*/SELINUX\=disabled/' /etc/selinux/configyum -y install nfs-utils rpcbindmkdir -p $mount_pointecho "$mount_point ${subnet}(rw,sync,no_root_squash)" >> /etc/exportssystemctl start rpcbind && systemctl enable rpcbindsystemctl restart nfs-server && systemctl enable nfs-serverchown -R nfsnobody:nfsnobody $mount_point
}function usage() {
echo "Require 2 argument: [mount_point] [subnet]
eg: sh $0 /mnt/data01 192.168.10.0/24"
}declare -i arg_nums
arg_nums=$#
if [ $arg_nums -eq 2 ];thennfs_server
elseusageexit 1
fi
1.2.2 部署nfs-provisioner
master1节点上执行 kubectl create namespace devops && kubectl apply -f nfs-provisioner.yaml
nfs-provisioner.yaml
apiVersion: v1
kind: ServiceAccount
metadata:name: nfs-provisionernamespace: devops
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:name: nfs-provisioner-runner
rules:
- apiGroups: [""]resources: ["persistentvolumes"]verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]resources: ["persistentvolumeclaims"]verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]resources: ["storageclasses"]verbs: ["get", "list", "watch"]
- apiGroups: [""]resources: ["events"]verbs: ["create", "update", "patch"]
- apiGroups: [""]resources: ["services", "endpoints"]verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: run-nfs-provisioner
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: nfs-provisioner-runner
subjects:
- kind: ServiceAccountname: nfs-provisionernamespace: devops
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:name: leader-locking-nfs-provisionernamespace: devops
rules:
- apiGroups: [""]resources: ["endpoints"]verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:name: leader-locking-nfs-provisionernamespace: devops
roleRef:apiGroup: rbac.authorization.k8s.iokind: Rolename: leader-locking-nfs-provisioner
subjects:
- kind: ServiceAccountname: nfs-provisionernamespace: devops
---
apiVersion: apps/v1
kind: Deployment
metadata:name: nfs-provisionernamespace: devops
spec:selector:matchLabels:app: nfs-provisionerreplicas: 1strategy:type: Recreatetemplate:metadata:labels:app: nfs-provisionerspec:serviceAccountName: nfs-provisionercontainers:- name: nfs-provisionerimage: docker.io/gmoney23/nfs-client-provisioner:latestvolumeMounts:- name: nfs-client-rootmountPath: /persistentvolumesenv:- name: PROVISIONER_NAMEvalue: example.com/nfs- name: NFS_SERVERvalue: 192.168.0.21- name: NFS_PATHvalue: /mnt/nfsvolumes:- name: nfs-client-rootnfs:server: 192.168.0.21path: /mnt/nfs
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:name: nfs
provisioner: example.com/nfs
#reclaimPolicy: Retain
1.3 安装mysql
kubectl apply -f deploy.yaml
deploy.yaml
apiVersion: v1
kind: Namespace
metadata:name: mysqllabels:app: mysql---
apiVersion: v1
kind: ConfigMap
metadata:name: mysqlnamespace: mysqllabels:app: mysql
data:master.cnf: |[client]default-character-set=utf8mb4[mysql]default-character-set=utf8mb4[mysqld]max_connections=2000default-time_zone='+8:00'character-set-server=utf8mb4collation-server=utf8mb4_unicode_ciinnodb_buffer_pool_size=536870912datadir=/var/lib/mysqlpid-file=/var/run/mysqld/mysqld.pidlog-error=/var/lib/mysql/error.loglog-bin=mysqllogskip-name-resolvelower-case-table-names=1log_bin_trust_function_creators=1slave.cnf: |[client]default-character-set=utf8mb4[mysql]default-character-set=utf8mb4[mysqld]max_connections=2000default-time_zone='+8:00'character-set-server=utf8mb4collation-server=utf8mb4_unicode_ciinnodb_buffer_pool_size=536870912datadir=/var/lib/mysqlpid-file=/var/run/mysqld/mysqld.pidlog-error=/var/lib/mysql/error.logsuper-read-onlyskip-name-resolvelog-bin=mysql-binlower-case-table-names=1log_bin_trust_function_creators=1---
apiVersion: v1
kind: Secret
metadata:name: mysql-secretnamespace: mysqllabels:app: mysql
type: Opaque
data:password: TnNiZzExMTEqQCE= # Nsbg1111*@!replicationUser: Y29weQ== #copyreplicationPassword: TnNiZzExMTEqQCE= #Nsbg1111*@!---
apiVersion: v1
kind: Service
metadata:name: mysqlnamespace: mysqllabels:app: mysql
spec:selector:app: mysqlclusterIP: Noneports:- name: mysqlport: 3306---
apiVersion: apps/v1
kind: StatefulSet
metadata:name: mysqlnamespace: mysqllabels:app: mysql
spec:selector:matchLabels:app: mysqlserviceName: mysqlreplicas: 2template:metadata:labels:app: mysqlspec:initContainers:- name: init-mysqlimage: docker.io/library/mysql:5.7.42command: - bash- "-c"- |set -ex#从pod的hostname中通过正则获取序号,如果没有截取到就退出程序ordinal=`cat /etc/hostname | awk -F"-" '{print $2}'` || exit 1#将serverId输入到对应的配置文件中,路径可以随意(与之后的对应上就行),但是文件名不能换echo [mysqld] > /etc/mysql/conf.d/server-id.cnf# 由于server-id不能为0,因此给ID加100来避开它server_id=$((100 + $ordinal))echo "server-id=$server_id" >> /etc/mysql/conf.d/server-id.cnfif [[ ${ordinal} -eq 0 ]]; then# 如果Pod的序号为0,说明它是Master节点,从ConfigMap里把Master的配置文件拷贝到/mnt/conf.d目录下cp /mnt/config-map/master.cnf /etc/mysql/conf.delse# 否则,拷贝ConfigMap里的Slave的配置文件cp /mnt/config-map/slave.cnf /etc/mysql/conf.dfiecho "ending..."env:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: password- name: MYSQL_REPLICATION_USERvalueFrom:secretKeyRef:name: mysql-secretkey: replicationUser- name: MYSQL_REPLICATION_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: replicationPasswordvolumeMounts:- name: confmountPath: /etc/mysql/conf.d- name: config-mapmountPath: /mnt/config-mapcontainers:- name: mysqlimage: docker.io/library/mysql:5.7.42lifecycle:postStart:exec:command:- bash- "-c"- |set -excd /var/lib/mysql#查看是否存在名为mysqlInitOk的文件,我们自己生产的标识文件,防止重复初始化集群if [ ! -f mysqlInitOk ]; thenecho "Waiting for mysqld to be ready(accepting connections)"#执行一条mysql的命令,查看mysql是否初始化完毕,如果没有就反复执行直到可以运行#until mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "use mysql;SELECT 1;"; do sleep 1; donesleep 5secho "Initialize ready"#判断是master还是slavepod_seq=`cat /etc/hostname | awk -F"-" '{print $2}'`if [ $pod_seq -eq 0 ];then#创建主从账户mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "create user '${MYSQL_REPLICATION_USER}'@'%' identified by '${MYSQL_REPLICATION_PASSWORD}';"#设置权限mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "grant replication slave on *.* to '${MYSQL_REPLICATION_USER}'@'%' with grant option;"#刷新配置mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "flush privileges;"#初始化mastermysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "reset master;"else#设置slave连接的master#mysql-0.mysql.mysql的由来{pod-name}.{service-name}.{namespace}mysql -e \"change master to master_host='mysql-0.mysql.mysql',master_port=3306, \master_user='${MYSQL_REPLICATION_USER}',master_password='${MYSQL_REPLICATION_PASSWORD}', \master_log_file='mysqllog.000001',master_log_pos=154;"#重置slavemysql -e "reset slave;"#开始同步mysql -e "start slave;"#改成只读模式mysql -e "set global read_only=1;"fi#运行完毕创建标识文件,防止重复初始化集群touch mysqlInitOkfienv:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: password- name: MYSQL_REPLICATION_USERvalueFrom:secretKeyRef:name: mysql-secretkey: replicationUser- name: MYSQL_REPLICATION_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: replicationPasswordports:- name: mysqlcontainerPort: 3306volumeMounts:- name: datamountPath: /var/lib/mysql- name: confmountPath: /etc/mysql/conf.d- name: run-mysqlmountPath: /var/run/mysqlresources:requests:cpu: 500mmemory: 2Gi#设置存活探针livenessProbe:exec:command: ["mysqladmin", "ping", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]initialDelaySeconds: 30periodSeconds: 10timeoutSeconds: 5#设置就绪探针readinessProbe:exec:command: ["mysqladmin", "ping", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]initialDelaySeconds: 5periodSeconds: 10timeoutSeconds: 1volumes:- name: config-mapconfigMap:name: mysqlvolumeClaimTemplates:- metadata:name: dataspec:accessModes:- ReadWriteOncestorageClassName: nfsresources:requests:storage: 5Gi- metadata: name: confspec:accessModes:- ReadWriteOncestorageClassName: nfsresources:requests:storage: 100Mi- metadata: name: run-mysqlspec:accessModes:- ReadWriteOncestorageClassName: nfsresources:requests:storage: 100Mi