当前位置: 首页 > news >正文

在K8S中部署MySQL主从

1 概述

在K8S环境中,配置单个MySQL是非常方便的,但如果需要配置MySQL主从,则比较麻烦。
配置MySQL主从有下面三个特殊的地方:
  • 主库的配置文件和从库的配置文件,也就是需要根据主从的不同使用不同的配置文件。
  • 从库开始的时候,主库可能已经有数据了,需要备份这些数据到从库作为初始数据。
  • 从库启动前,需要连接主库并指定同步文件的名称和从哪个位置开始同步数据,然后启动从库。
如果是手工搭建MySQL主从,上面这些特殊地方手工一个个完成即可。但在K8S环境中,MySQL主从属于有状态的,需要由statefulset来编排,也就是上面那些特殊地方,需要用Pod中的容器来协助完成,才能够纳入到statefulset中进行编排,否则就无法做到自动多一个或者少一个从库。

2 配置

2.1 yaml配置

1、设定namespace
采用了自定义namespace,好处是pod、statefulset、service等的名称不怕重复,这也是推荐的一种实践。下面除了PV对象之外,其它对象都加上此namespace,方便管理,缺点是后面查询对象的命令都需要加上-n mysql-demo03参数指定namespace来查询。所有对象都加上相同的label,方便需要全部查询对象的场景。
# mysql-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:name: mysql-demo03labels:app: mysql

2、主从库的配置文件

主库主要是开启binlog,使得从库可以同步binlog文件来保证数据与主库一致。从库则需要设置只读,不支持写入数据。

# mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: mysqlnamespace: mysql-demo03labels:app: mysql
data:master.cnf: |[mysqld]log-bin slave.cnf: |[mysqld]super-read-only

3、设置MySQL数据库的访问密码

使用Secret类型时,数据需要用Base64编码,可以在Linux命令行中执行命令进行Base64编码:echo -n "123456" | base64

# mysql-secret.yaml
apiVersion: v1
kind: Secret
metadata:name: mysql-secretnamespace: mysql-demo03labels:app: mysql
type: Opaque
data:password: MTIzNDU2

4、开放访问端口

使用NodePort类型的Service,支持从外部访问MySQL,注意在Windows系统需要使用WSL的IP,Linux则可以使用宿主机的IP。

# mysql-service.yaml
apiVersion: v1
kind: Service
metadata:name: mysqlnamespace: mysql-demo03labels:app: mysql
spec:type: NodePortports:- name: mysqlport: 3306nodePort: 31306selector:app: mysql
---
apiVersion: v1
kind: Service
metadata:name: mysql-readnamespace: mysql-demo03labels:app: mysql
spec:ports:- name: mysqlport: 3306selector:app: mysql

5、定义文件目录类型的PV

作为例子,使用宿主机上的目录作为PV最简单。注意Windows系统中需要用WSL里面的的目录,Linux上可以直接使用宿主机上的目录。也可以配置NFS之类的来提供PV。注意storageClassName,需要在下面是statefulset中映射上,否则PVC无法正确绑定PV。volumeClaimTemplates中补充storageClassName的配置,用于匹配PV。

# mysql-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: demo03-mysql-pv01labels:app: mysql
spec:storageClassName: demo03-mysql-pvaccessModes:- ReadWriteOncecapacity:storage: 1GihostPath:path: /mnt/host/d/mysql_demo03/volume-pv01
---
apiVersion: v1
kind: PersistentVolume
metadata:name: demo03-mysql-pv02labels:app: mysql
spec:storageClassName: demo03-mysql-pvaccessModes:- ReadWriteOncecapacity:storage: 1GihostPath:path: /mnt/host/d/mysql_demo03/volume-pv02
---
apiVersion: v1
kind: PersistentVolume
metadata:name: demo03-mysql-pv03labels:app: mysql
spec:storageClassName: demo03-mysql-pvaccessModes:- ReadWriteOncecapacity:storage: 1GihostPath:path: /mnt/host/d/mysql_demo03/volume-pv03

6、编排容器

使用statefulset编排容器,使用两个initContainers,一个通过提取容器的编号来区分主从,从而获取不同的配置;第二个组装启动从库的同步SQL。还提供了一个常规容器xtrabackup来备份数据,备份数据用来初始化从库数据和提供同步初始信息。

