利用文件存储NAS搭建K8S集群的Mysql主从复制+读写分离
2021/4/24 19:28:16
本文主要是介绍利用文件存储NAS搭建K8S集群的Mysql主从复制+读写分离,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
本文介绍如何利用阿里云文件存储NAS替代K8S原生NFS系统,从而实现存储系统脱离于集群之外的可弹性扩展,高可用,高性能 的部署
搭建的结构
- 一个 master 节点和多个从 master 上异步复制数据的 slave 节点组成,即一主多从复制模型。其中,master 节点可用来处理用户的读写请求,slave 节点只能用来处理用户的读请求。
- 通过statefulset部署的mysql能通过无头服务的域名发现彼此,实现主从表同步。
- 我们除了要实现这个之外,还需要将mysql的数据存储到nas文件存储系统当中
- 将主从表的配置放在configMap中
- 通过内网的负载均衡,将只读查询通过轮询或其他规则的请求打在从表一二之上。而读写请求则可以直接访问主表。
搭建思路
-
申请阿里云NAS文件系统,使用NAS存储系统;
-
创建Storage存储类;
-
创建configMap配置字典;
-
部署headless无头服务;
-
部署statefulset应用;
-
查看状态;
-
部署对外只读服务 Read-Only;
-
部署对外读写服务 Read-Write
下面我们开始一步步开始搭建部署
具体步骤
-
创建使用NAS存储系统
- 创建nas文件系统
这里其实推荐极速型,更适用于读写频繁的数据库,因为它低时延,大概只有3ms左右
-
挂载使用,我这里只演示通用型的
挂载点:0c28c4801a-l***5.cn-hangzhou.nas.aliyuncs.com
-
在linux上挂载使用,方便管理
-
#如果您使用CentOS、Redhat、Aliyun Linux操作系统,请执行以下命令 sudo yum install nfs-utils #增加同时发起的NFS请求的数量。 #请执行以下命令,将同时发起的NFS请求数量修改为128 sudo echo "options sunrpc tcp_slot_table_entries=128" >> /etc/modprobe.d/sunrpc.conf sudo echo "options sunrpc tcp_max_slot_table_entries=128" >> /etc/modprobe.d/sunrpc.conf 查看 mount -l 查看当前文件系统的容量信息 df -h
-
下面开始把NAS挂载到集群内
创建StorageClass存储类
先创建一个命名空间为mysql,这里不详细演示;
这里创建的sc能够动态帮我们创建使用存储类的持久化存储卷声明(PVC),然后存储持久化声明通知系统它需要一个使用存储类创建的持久化存储卷(PV),它会自动帮我们在挂载NAS系统中去寻找一块可用的空间并进行绑定
kind :StorageClass
name:data
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: data mountOptions: - nolock,tcp,noresvport - vers=3 parameters: server: "2b474***-cxc20.cn-shenzhen.nas.aliyuncs.com:/nasroot1/" driver: flexvolume provisioner: alicloud/nas reclaimPolicy: Delete
官方文档链接:https://help.aliyun.com/document_detail/27518.html
创建configMap配置字典
kind :ConfigMap
创建mysql的配置项
apiVersion: v1 kind: ConfigMap metadata: name: mysql labels: app: mysql data: master.cnf: | # Apply this config only on the master. [mysqld] log-bin slave.cnf: | # Apply this config only on slaves. [mysqld] super-read-only
创建mysql的账号密码配置
apiVersion: v1 kind: ConfigMap metadata: name: mconfig labels: app: mconfig data: passwd.cnf: | [mysql] user=root password=123456 [mysqladmin] user=root password=123456
部署headless无头服务
kind: Service
clusterIP: None
apiVersion: v1 kind: Service metadata: name: mysql-headless labels: app: mysql spec: ports: - name: mysql port: 3306 clusterIP: None selector: app: mysql
#服务名称 + 命名空间 + 集群域名+@coredns的IP地址
mysql-master-svc.mysql.svc.cluster.local @10.27.0.80
部署statefulset应用
具体请参考:国际渣男的文章:https://blog.csdn.net/qq_38900565/article/details/114832445
apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql-ss spec: selector: matchLabels: app: mysql serviceName: mysql-headless replicas: 3 template: metadata: labels: app: mysql spec: initContainers: - name: init-mysql image: mysql:5.7 imagePullPolicy: IfNotPresent command: - bash - "-c" - | set ex # 从hostname中获取索引,比如(mysql-1)会获取(1) [[ `hostname` =~ -([0-9]+)$ ]] || exit 1 ordinal=${BASH_REMATCH[1]} echo [mysqld] > /mnt/conf.d/server-id.cnf # 为了不让server-id=0而增加偏移量 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf # 拷贝对应的文件到/mnt/conf.d/文件夹中 if [[ $ordinal -eq 0 ]]; then cp /mnt/config-map/master.cnf /mnt/conf.d/ else cp /mnt/config-map/slave.cnf /mnt/conf.d/ fi volumeMounts: - name: conf mountPath: /mnt/conf.d - name: config-map mountPath: /mnt/config-map - name: clone-mysql image: ist0ne/xtrabackup imagePullPolicy: IfNotPresent command: - bash - "-c" - | set -ex # 整体意思: # 1.如果是主mysql中的xtrabackup,就不需要克隆自己了,直接退出 # 2.如果是从mysql中的xtrabackup,先判断是否是第一次创建,因为第二次重启本地就有数据库,无需克隆。若是第一次创建(通过/var/lib/mysql/mysql文件是否存在判断),就需要克隆数据库到本地。 # 如果有数据不必克隆数据,直接退出() [[ -d /var/lib/mysql/mysql ]] && exit 0 # 如果是master数据也不必克隆 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1 ordinal=${BASH_REMATCH[1]} [[ $ordinal -eq 0 ]] && exit 0 # 从序列号比自己小一的数据库克隆数据,比如mysql-2会从mysql-1处克隆数据 ncat --recv-only mysql-ss-$(($ordinal-1)).mysql-headless 3307 | xbstream -x -C /var/lib/mysql # 比较数据,登录 xtrabackup --user=root --password=123456 --prepare --target-dir=/var/lib/mysql volumeMounts: - name: data mountPath: /var/lib/mysql subPath: mysql - name: conf mountPath: /etc/mysql/conf.d containers: - name: mysql image: mysql:5.7 imagePullPolicy: IfNotPresent args: ["--default-authentication-plugin=mysql_native_password"] env: - name: MYSQL_ROOT_PASSWORD value: "123456" ports: - name: mysql containerPort: 3306 volumeMounts: - name: mconfig mountPath: /var/passwd.cnf subPath: var/passwd.cnf - name: data mountPath: /var/lib/mysql subPath: mysql - name: conf mountPath: /etc/mysql/conf.d resources: requests: cpu: 50m memory: 50Mi livenessProbe: exec: command: ["mysqladmin", "--defaults-extra-file=/var/passwd.cnf", "ping"] initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 5 readinessProbe: exec: # Check we can execute queries over TCP (skip-networking is off). command: ["mysql", "--defaults-extra-file=/var/passwd.cnf","-h", "127.0.0.1", "-e", "SELECT 1"] initialDelaySeconds: 5 periodSeconds: 2 timeoutSeconds: 1 - name: xtrabackup image: ist0ne/xtrabackup imagePullPolicy: IfNotPresent ports: - name: xtrabackup containerPort: 3307 command: - bash - "-c" - | set -ex # 确定binlog 克隆数据位置(如果binlog存在的话). cd /var/lib/mysql # 如果存在该文件,则该xrabackup是从现有的从节点克隆出来的。 if [[ -s xtrabackup_slave_info ]]; then mv xtrabackup_slave_info change_master_to.sql.in rm -f xtrabackup_binlog_info elif [[ -f xtrabackup_binlog_info ]]; then [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1 rm xtrabackup_binlog_info echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\ MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in fi # Check if we need to complete a clone by starting replication. if [[ -f change_master_to.sql.in ]]; then echo "Waiting for mysqld to be ready (accepting connections)" until mysql -h 127.0.0.1 -p123456 -e "SELECT 1"; do sleep 1; done echo "Initializing replication from clone position" mv change_master_to.sql.in change_master_to.sql.orig mysql -h 127.0.0.1 -p123456 <<EOF $(<change_master_to.sql.orig), MASTER_HOST='mysql-ss-0.mysql-headless', MASTER_USER='root', MASTER_PASSWORD='123456', MASTER_CONNECT_RETRY=10; START SLAVE; EOF fi exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \ "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=123456" volumeMounts: - name: data mountPath: /var/lib/mysql subPath: mysql - name: conf mountPath: /etc/mysql/conf.d resources: requests: cpu: 10m memory: 10Mi volumes: - name: mconfig configMap: name: mconfig items: - key: passwd.cnf path: var/passwd.cnf - name: conf emptyDir: {} - name: config-map configMap: name: mysql volumeClaimTemplates: - metadata: name: data spec: accessModes: - ReadWriteOnce storageClassName: data resources: requests: storage: 2Gi
查看状态
测试看看
kubectl get pods -n mysql -o wide kubectl exec -it mysql-ss-0 -n mysql -c mysql /bin/bash
分别进行在主数据库中创建表,插入数据,在从表1中查询,在从表2中查询
mysql-master创建一个staffsde表
在mysql-slaver-1中也能查看得到
这样mysql就部署好了,我们还需要讲应用暴露进行测试
部署对外只读服务(Only-Read)
这里只读服务可以主从三个表都可以使用,两种方法
kind:NodePort
nodeport 方式部署,将mysql以节点端口方式向外暴露,在本地进行只读连接测试(使用集群任意节点IP:nodePort进行连接)
apiVersion: v1 kind: Service metadata: name: mysql-Read labels: app: mysql spec: ports: - name: mysql port: 3306 targetPort: 3306 nodePort: 30036 type: NodePort selector: app: mysql
kind: LoadBalancer
LoadBalancer负载均衡方式将mysql,暴露
apiVersion: v1 kind: Service metadata: name: mysql namespace: mysql spec: ports: - port: 80 protocol: 30036 targetPort: 3306 selector: run: nginx type: LoadBalancer
在navicat中连接mysql进行测试,尝试插入数据,显示只读,部署完成
部署对外读写服务(Read-Write)
这里读写服务只允许主表能够使用,通过标签选择:statefulset.kubernetes.io/pod-name: mysql-ss-0
kind:NodePort
apiVersion: v1 kind: Service metadata: name: mysql-Read labels: app: mysql spec: ports: - name: mysql port: 3306 targetPort: 3306 nodePort: 30036 type: NodePort selector: statefulset.kubernetes.io/pod-name: mysql-ss-0
kind: LoadBalancer
LoadBalancer负载均衡方式将mysql,暴露
apiVersion: v1 kind: Service metadata: name: mysql namespace: mysql spec: ports: - port: 80 protocol: 30036 targetPort: 3306 selector: statefulset.kubernetes.io/pod-name: mysql-ss-0 type: LoadBalancer
此时可以通过读写连接测试(使用集群任意节点IP:nodePort进行连接)
至此,部署完成啦;
让我们现在通过集群外的主机看看nas挂载的数据变成什么样吧
创建的staffs表可以看到是在存储卷内的。至此,部署完成,哈哈
这篇关于利用文件存储NAS搭建K8S集群的Mysql主从复制+读写分离的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-25MySQL报错Duplicate entry '0' for key 'PRIMARY'
- 2024-05-29阿里 Canal 实时同步 MySQL 增量数据至 ClickHouse 数据库
- 2024-05-24在Linux下管理MySQL的大小写敏感性
- 2024-04-26MySQL查出时间比实际晚8小时的解决方案
- 2024-04-01JPA不识别MySQL的枚举类型
- 2024-03-30mysql数据库表卡死解决方法
- 2024-03-15MySQL多数据源笔记5-ShardingJDBC实战
- 2024-03-11natural join mysql
- 2024-03-11关于VS2017,VS2015 中利用 EF使用Mysql 不显示数据源问题解决方案
- 2024-02-26mysql 阿里云xb后缀备份文件恢复-icode9专业技术文章分享