K8S搭建redis主从集群

2022-08-10 11:57:35

1. 创建NFS存储

创建NFS存储主要是为了给Redis提供稳定的后端存储,当Redis的Pod重启或迁移后,依然能获得原先的数据。这里,我们先要创建NFS,然后通过使用PV为Redis挂载一个远程的NFS路径。

安装NFS

#将需要在挂载的服务器中安装NFS
yum -yinstall nfs-utils(主包提供文件系统)
yum -yinstall rpcbind(提供rpc协议)

新增/etc/exports文件,用于设置需要共享的路径:

vim /etc/exports
/home/nfs/pv1 *(rw,sync,no_subtree_check,no_root_squash)
/home/nfs/pv2 *(rw,sync,no_subtree_check,no_root_squash)
/home/nfs/pv3 *(rw,sync,no_subtree_check,no_root_squash)
/home/nfs/pv4 *(rw,sync,no_subtree_check,no_root_squash)
/home/nfs/pv5 *(rw,sync,no_subtree_check,no_root_squash)
/home/nfs/pv6 *(rw,sync,no_subtree_check,no_root_squash)

创建相应目录

mkdir -p /home/nfs/pv{1..6}

启动NFS和rpcbind服务

systemctlenable rpcbind.service
systemctlenable nfs-server.service
systemctl start rpcbind.service
systemctl start nfs-server.service
exportfs -r
systemctl reload nfs-server

查看存储端共享

showmount -e[IP]

2. 创建PV

每一个Redis Pod都需要一个独立的PV来存储自己的数据,因此可以创建一个pv.yaml文件,包含6个PV:

apiVersion: v1kind: PersistentVolumemetadata:name: nfs-pv1spec:capacity:storage: 200MaccessModes:- ReadWriteManynfs:server: 192.168.1.23path:"/home/nfs/pv1"---apiVersion: v1kind: PersistentVolumemetadata:name: nfs-pv2spec:capacity:storage: 200MaccessModes:- ReadWriteManynfs:server: 192.168.1.23path:"/home/nfs/pv2"---apiVersion: v1kind: PersistentVolumemetadata:name: nfs-pv3spec:capacity:storage: 200MaccessModes:- ReadWriteManynfs:server: 192.168.1.23path:"/home/nfs/pv3"---apiVersion: v1kind: PersistentVolumemetadata:name: nfs-pv4spec:capacity:storage: 200MaccessModes:- ReadWriteManynfs:server: 192.168.1.23path:"/home/nfs/pv4"---apiVersion: v1kind: PersistentVolumemetadata:name: nfs-pv5spec:capacity:storage: 200MaccessModes:- ReadWriteManynfs:server: 192.168.1.23path:"/home/nfs/pv5"---apiVersion: v1kind: PersistentVolumemetadata:name: nfs-pv6spec:capacity:storage: 200MaccessModes:- ReadWriteManynfs:server: 192.168.1.23path:"/home/nfs/pv6"

创建PV

kubectl create -f pv.yaml

3. 创建Configmap

这里,我们可以直接将Redis的配置文件转化为Configmap,这是一种更方便的配置读取方式。配置文件redis.conf如下

appendonly yes
cluster-enabled yes
cluster-config-file /var/lib/redis/nodes.conf
cluster-node-timeout 5000
dir /var/lib/redis
port 6379

创建名为redis-conf的Configmap:

kubectl create configmap redis-conf --from-file=redis.conf

4. 创建Headless service

Headless service是StatefulSet实现稳定网络标识的基础,我们需要提前创建。准备文件headless-service.yml如下:

apiVersion: v1kind: Servicemetadata:name: redis-servicelabels:app: redisspec:ports:-name: redis-portport:6379clusterIP: Noneselector:app: redisappCluster: redis-cluster

创建

kubectl create -f headless-service.yml

在这里插入图片描述
服务名称为redis-service,其CLUSTER-IP为None,表示这是一个“无头”服务。

5. 创建Redis集群节点(v=6.2.6)

创建好Headless service后,就可以利用StatefulSet创建Redis 集群节点,这也是本文的核心内容。我们先创建redis.yml文件:

apiVersion: apps/v1kind: StatefulSetmetadata:name: redis-appspec:serviceName:"redis-service"replicas:6selector:matchLabels:app: redistemplate:metadata:labels:app: redisappCluster: redis-clusterspec:terminationGracePeriodSeconds:20affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:-weight:100podAffinityTerm:labelSelector:matchExpressions:-key: appoperator: Invalues:- redistopologyKey: kubernetes.io/hostnamecontainers:-name: redisimage: rediscommand:-"redis-server"args:-"/etc/redis/redis.conf"-"--protected-mode"-"no"resources:requests:cpu:"100m"memory:"100Mi"ports:-name: rediscontainerPort:6379protocol:"TCP"-name: clustercontainerPort:16379protocol:"TCP"volumeMounts:-name:"redis-conf"mountPath:"/etc/redis"-name:"redis-data"mountPath:"/var/lib/redis"volumes:-name:"redis-conf"configMap:name:"redis-conf"items:-key:"redis.conf"path:"redis.conf"volumeClaimTemplates:-metadata:name: redis-dataspec:accessModes:["ReadWriteMany"]resources:requests:storage: 200M

如上,总共创建了6个Redis节点(Pod),其中3个将用于master,另外3个分别作为master的slave;Redis的配置通过volume将之前生成的redis-conf这个Configmap,挂载到了容器的/etc/redis/redis.conf;Redis的数据存储路径使用volumeClaimTemplates声明(也就是PVC),其会绑定到我们先前创建的PV上。

创建

kubectl apply -f redis.yaml

在这里插入图片描述
另外,根据StatefulSet的规则,我们生成的Redis的6个Pod的hostname会被依次命名为 [statefulset名称]-[序号]

如图所示:可以看到这些Pods在部署时是以{0…N-1}的顺序依次创建的。注意,直到redis-app-0状态启动后达到Running状态之后,redis-app-1 才开始启动。

同时,每个Pod都会得到集群内的一个DNS域名,格式为[podname].[service name].[namespace].svc.cluster.local,也即

redis-app-0.redis-service.default.svc.cluster.local
redis-app-1.redis-service.default.svc.cluster.local...以此类推...

在K8S集群内部,这些Pod就可以利用该域名互相通信。我们可以使用ubuntu镜像的nslookup检验这些域名:
在这里插入图片描述
另外可以发现,我们之前创建的pv都被成功绑定了:
在这里插入图片描述

6. 初始化Redis集群

创建好6个Redis Pod后,我们还需要利用常用的Redis-tribe工具进行集群的初始化

由于Redis集群必须在所有节点启动后才能进行初始化,而如果将初始化逻辑写入Statefulset中,则是一件非常复杂而且低效的行为。我们可以在K8S上创建一个额外的容器,专门用于进行K8S集群内部某些服务的管理控制。
这里,我们专门启动一个Ubuntu的容器,可以在该容器中安装Redis-tribe,进而初始化Redis集群.

因为官方的ubuntu镜像里面的redis初始化的工具是没有的,我已经将初始化时需要的环境都打好了
https://download.csdn.net/download/zxc_123_789/80630356

下载此tar包后将其加载为镜像,然后运行此镜像

kubectl run -it ubuntu --image=ubuntu --restart=Never /bin/bash

初始化集群:
可以使用nslookup redis-app-0.redis-service命令查看每个节点对应的IP
在这里插入图片描述

然后,创建只有Master节点的集群:

redis-trib.py create10.244.4.16:637910.244.1.66:637910.244.6.14:6379

其次,为每个Master添加Slave

redis-trib.py replicate --master-addr10.244.4.16:6379  --slave-addr10.244.3.25:6379
redis-trib.py replicate --master-addr10.244.1.66:6379  --slave-addr10.244.5.27:6379
redis-trib.py replicate --master-addr10.244.6.14:6379  --slave-addr10.244.2.71:6379

至此,我们的Redis集群就真正创建完毕了,连到任意一个Redis Pod中检验一下:

kubectlexec -it redis-app-0bash

在这里插入图片描述
另外,还可以在NFS上查看Redis挂载的数据:
在这里插入图片描述

7. 创建用于访问Service

前面我们创建了用于实现StatefulSet的Headless Service,但该Service没有Cluster Ip,因此不能用于外界访问。所以,我们还需要创建一个Service,专用于为Redis集群提供访问和负载均衡:

apiVersion: v1
kind: Service
metadata:
  name: redis-access-service
  labels:
    app: redis
spec:
  ports:
    - name: redis-port
      protocol:"TCP"
      port:6379
      targetPort:6379
  selector:
    app: redis
    appCluster: redis-cluster

如上,该Service名称为redis-access-service,在K8S集群中暴露6379端口,并且会对labels name为app: redisappCluster: redis-cluster的pod进行负载均衡。

至此,k8s中的3主3从的redis集群环境就搭建好了.

  • 作者:心海里的锚
  • 原文链接:https://blog.csdn.net/zxc_123_789/article/details/122924616
    更新时间:2022-08-10 11:57:35