# mysql-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:name: mysqlnamespace: mysql-demo03labels:app: mysql
spec:selector:matchLabels:app: mysqlserviceName: mysqlreplicas: 3template:metadata:labels:app: mysqlspec:initContainers:- name: init-mysqlimage: ubuntu:20.04env:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: passwordcommand:- bash- "-c"- |set -ex# statefulset为pod生成hostname,里面包含序号,提取序号来作为server-id,并区分主从(第0个为主、其它为从)[[ $(hostname) =~ -([0-9]+)$ ]] || exit 1ordinal=${BASH_REMATCH[1]}echo [mysqld] > /mnt/conf.d/server-id.cnf# 由于server-id不能为 0,因此给ID加个数来避开它echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf# 如果pod序号为0则为主,其它为从,区分主从获取不同的配置if [[ ${ordinal} -eq 0 ]]; thencp /mnt/config-map/master.cnf /mnt/conf.delsecp /mnt/config-map/slave.cnf /mnt/conf.dfivolumeMounts:- name: confmountPath: /mnt/conf.d- name: config-mapmountPath: /mnt/config-map- name: clone-mysqlimage: ist0ne/xtrabackup:1.0env:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: passwordcommand:- bash- "-c"- |set -ex# 一个新的MySQL需要拷贝已有的数据,如果数据已经存在,就不需要再次拷贝了[[ -d /var/lib/mysql/mysql ]] && exit 0# 从hostname中提取pod序号[[ $(hostname) =~ -([0-9]+)$ ]] || exit 1ordinal=${BASH_REMATCH[1]}# 主MySQL不用拷贝数据[[ $ordinal == 0 ]] && exit 0# 从前一个序号的MySQL中拷贝数据ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysqlxtrabackup --prepare --target-dir=/var/lib/mysqlvolumeMounts:- name: datamountPath: /var/lib/mysqlsubPath: mysql- name: confmountPath: /etc/mysql/conf.dcontainers:- name: mysqlimage: mysql:5.7env:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: passwordports:- name: mysqlcontainerPort: 3306volumeMounts:- name: datamountPath: /var/lib/mysqlsubPath: mysql- name: confmountPath: /etc/mysql/conf.dresources:requests:cpu: 500mmemory: 1GilivenessProbe:exec:command: ["mysqladmin", "ping", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]initialDelaySeconds: 30periodSeconds: 10timeoutSeconds: 5readinessProbe:exec:command: ["mysqladmin", "ping", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]initialDelaySeconds: 5periodSeconds: 2timeoutSeconds: 1- name: xtrabackupimage: ist0ne/xtrabackup:1.0ports:- name: xtrabackupcontainerPort: 3307env:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: passwordcommand:- bash- "-c"- |set -excd /var/lib/mysql# 启动从库前,需要执行"CHANGE MASTER TO" SQL,里面需要提供MASTER_LOG_FILE(binlog文件名)和MASTER_LOG_POS(同步数据位置)# 如果通过xtrabackup备份了数据文件,则可以从备份文件里获取到这两个信息if [[ -f xtrabackup_slave_info ]]; then# xtrabackup_slave_info文件来自于从库,文件里已经包含"CHANGE MASTER TO" SQL,改名字后直接使用即可mv xtrabackup_slave_info change_master_to.sql.inrm -f xtrabackup_binlog_infoelif [[ -f xtrabackup_binlog_info ]]; then# xtrabackup_binlog_info文件来自于主库,需要从中提取MASTER_LOG_FILE和MASTER_LOG_POS并组装"CHANGE MASTER TO" SQL[[ $(cat xtrabackup_binlog_info) =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1rm xtrabackup_binlog_infoecho "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.infiif [[ -f change_master_to.sql.in ]]; then# 等待MySQL容器ready之后才能执行上面组装的SQLecho "Waiting for mysqld to be ready(accepting connections)"until mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "SELECT 1"; do sleep 1; doneecho "Initializing replication from clone position"mv change_master_to.sql.in change_master_to.sql.orig# 执行"CHANGE MASTER TO" SQL,并启动Slave库同步mysql -uroot -p${MYSQL_ROOT_PASSWORD} << EOF$(< change_master_to.sql.orig),MASTER_HOST='mysql-0.mysql.weixnie',MASTER_USER='root',MASTER_PASSWORD='${MYSQL_ROOT_PASSWORD}',MASTER_CONNECT_RETRY=10;START SLAVE;EOFfi# ncat监听3307端口,有新数据则备份exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \"xtrabackup --backup --slave-info --stream=xbstream --user=root --password=${MYSQL_ROOT_PASSWORD}"volumeMounts:- name: datamountPath: /var/lib/mysqlsubPath: mysql- name: confmountPath: /etc/mysql/conf.dvolumes:- name: confemptyDir: {}- name: config-mapconfigMap:name: mysqlvolumeClaimTemplates:- metadata:name: dataspec:accessModes: ["ReadWriteOnce"]resources:requests:storage: 1GistorageClassName: demo03-mysql-pvvolumeMode: Filesystem

