Kubernetes部署MySQL主从复制
Kubernetes集群为一主二从
1.部署架构图
2.创建ConfigMap
2.1 主节点ConfigMap配置
新建主节点mysqld.cnf资源清单文件mysql-source-cnf.yaml,并输入以下内容:
kind: ConfigMap
apiVersion: v1
metadata:name: mysql-source-cnf
data:mysqld.cnf: |-[mysqld]server-id=1read-only=0host-cache-size=0skip-name-resolve
2.2 从节点ConfigMap配置
新建从节点mysqld.cnf资源清单文件mysql-replica-cnf.yaml,并输入以下内容:
kind: ConfigMap
apiVersion: v1
metadata:name: mysql-replica-cnf
data:mysqld.cnf: |-[mysqld]server-id=2read-only=1host-cache-size=0skip-name-resolve
2.3 创建资源
[root@k8s-master01]# kubectl apply -f mysql-replica-cnf.yaml -f mysql-sourcecnf.yaml
3.创建Secret
3.1 Secret配置
我们创建一个 Secret 用来存储 MySQL root 用户的密码,主从使用相同的 Secret 配置。 运行 echo -n "123456!" | base64 命令生成 base64 编码的密码。 使用 vi 编辑器,新建 MySQL Secret 资源清单文件 mysql-secret.yaml ,并输入以下内容:
kind: Secret
apiVersion: v1
metadata:name: mysql-secret
data:MYSQL_ROOT_PASSWORD: MTIzNDU2type: Opaque
3.2 创建资源
[root@k8s-master01]# kubectl apply -f mysql-secret.yaml
4. 创建Service
4.1 创建主节点headless服务
新建 MySQL 主节点 headless 资源清单文件 mysql-source-svc.yaml ,并输入以下 内容:
kind: Service
apiVersion: v1
metadata:name: mysql-source-headlesslabels:app: mysql-source
spec:ports:- name: tcp-3306protocol: TCPport: 3306targetPort: 3306selector:app: mysql-sourceclusterIP: Nonetype: ClusterIP
执行下面的命令,创建资源。
[root@k8s-master01]# kubectl apply -f mysql-replica-svc.yaml
4.2 创建从节点headless服务
新建 MySQL 从节点 headless 资源清单文件 mysql-replica-svc.yaml ,并输入以 下内容:
kind: Service
apiVersion: v1
metadata:name: mysql-replica-headlesslabels:app: mysql-replica
spec:ports:- name: tcp-3306protocol: TCPport: 3306targetPort: 3306selector:app: mysql-replicaclusterIP: Nonetype: ClusterIP
执行下面的命令,创建资源
[root@k8s-master01]# kubectl apply -f mysql-replica-svc.yaml
4.3 创建外部访问服务
使用最简单的 NodePort 方式发布 k8s 集群上的 MySQL 服务给外部应用访问,指定的端口为 31306。
新建 MySQL 从节点 headless 资源清单文件 mysql-external-svc.yaml ,并输入以 下内容:
apiVersion: v1
kind: Service
metadata:name: mysql-source-external
spec:type: NodePortselector:app: mysql-sourceports:- port: 3306targetPort: 3306nodePort: 31306
执行下面的命令,创建资源。
[root@k8s-master01]# kubectl apply -f mysql-external-svc.yaml
5.创建StatefulSet
在 Kubernetes 集群中部署数据库服务时,我们面临着选择有状态服务(StatefulSet)与无状态服务 (Deployment)之间的决策。对于 MySQL 这类数据库服务,我们选择使用 StatefulSet 而不是 Deployment,原因如下:
- 稳定的网络身份:StatefulSet 为每个 Pod 分配了一个持久且唯一的网络标识符,这对于 MySQL 这 类需要固定主机名或网络地址以维持主从复制关系的数据库服务至关重要。
- 持久化存储:StatefulSet 易于与持久化存储卷结合使用,确保数据库数据的持久保存,即便是在 Pod 重启或重新调度后。
- 适合有状态应用:StatefulSet 是为有状态应用设计的,如数据库和消息队列,它提供了必要的支持 来维护这些应用的状态。
5.1 创建主节点StatefulSet
新建 MySQL 主节点 StatefulSet 资源清单文件 mysql-source-sts.yaml ,并输入以 下内容:
kind: StatefulSet
apiVersion: apps/v1
metadata:name: mysql-sourcelabels:app: mysql-source
spec:replicas: 1selector:matchLabels:app: mysql-sourcetemplate:metadata:labels:app: mysql-sourcespec:volumes:- name: host-timehostPath:path: /etc/localtimetype: ''- name: configconfigMap:name: mysql-source-cnfdefaultMode: 420containers:- name: mysql-sourceimage: mysql:8.4.3imagePullPolicy: IfNotPresentports:- containerPort: 3306env:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: MYSQL_ROOT_PASSWORDresources:limits:cpu: '2'memory: 4Girequests:cpu: 100mmemory: 100MivolumeMounts:- name: host-timemountPath: /etc/localtime- name: datamountPath: /var/lib/mysql- name: configreadOnly: truemountPath: /etc/mysql/conf.d/volumeClaimTemplates:- metadata:name: dataspec:accessModes: ["ReadWriteOnce"]resources:requests:storage: 10GistorageClassName: nfs-clientvolumeMode: FilesystemserviceName: mysql-source-headless
执行下面的命令,创建资源。
[root@k8s-master01]# kubectl apply -f mysql-source-sts.yaml
5.2 创建从节点StatefulSet
新建 MySQL 从节点 StatefulSet 资源清单文件 mysql-replica-sts.yaml ,并输入 以下内容:
kind: StatefulSet
apiVersion: apps/v1
metadata:name: mysql-replicalabels:app: mysql-replica
spec:replicas: 1selector:matchLabels:app: mysql-sourcetemplate:metadata:labels:app: mysql-sourcespec:volumes:- name: host-timehostPath:path: /etc/localtimetype: ''- name: configconfigMap:name: mysql-source-cnfdefaultMode: 420containers:- name: mysql-sourceimage: mysql:8.4.3imagePullPolicy: IfNotPresentports:- containerPort: 3306env:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: MYSQL_ROOT_PASSWORDresources:limits:cpu: '2'memory: 4Girequests:cpu: 100mmemory: 100MivolumeMounts:- name: host-timemountPath: /etc/localtime- name: datamountPath: /var/lib/mysql- name: configreadOnly: truemountPath: /etc/mysql/conf.d/volumeClaimTemplates:- metadata:name: dataspec:accessModes: ["ReadWriteOnce"]resources:requests:storage: 10GistorageClassName: nfs-clientvolumeMode: FilesystemserviceName: mysql-source-headless
执行下面的命令,创建资源
[root@k8s-master01]# kubectl apply -f mysql-replica-sts.yaml
5.3 验证MySQL主从Pod状态
查看 Pod 状态
[root@k8s-master01]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
NOMINATED NODE READINESS GATES
mysql-replica-0 1/1 Running 0 13m 10.244.58.243 k8s-node02
<none> <none>
mysql-source-0 1/1 Running 0 13m 10.244.58.246 k8s-node02
<none> <none>
验证自定义配置是否生效6.
[root@k8s-master01]# kubectl exec -it mysql-source-0 -- mysql -uroot -p123456 -
e "show variables like '%max_conn%';"
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------------------+---------+
| Variable_name | Value |
+------------------------+---------+
| max_connect_errors | 1000000 |
| max_connections | 2048 |
| mysqlx_max_connections | 100 |
+------------------------+---------+
6.配置主从同步
6.1 主节点配置
6.1.1进入MySQL主节点容器内部
[root@k8s-master01 3]# kubectl exec -it mysql-source-0 -- mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.4.3 MySQL Community Server - GPLCopyright (c) 2000, 2024, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql>
6.1.2 创建主从同步用户
在主服务器上创建同步使用的用户 repuser 并赋予指定的权限
-- 创建用户并设置密码
mysql> CREATE USER 'repuser'@'%' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.01 sec) -- 赋予权限
mysql> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repuser'@'%';
Query OK, 0 rows affected (0.01 sec)-- 刷新权限
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
6.1.3 查看Master状态
mysql> SHOW BINARY LOG STATUS;
+---------------+----------+--------------+------------------+-------------------
+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set
|
+---------------+----------+--------------+------------------+-------------------
+
| binlog.000002 | 886 | | |
|
+---------------+----------+--------------+------------------+-------------------
+
1 row in set (0.00 sec)
6.2 从节点配置
6.2.1 进入MySQL从节点容器内部
[root@k8s-master01 3]# kubectl exec -it mysql-replica-0 -- mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.4.3 MySQL Community Server - GPLCopyright (c) 2000, 2024, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql>
6.2.2 配置主从同步
mysql> CHANGE REPLICATION SOURCE TOSOURCE_HOST='mysql-source-headless.default.svc.cluster.local',SOURCE_PORT=3306,SOURCE_USER='repuser',SOURCE_PASSWORD='123456',SOURCE_LOG_FILE='binlog.000002',SOURCE_LOG_POS=886,GET_SOURCE_PUBLIC_KEY=1;Query OK, 0 rows affected, 2 warnings (0.03 sec)
6.2.3 启动主从同步
mysql> start replica;
6.3.3 查看主从同步状态
mysql> show replica status\G;**************** 1. row ***************************Replica_IO_State: Waiting for source to send eventSource_Host: mysql-source-headless.default.svc.cluster.localSource_User: repuserSource_Port: 3306Connect_Retry: 60Source_Log_File: binlog.000002Read_Source_Log_Pos: 886Relay_Log_File: mysql-replica-0-relay-bin.000002Relay_Log_Pos: 325Relay_Source_Log_File: binlog.000002Replica_IO_Running: Yes # 重点注意Replica_SQL_Running: Yes # 重点注意
7. 验证主从同步
确认同步状态,在主节点新建数据库及表并添加数据,然后在从节点查询以验证主从同步是否正常。