《k8s搭建一主三从的mysql8集群---无坑-CSDN博客》通过搭建一主三从,我们能理解到主节点只有1个,那么承担增删改主要还是主节点,如果你在从节点上去操作增删改操作,数据不会同步到其他节点。本章我们将实现多主(双主)集群。实现在多个节点上操作增删改,能同步其他节点。
一,环境准备
1.1 k8s集群服务器
|----------------|--------|-----------|-----------|---------|---------|
| ip | 角色 | 系统 | 主机名 | cpu | mem |
| 192.168.40.129 | master | centos7.9 | k8smaster | 4 | 8 |
| 192.168.40.130 | node1 | centos7.9 | k8snode1 | 4 | 8 |
| 192.168.40.131 | node2 | centos7.9 | k8snode2 | 4 | 8 |
| 192.168.40.132 | node3 | centos7.9 | k8snode3 | 4 | 8 |
k8s集群操作请参考《K8s安装部署(v1.28)--超详细(cri-docker作为运行时)-CSDN博客》
1.2 nfs服务器器
|----------------|--------|-----------|-----------|---------|---------|-----------------------|
| ip | 角色 | 系统 | 主机名 | cpu | mem | 用图 |
| 192.168.40.129 | master | centos7.9 | k8smaster | 4 | 8 | k8s主服务器 兼 nfs服务器 |
| 192.168.40.130 | node1 | centos7.9 | k8snode1 | 4 | 8 | k8s的工作节点 需要装nfs软件 |
| 192.168.40.131 | node2 | centos7.9 | k8snode2 | 4 | 8 | k8s的工作节点 需要装nfs软件 |
| 192.168.40.132 | node3 | centos7.9 | k8snode3 | 4 | 8 | k8s的工作节点 需要装nfs软件 |
二,安装nfs服务
2.1 安装(所有节点)
因为需要在三个工作节点上连接nfs,所以工作节点上也要安装
bash
yum install -y nfs-utils
2.2 暴露nfs目录(只暴露nfs主服务器)
要安装四台服务器。
直接在nfs服务器(k8s-master:192.168.40.129)当中创建这三个目录并写入 /etc/exports 文件夹中(创建的目录可以修改):
bash
#创建nfs目录
mkdir -p /data/nfs/{mysql-master-01,mysql-master-02}
bash
vi /etc/exports
#添加
/data/nfs/mysql-master-01 *(rw,sync,no_root_squash)
/data/nfs/mysql-master-02 *(rw,sync,no_root_squash)
如果目录不为空,需要清空
bash
rm -rf /data/nfs/mysql-master-01/*
rm -rf /data/nfs/mysql-master-02/*
2.3 开启nfs服务器
直接在主服务器(192.168.40.129)上启动nfs服务器。
bash
systemctl enable --now nfs-server
2.4 测试nfs服务
我们可以通过这行命令来检查目录是否暴露成功: 注意修改为自己的nfs服务器地址
bash
showmount -e 192.168.40.129
三,搭建MySql集群
3.1 创建命名空间
创建一个命名空间来部署MySQL集群,当然你也可以使用默认的Default命名空间。这里就用 mysql-cluster 命名空间来搭建集群了,首先我们将这个命名空间创建出来:
创建yaml
bash
kubectl create namespace mysql-cluster --dry-run=client -o yaml
bash
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: null
name: mysql-cluster
spec: {}
status: {}
将上面内容 保存到mysql-ns.yaml中
执行命令
bash
kubectl apply -f mysql-ns.yaml
查看名称空间
bash
kubectl get ns
3.2 创建MySQL密码的Secret
创建一个存储了MySQL密码的Secret,直接使用这行命令生成这个Secret的资源清单文件:
注意修改root的密码和命名空间,我的root密码设置为的是123456
bash
kubectl create secret generic mysql-password --namespace=mysql-cluster --from-literal=mysql_root_password=123456 --dry-run=client -o=yaml
bash
apiVersion: v1
data:
mysql_root_password: MTIzNDU2
kind: Secret
metadata:
creationTimestamp: null
name: mysql-password
namespace: mysql-cluster
将上述yaml内容保存到 mysql-secret.yaml
bash
kubectl apply -f mysql-secret.yaml
查看创建的密码
bash
kubectl get secret -n mysql-cluster
3.3 编写MySQL双主节点yaml
3.3.1 主节点1
mysql-master-1.yaml 内容如下
bash
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-master-01-nfs-pv
namespace: mysql-cluster
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 192.168.40.129
path: /data/nfs/mysql-master-01
storageClassName: "nfs"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-master-01-nfs-pvc
namespace: mysql-cluster
spec:
accessModes:
- ReadWriteMany
storageClassName: "nfs"
resources:
requests:
storage: 1Gi
volumeName: mysql-master-01-nfs-pv
---
apiVersion: v1
kind: Service
metadata:
name: mysql-master-svc-01
namespace: mysql-cluster
labels:
app: mysql-master
spec:
ports:
- port: 3306
name: mysql
targetPort: 3306
nodePort: 3306
selector:
app: mysql-master
type: NodePort
sessionAffinity: ClientIP
---
apiVersion: v1
data:
my.cnf: |
[mysqld]
server-id = 1
# 开启gtid
gtid_mode = ON
enforce_gtid_consistency = 1
# 设置自增ID初始值为2,每次自增量为2。即都是偶数2,4,6,8,...
auto_increment_offset = 2
auto_increment_increment = 2
# 开启bin_log(默认是开启的,直接使用默认),模式为ROW,允许最大日志为1G
#log_bin = mysql-bin
#binlog_format = ROW
#max_binlog_size = 1024M
# 主节点master不需要写binlog的数据库
binlog_ignore_db = mysql
binlog_ignore_db = information_schema
binlog_ignore_db = performance_schema
binlog_ignore_db = sys
# 从节点slave不进行数据同步的数据库
replicate_ignore_db = mysql
replicate_ignore_db = information_schema
replicate_ignore_db = performance_schema
replicate_ignore_db = sys
# 中继日志(默认是开启的,直接使用默认)
#relay_log = mysql-relay-bin
# mysql5.7以后的版本不需要配置log-slave-updates=1
# log-slave-updates = 1
#[client]
#socket = /var/run/mysqld/mysqld.sock
#!includedir /etc/mysql/conf.d/
kind: ConfigMap
metadata:
creationTimestamp: null
name: mysql-master-01-cm
namespace: mysql-cluster
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql-master-01
namespace: mysql-cluster
spec:
selector:
matchLabels:
app: mysql-master
serviceName: "mysql-master-svc-01"
replicas: 1
template:
metadata:
labels:
app: mysql-master
spec:
terminationGracePeriodSeconds: 10
containers:
- args:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --lower_case_table_names=1
- --default-time_zone=+8:00
name: mysql
# image: docker.io/library/mysql:8.0.34
image: registry.cn-shenzhen.aliyuncs.com/xiaohh-docker/mysql:8.0.34
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
- name: mysql-conf
mountPath: /etc/my.cnf
readOnly: true
subPath: my.cnf
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
key: mysql_root_password
name: mysql-password
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-master-01-nfs-pvc
- name: mysql-conf
configMap:
name: mysql-master-01-cm
items:
- key: my.cnf
mode: 0644
path: my.cnf
3.3.2 主节点2
主节点2 mysql-master-2.yaml 内容如下
bash
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-master-02-nfs-pv
namespace: mysql-cluster
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 192.168.40.129
path: /data/nfs/mysql-master-02
storageClassName: "nfs"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-master-02-nfs-pvc
namespace: mysql-cluster
spec:
accessModes:
- ReadWriteMany
storageClassName: "nfs"
resources:
requests:
storage: 1Gi
volumeName: mysql-master-02-nfs-pv
---
apiVersion: v1
kind: Service
metadata:
name: mysql-master-svc-02
namespace: mysql-cluster
labels:
app: mysql-master
spec:
ports:
- port: 3306
name: mysql
targetPort: 3306
nodePort: 3307
selector:
app: mysql-master
type: NodePort
sessionAffinity: ClientIP
---
apiVersion: v1
data:
my.cnf: |
[mysqld]
server-id = 2
# 开启gtid
gtid_mode = ON
enforce_gtid_consistency = 1
# 设置自增ID初始值为1,每次自增量为2。即都是偶数2,4,6,8,...
auto_increment_offset = 1
auto_increment_increment = 2
# 开启bin_log(默认是开启的,直接使用默认),模式为ROW,允许最大日志为1G
#log_bin = mysql-bin
#binlog_format = ROW
#max_binlog_size = 1024M
# 主节点master不需要写binlog的数据库
binlog_ignore_db = mysql
binlog_ignore_db = information_schema
binlog_ignore_db = performance_schema
binlog_ignore_db = sys
# 从节点slave不进行数据同步的数据库
replicate_ignore_db = mysql
replicate_ignore_db = information_schema
replicate_ignore_db = performance_schema
replicate_ignore_db = sys
# 中继日志(默认是开启的,直接使用默认)
#relay_log = mysql-relay-bin
# mysql5.7以后的版本不需要配置log-slave-updates=1
# log-slave-updates = 1
#[client]
#socket = /var/run/mysqld/mysqld.sock
#!includedir /etc/mysql/conf.d/
kind: ConfigMap
metadata:
creationTimestamp: null
name: mysql-master-02-cm
namespace: mysql-cluster
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql-master-02
namespace: mysql-cluster
spec:
selector:
matchLabels:
app: mysql-master
serviceName: "mysql-master-svc-02"
replicas: 1
template:
metadata:
labels:
app: mysql-master
spec:
terminationGracePeriodSeconds: 10
containers:
- args:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --lower_case_table_names=1
- --default-time_zone=+8:00
name: mysql
# image: docker.io/library/mysql:8.0.34
image: registry.cn-shenzhen.aliyuncs.com/xiaohh-docker/mysql:8.0.34
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
- name: mysql-conf
mountPath: /etc/my.cnf
readOnly: true
subPath: my.cnf
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
key: mysql_root_password
name: mysql-password
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-master-02-nfs-pvc
- name: mysql-conf
configMap:
name: mysql-master-02-cm
items:
- key: my.cnf
mode: 0644
path: my.cnf
3.3.3 配置注意点
- nfs 的地址、路径
- msql的配置中 server-id 要不同,gtid_mode设置为on,enforce_gtid_consistency设置为1
bash
[mysqld]
server-id = 2
# 开启gtid
gtid_mode = ON
enforce_gtid_consistency = 1
- mysql的镜像地址 有需要改成能拉取到的镜像
- service 的nodePort端口要设置不同(共用一个service的可以不变)
3.4 启动集群
3.4.1 启动
bash
kubectl apply -f .
3.4.2 k8s查看所有集群信息
bash
kubectl get all -n mysql-cluster -o wide
3.4.3 进入主节点1
bash
kubectl exec -itn mysql-cluster pod/mysql-master-01-0 -- mysql -uroot -p
输入密码·12345
加入集群命令
bash
change master to
master_host='mysql-master-02-0.mysql-master-svc-02.mysql-cluster.svc.cluster.local',
master_port=3306,
master_user='root',
master_password='123456',
master_auto_position=1,
get_master_public_key=1;
需要注意下面的几个参数:
- master_host: 这个参数是 节点2的 master的地址,(根据k8s的网络解析,pod名称.service名称.命名空间.svc.cluster.local 。我的是 mysql-master-02-0.mysql-master-svc-02.mysql-cluster.svc.cluster.local)
- master_port: 主节点的mysql端口,我们没改默认是3306
- master_user: 登录到主节点的mysql用户
- master_password: 登录到主节点要用到的密码
- get_master_public_key: 连接主mysql的公钥获取方式 根据上面参数,
如果要修改那么请按照自己的环境进行修改。
启动主从
bash
#启动
start slave;
#查看副本状态
show replica status\G;
看到这两项都为yes表示正常
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
3.4.4 进入主节点2
bash
kubectl exec -itn mysql-cluster pod/mysql-master-02-0 -- mysql -uroot -p
输入密码·12345
加入集群命令
bash
change master to
master_host='mysql-master-01-0.mysql-master-svc-01.mysql-cluster.svc.cluster.local',
master_port=3306,
master_user='root',
master_password='123456',
master_auto_position=1,
get_master_public_key=1;
需要注意下面的几个参数:
- master_host: 这个参数是 节点1的 master的地址,(根据k8s的网络解析,pod名称.service名称.命名空间.svc.cluster.local 。我的是 mysql-master-01-0.mysql-master-svc-01.mysql-cluster.svc.cluster.local)
- master_port: 主节点的mysql端口,我们没改默认是3306
- master_user: 登录到主节点的mysql用户
- master_password: 登录到主节点要用到的密码
- get_master_public_key: 连接主mysql的公钥获取方式 根据上面参数,
如果要修改那么请按照自己的环境进行修改。
启动主从
bash
#启动
start slave;
#查看副本状态
show replica status\G;
看到这两项都为yes表示正常
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
四,测试集群
4.1 完整性测试
工具连接两个 是3306、3307,端口,
我们在在节点1上建库,建表
sql
CREATE DATABASE `test_db`;
USE `test_db`;
CREATE TABLE `user` (
`user_id` BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '用户id',
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`age` TINYINT UNSIGNED DEFAULT 18 COMMENT '年龄',
`gender` TINYINT UNSIGNED DEFAULT 2 COMMENT '性别;0=男,1=女,2=未知'
) COMMENT '用户表';
到节点2上查看,是否同步了
我们在节点2上插入2条数据,看下是否能同步
sql
INSERT INTO `user` (`username`, `age`, `gender`) VALUES ('oopxiajun', '18', '0');
INSERT INTO `user` (`username`, `age`, `gender`) VALUES ('01', '28', '0');
再去节点1上看下是否有这两条数据
已经成功同步。
4.2 宕机其中一台测试
关闭 节点2
bash
kubectl delete -f mysql-master-2.yaml
节点2已经连不上连不上了
这时我们在节点1插入一条数据
sql
INSERT INTO `user` (`username`, `age`, `gender`) VALUES ('02宕机数据', '28', '0');
启动节点2
bash
kubectl apply -f mysql-master-2.yaml
查看数据是否同步
这样我们架构就保证我们两台中一台能正常运行,业务就不会停止,发生故障的服务器恢复后可以自动同步数据。