通过kubectl apply -f xx.yaml,按顺序执行上面yaml文件即可。

2.2 一些问题

1、容器init-mysql需要使用正确的镜像。

这个容器中用到了bash脚本,需要使用提供bash命令的镜像,比如上例换成了ubuntu:20.04镜像,提供完整的Linux命令,方便测试时可以多一些命令可以使用,缺点是镜像比较大。正式使用时可以选用小一点的镜像。

2、Service需要在Statefulset之前执行

Statefulset中从库需要连接主库,由于Pod本身的IP是不确定的,所以需要Service来提供稳定的连接服务。如果Service后执行,需要重启Statefulset。

3、不能使用127.0.0.1 IP

Statefulset里面有bash脚本中访问MySQL库的时候,如果用了-h 127.0.0.1,带着这个参数实际是访问不了的,在Pod中并不认这个IP,应该使用Service名称访问。

4、配置好PV

没有PV的时候,Pod也启动不起来。需要先配置好PV,最简单的配置PV方式就是使用宿主机的目录,如果是Windows系统,需要注意要把宿主机的目录转为WSL里的目录,上例使用的就是Windows的目录。

2.3 检验

1、使用kubectl get pod -n mysql-demo03查看Pod的状态,观察STATUS字段需要为Running,READY字段里的两个数字要相等,这样Pod才正常运行。

2、使用kubectl exec -it mysql-0 -n mysql-demo03 -- /bin/bash 进入Pod,用mysql -uroot -p命令登录MySQL,在里面能够正常执行SQL命令。主库可查可写,从库只能查不能写。

3、修改statefulset里的replicas字段值,增减从库数量,通过kubectl rollout status sts/mysql 命令查看从库的增减过程。

4、如果遇到问题,则使用kubectl logs pod_name -c container_name -n mysql-demo03来查看具体的日志,根据日志解决问题。

3 小结

使用K8S来部署主从,有点在yaml里写shell脚本的嫌疑,如果不使用Go语言来自定义Operator,就只能先用这种方式了。

http://www.dtcms.com/a/524534.html

相关文章:

  • go strconv包介绍
  • 论文阅读12——基于学习的具有扩散行为的人流量预测方法
  • 对于随机变量x1, …, xn,其和的范数平方的期望不超过n倍各随机变量范数平方的期望之和
  • ARM《3》_学习c和汇编的混合编程
  • 硬件工程师11月实战项目-10G高速数字示波器开发
  • FPGA Debug:Vivado程序综合卡在了Run Synthesis
  • 免费网站建设推广服务什么样的公司愿意做网站
  • 世隆科技:无人船——开启水上智能作业新时代
  • 网站后台模板关联自己做的网站电商网站楼层 设计
  • 【北京迅为】iTOP-4412精英版使用手册-第六十八章 U-boot基础知识
  • 关于函数调用其实是函数指针+传参+解引用的一些思考
  • 奇缦科技珠海网站建设优化网站地图样本
  • 【设计模式】组合模式(Composite)
  • 【论文精读】Matten:融合 Mamba 与 Attention 的视频生成新范式
  • HTB Networked writeup(network-scripts提权)
  • 如何入门python机器学习?金融从业人员如何快速学习Python、机器学习?机器学习、数据科学如何进阶成为大神?
  • 网站开发技术交流中国国家培训网
  • 网站无法做301重定向网站查询域名入口
  • 国产数据库MongoDB兼容性技术分析与实践对比
  • 350做网站深圳零基础网站建设入门到精通视频教程
  • 冒泡排序代码实现详解
  • 金仓多模数据库平替MongoDB的电子证照国产化实践——从2TB数据迁移到1600+并发支撑
  • 【优先级队列(堆)】3.前 K 个⾼频单词 (medium)
  • 苏州建站公司 诚找苏州聚尚网络设计图案用什么软件
  • 数据结构——快速排序
  • IntelliJ IDEA新版下载、安装、创建项目及Maven配置的教程(附安装包等)
  • C++特性详解:extern、缺省参数、函数模板与名字空间
  • VUE+Electron从0开始搭建开发环境
  • MongoDB 平替新方案:金仓多模数据库驱动电子证照国产化落地
  • 项目(一)