k8s上部署高可用redis集群--三主三从

K8S搭建三主三从高可用redis集群

  • 一、创建存储卷
  • 二、创建PV
  • 三、创建configmap
  • 四、创建headless service
  • 五、创建redis集群节点
  • 六、初始化redis集群
  • 七、创建用于访问的service
  • 八、redis主从切换测试

本方案采用StatefulSet进行redis的部署。它为了解决有状态服务的问题,它所管理的Pod拥有固定的Pod名称,启停顺序。在Deployment中,与之对应的服务是service,而在StatefulSet中与之对应的headless service,headless service,即无头服务,与service的区别就是它没有Cluster IP,解析它的名称时将返回该Headless Service对应的全部Pod的Endpoint列表。
在k8s上搭建Redis sentinel完全没有意义,经过测试,当master节点宕机后,sentinel选择新的节点当主节点,当原master恢复后,此时无法再次成为集群节点。因为在物理机上部署时,sentinel探测以及更改配置文件都是以IP的形式,集群复制也是以IP的形式,但是在容器中,虽然采用的StatefulSet的Headless Service来建立的主从,但是主从建立后,master、slave、sentinel记录还是解析后的IP,但是pod的IP每次重启都会改变,所有sentinel无法识别宕机后又重新启动的master节点,所以一直无法加入集群,虽然可以通过固定pod IP或者使用NodePort的方式来固定,或者通过sentinel获取当前master的IP来修改配置文件。 sentinel实现的是高可用Redis主从,检测Redis Master的状态,进行主从切换等操作,但是在k8s中,无论是dc或者ss,都会保证pod以期望的值进行运行,再加上k8s自带的活性检测,当端口不可用或者服务不可用时会自动重启pod或者pod的中的服务,所以当在k8s中建立了Redis主从同步后,相当于已经成为了高可用状态,并且sentinel进行主从切换的时间不一定有k8s重建pod的时间快,所以个人认为在k8s上搭建sentinel没有意义。

K8s集群环境

节点 IP
master 192.168.1.100
node1 192.168.1.101
node2 192.168.1.102
node3 192.168.1.103

下载镜像经导入集群中redis:3.2.8、inem0o/redis-trib:latest
docker pull redis:3.2.8; docker save –o redis.tar redis:3.2.8
docker pull inem0o/redis-trib:latest; docker save –o redis-trib.tar inem0o/redis-trib:latest
redis.tar上传至k8s的各个node节点;redis-trib.tar上传至k8s的master节点

一、创建存储卷

创建NFS存储主要是为了给Redis提供稳定的后端存储,当Redis的Pod重启或迁移后,依然能获得原先的数据。

  1. 安装nfs软件包
]# yum –y install nfs-utils rpcbind	#任选一台节点(这里选k8s-master)
  1. 创建共享存储
]# mkdir -p /usr/local/k8s/redis/pv{1..6}	#创建共享目录
]# cat /etc/exports	#配置共享路径
/redis/pv1 192.168.1.0/24(rw,sync,no_root_squash)
/redis/pv2 192.168.1.0/24(rw,sync,no_root_squash)
/redis/pv3 192.168.1.0/24(rw,sync,no_root_squash)
/redis/pv4 192.168.1.0/24(rw,sync,no_root_squash)
/redis/pv5 192.168.1.0/24(rw,sync,no_root_squash)
/redis/pv6 192.168.1.0/24(rw,sync,no_root_squash)
]# systemctl restart rpcbind;systemctl restart nfs;systemctl enable nfs 

查看共享路径
exportfs –v	#k8s-master上操作
其他节点安装nfs客户端,并验证
]# yum -y install nfs-utils
]# showmount -e 192.168.1.100
Export list for 192.168.1.10:
/redis/pv1 192.168.1.0/24
/redis/pv2 192.168.1.0/24
/redis/pv3 192.168.1.0/24
/redis/pv4 192.168.1.0/24
/redis/pv5 192.168.1.0/24
/redis/pv6 192.168.1.0/24

二、创建PV

