基于K8S的StatefulSet部署MySQL集群

网友投稿 885 2023-03-27

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。

基于K8S的StatefulSet部署MySQL集群

环境:

# 采用NFS存储卷的方式 持久化存储mysql数据目录

需求:

展示如何使用 StatefulSet 控制器运行一个有状态的应用程序。此例是多副本的 MySQL 数据库。 示例应用的拓扑结构有一个主服务器和多个副本,使用异步的基于行(Row-Based) 的数据复制。

搭建一个“主从复制”(Maser-Slave Replication)的 MySQL 集群存在一个主节点【master】,有多个从节点【slave】从节点可以水平拓展所有的写操作,只能在主节点上执行读操作可以在所有节点上执行

一、部署NFS服务器

#服务器安装nfs服务,提供nfs存储功能 1、安装nfs-utils yum install nfs-utils (centos) 或者  apt-get install nfs-kernel-server (ubuntu)  2、启动服务 systemctl enable nfs-server systemctl start nfs-server  3、创建共享目录完成共享配置 mkdir /home/nfs   #创建共享目录  4、编辑共享配置 vim /etc/exports                                            #语法格式:    共享文件路径     客户机地址(权限)     #这里的客户机地址可以是IP,网段,域名,也可以是任意* /home/nfs  *(rw,async,no_root_squash)

#服务器安装nfs服务,提供nfs存储功能 1、安装nfs-utils yum install nfs-utils (centos) 或者  apt-get install nfs-kernel-server (ubuntu)  2、启动服务 systemctl enable nfs-server systemctl start nfs-server  3、创建共享目录完成共享配置 mkdir /home/nfs   #创建共享目录  4、编辑共享配置 vim /etc/exports                                            #语法格式:    共享文件路径     客户机地址(权限)     #这里的客户机地址可以是IP,网段,域名,也可以是任意* /home/nfs  *(rw,async,no_root_squash)

二、配置PV 动态供给(NFS StorageClass),创建pvc

部署NFS实现自动创建PV插件: 一共设计到4个yaml 文件 ,官方的文档有详细的说明

root@k8s-master1:~ # mkdir  /root/pvc root@k8s-master1:~ # cd   /root/pvc

创建rbac.yaml 文件

root@k8s-master1:pvc # cat rbac.yaml  kind: ServiceAccount apiVersion: v1 metadata:   name: nfs-client-provisioner --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata:   name: nfs-client-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"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata:   name: run-nfs-client-provisioner subjects:   - kind: ServiceAccount     name: nfs-client-provisioner     namespace: default roleRef:   kind: ClusterRole   name: nfs-client-provisioner-runner   apiGroup: rbac.authorization.k8s.io --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata:   name: leader-locking-nfs-client-provisioner rules:   - apiGroups: [""]     resources: ["endpoints"]     verbs: ["get", "list", "watch", "create", "update", "patch"] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata:   name: leader-locking-nfs-client-provisioner subjects:   - kind: ServiceAccount     name: nfs-client-provisioner     # replace with namespace where provisioner is deployed     namespace: default roleRef:   kind: Role   name: leader-locking-nfs-client-provisioner   apiGroup: rbac.authorization.k8s.io

创建deployment.yaml 文件

官方默认的镜像地址,国内可能无法下载,可以使用 image:

fxkjnj/nfs-client-provisioner:latest

#定义NFS 服务器的地址,共享目录名称

root@k8s-master1:pvc # cat deployment.yaml  apiVersion: v1 kind: ServiceAccount metadata:   name: nfs-client-provisioner --- kind: Deployment apiVersion: apps/v1  metadata:   name: nfs-client-provisioner spec:   replicas: 1   strategy:     type: Recreate   selector:     matchLabels:       app: nfs-client-provisioner   template:     metadata:       labels:         app: nfs-client-provisioner     spec:       serviceAccountName: nfs-client-provisioner       containers:         - name: nfs-client-provisioner           image: fxkjnj/nfs-client-provisioner:latest           volumeMounts:             - name: nfs-client-root               mountPath: /persistentvolumes           env:             - name: PROVISIONER_NAME               value: fuseim.pri/ifs             - name: NFS_SERVER               value: 172.16.201.209              - name: NFS_PATH               value: /home/nfs       volumes:         - name: nfs-client-root           nfs:             server: 172.16.201.209             path: /home/nfs

创建class.yaml

root@k8s-master1:pvc # cat class.yaml  apiVersion: storage.k8s.io/v1 kind: StorageClass metadata:   name: managed-nfs-storage provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME' parameters:   archiveOnDelete: "true"