以下操作在k8s-master上执行即可
1.每一个Redis Pod都需要一个独立的PV来存储自己的数据,因此可以创建一个pv.yaml文件,包含6个PV:

]# vim pv.yaml 
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv1
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.100
    path: "/redis/pv1"
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-vp2
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.100
    path: "/redis/pv2"
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv3
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.100
    path: "/redis/pv3"
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-vp4
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.100
    path: "/redis/pv4"
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv5
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.100
    path: "/redis/pv5"
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-vp6
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.100
    path: "/redis/pv6"
    
]# kubectl create -f pv.yaml #创建pv存储卷
persistentvolume "nfs-pv1" created
persistentvolume "nfs-pv2" created
persistentvolume "nfs-pv3" created
persistentvolume "nfs-pv4" created
persistentvolume "nfs-pv5" created
persistentvolume "nfs-pv6" created

三、创建configmap

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

]# vim 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

]# kubectl create configmap redis-conf --from-file=redis.conf
]# kubectl describe cm redis-conf #查看创建的configmap:
Name:         redis-conf
Namespace:    default
Labels:       
Annotations:  

Data
====
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

Events:   

四、创建headless service

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

]# vim headless-service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: redis-service
  labels:
    app: redis
spec:
  ports:
  - name: redis-port
    port: 6379
  clusterIP: None
  selector:
app: redis

]# kubectl create -f headless-service.yml
]# kubectl get svc redis-service 

五、创建redis集群节点

  1. 通过StatefulSet创建6个redis的pod ,实现3主3从的redis集群
]# vim redis.yaml 
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-app
spec:
  serviceName: "redis-service"
  replicas: 6 
  selector: 
    matchLabels:
      app: redis
      appCluster: redis-cluster
  template:
    metadata:
      labels:
        app: redis
        appCluster: redis-cluster
    spec:
      containers:
      - name: redis
        image: "redis:3.2.8"
        command:
          - "redis-server"
        args:
          - "/etc/redis/redis.conf"
          - "--protected-mode"
          - "no"
        resources:
          requests:
            cpu: "100m"
            memory: "100Mi"
        ports:
            - name: redis
              containerPort: 6379
              protocol: "TCP"
            - name: cluster
              containerPort: 16379
              protocol: "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-data
    spec:
      accessModes: [ "ReadWriteMany" ]
      resources:
        requests:
          storage: 2Gi
          
]# kubectl create -f redis.yaml
]# kubectl get pods -o wide

六、初始化redis集群

初始化集群采用redis-trib这个工具,直接运行一个容器实现初始化
参考链接https://github.com/iNem0o/docker-redis-trib

]# docker run --rm -ti inem0o/redis-trib create --replicas 1 IP1:6379 IP2:6379  IP3:6379  IP4:6379  IP5:6379  IP6:6379    # IP为6个redis pod的IP
在提示中输入Yes继续初始化

k8s上部署高可用redis集群--三主三从_第1张图片

验证集群状态,集群节点状态为OK,共有6个节点

#kubectl exec -ti redis-app-0 -- redis-cli -c
> cluster iinfo    # 查看集群状态
> role    #查看角色

k8s上部署高可用redis集群--三主三从_第2张图片

七、创建用于访问的service

之前创建了用于实现StatefulSet的Headless Service,但该Service没有Cluster IP,因此不能用于外界访问。所以,我们还需要创建一个Service,专用于为Redis集群提供访问和负载均衡;也可以部署为Ingress供集群外部访问。这里只创建用于内部访问的service

]# vim redis-access-service.yaml 
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

]# kubectl create -f redis-access-service.yaml
该Service名称为 redis-access-service,在K8S集群中暴露6379端口。如果需要提供集群外部访问,可以创建NodePort或者ingress类型

八、redis主从切换测试

删除一个pod为redis的master
]# kubectl delete pods redis-app-1
pod “redis-app-0” deleted

删除pod后,k8s会自动重建一个名称为“redis-app-1”并加入到集群中,但IP不一定是原来的IP;再次查看集群角色,redis-app-1由master变为salve,集群整体依然是6个

你可能感兴趣的:(kubernetes)