部署

root@k8s-master1:pvc # kubectl apply -f .   #查看存储卷 root@k8s-master1:pvc # kubectl  get sc NAME                  PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE managed-nfs-storage   fuseim.pri/ifs   Delete          Immediate           false                  25h

三、编写mysql 相关yaml文件

MySQL 示例部署包含一个 ConfigMap、两个 Service 与一个 StatefulSet。

ConfigMap:

vim mysql-configmap.yaml

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

说明:

在这里,我们定义了 master.cnf 和 slave.cnf 两个 MySQL 的配置文件

master.cnf 开启了log-bin,可以使用二进制日志文件的方式进行主从复制.slave.cnf 开启了 super-read-only ,表示从节点只接受主节点的数据同步的所有写的操作,拒绝其他的写入操作,对于用户来说就是只读的master.cnf 和 slave.cnf 已配置文件的形式挂载到容器的目录中

Service:

vim mysql-services.yaml

# Headless service for stable DNS entries of StatefulSet members. apiVersion: v1 kind: Service metadata:   name: mysql   labels:     app: mysql spec:   ports:   - name: mysql     port: 3306   clusterIP: None   selector:     app: mysql --- # Client service for connecting to any MySQL instance for reads. # For writes, you must instead connect to the master: mysql-0.mysql. apiVersion: v1 kind: Service metadata:   name: mysql-read   labels:     app: mysql spec:   ports:   - name: mysql     port: 3306   selector:     app: mysql

说明:

clusterIP: None,使用无头服务 Headless Service(相比普通Service只是将spec.clusterIP定义为None,也就是没有clusterIP,直接使用endport 来通信)来维护Pod网络身份,会为每个Pod分配一个数字编号并且按照编号顺序部署。还需要在StatefulSet添加serviceName: “mysql”字段指定StatefulSet控制器

另外statefulset控制器网络标识,体现在主机名和Pod A记录:

• 主机名:-<编号>

例如: mysql-0

• Pod DNS A记录:. ..svc.cluster.local (POD 之间通过DNS A 记录互相通信)

例如:

mysql-0.mysql.default.svc.cluster.local

StatefulSet:

vim mysql-statefulset.yaml

说明:

四、部署并测试

root@k8s-master1:~/kubernetes/mysql# ll total 24 drwxr-xr-x 2 root root 4096 Nov  3 16:42 ./ drwxr-xr-x 8 root root 4096 Nov  3 13:33 ../ -rw-r--r-- 1 root root  278 Nov  2 22:15 mysql-configmap.yaml -rw-r--r-- 1 root root  556 Nov  2 22:08 mysql-services.yaml -rw-r--r-- 1 root root 5917 Nov  3 14:22 mysql-statefulset.yaml  root@k8s-master1:~/kubernetes/mysql# kubectl apply -f . configmap/mysql create service/mysql create service/mysql-read create statefulset.apps/mysql create   #动态追踪查看Pod的状态: root@k8s-master1:~/kubernetes/mysql# kubectl get pods -l app=mysql --watch NAME      READY   STATUS    RESTARTS   AGE mysql-0   2/2     Running   0          3h12m mysql-1   2/2     Running   0          3h11m mysql-2   2/2     Running   0          3h10m

可以看到,StatefulSet 启动成功后,将会有三个 Pod 运行。

接下来,我们可以尝试向这个 MySQL 集群发起请求,执行一些 SQL 操作来验证它是否正常:

kubectl run mysql-client --image=mysql:5.7 -i --rm --restart=Never --\ mysql -h mysql-0.mysql <

如上所示,我们通过启动一个容器,使用 MySQL client 执行了创建数据库和表、以及插入数据的操作。需要注意的是,我们连接的 MySQL 的地址必须是 mysql-0.mysql(即:Master 节点的 DNS A 记录, 因为POD 之间通过DNS A 记录互相通信)只有 Master 节点才能处理写操作。

而通过连接 mysql-read 这个 Service,我们就可以用 SQL 进行读操作,如下所示:

kubectl run mysql-client --image=mysql:5.7 -i -t --rm --restart=Never --\   mysql -h mysql-read -e "SELECT * FROM test.messages"       #你应该获得如下输出: Waiting for pod default/mysql-client to be running, status is Pending, pod ready: false +---------+ | message | +---------+ | hello   | +---------+ pod "mysql-client" deleted

或者:

上一篇:如何搭建IT运维管理体系
下一篇:IT运维选型 电信级和企业级解决方案
相关文章

 发表评论

暂时没有评论,来抢沙发吧~