在Kubernetes上部署Redis集群

2022-01-11  本文已影响0人  zizhazhu

Redis的分布式模式有主从模式、哨兵模式和Cluster模式,相对来说Cluster模式的机制更完善,内存利用率更高。因为项目在使用Redis进行存储时碰到了性能瓶颈,所以准备用Cluster模式尝试部署分布式Redis。

ps:Redis分布式的介绍可以参考https://segmentfault.com/a/1190000022808576

一、配置文件

先配置一个ConfigMap,后面会挂载到Redis的实例上,里面有一个脚本和一个redis的配置文件,redis配置文件可以根据需求修改,脚本的作用后面会讲。

apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster
data:
  fix-ip.sh: |
    #!/bin/sh
    CLUSTER_CONFIG="/data/nodes.conf"
    echo "creating nodes"
    if [ -f ${CLUSTER_CONFIG} ]; then
      echo "[ INFO ]File:${CLUSTER_CONFIG} is Found"
    else
      touch $CLUSTER_CONFIG
    fi
    if [ -z "${POD_IP}" ]; then
      echo "Unable to determine Pod IP address!"
      exit 1
    fi
    echo "Updating my IP to ${POD_IP} in ${CLUSTER_CONFIG}"
    sed -i.bak -e "/myself/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/${POD_IP}/" ${CLUSTER_CONFIG}
    echo "done"
    exec "$@"
  redis.conf: |+
    cluster-enabled yes
    cluster-require-full-coverage no
    cluster-node-timeout 15000
    cluster-config-file /data/nodes.conf
    cluster-migration-barrier 1
    appendonly yes
    protected-mode no

二、启动节点

这里使用StatefulSet作为工作负载,因为redis集群的节点是有状态的,这个状态会记录在之前配置指定的/data/nodes.conf文件里,节点重启后会根据这个文件的内容恢复节点在集群里的状态,所以需要StatefulSet提供持久化。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
  labels:
    run: redis-cluster
spec:
  serviceName: redis-cluster
  replicas: 6
  selector:
    matchLabels:
      run: redis-cluster
  template:
    metadata:
      labels:
        run: redis-cluster
    spec:
      containers:
      - name: redis
        image: redis:alpine 
        ports:
        - containerPort: 6379
          name: redis
        - containerPort: 16379
          name: gossip
        command: ["/conf/fix-ip.sh", "redis-server", "/conf/redis.conf"]
        env:
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        volumeMounts:
        - name: conf
          mountPath: /conf
          readOnly: false
        - name: data
          mountPath: /data
          readOnly: false
      volumes:
      - name: conf
        configMap:
          name: redis-cluster
          defaultMode: 0755
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 5Gi
      storageClassName: default

三、创建集群

加载上面两个配置文件后执行:

kubectl exec -it redis-cluster-0 -- redis-cli --cluster create --cluster-replicas 1 $(kubectl get pods -l run=redis-cluster -o jsonpath='{range.items[*]}{.status.podIP}:6379 {end}')  

这样就创建好了redis集群,redis-server会写入/data/nodes.conf文件,记录集群状态。因为在创建集群的时候是使用固定ip创建的,当节点重启后ip会发生变化,这个文件的信息就不准确了,所以需要在启动时更新/data/nodes.conf。这个就是fix-ip.sh这个脚本的工作,如果文件存在,就更新ip,如果不存在就创建文件。所以k8s的容器配置里有两个点和单机不一样:一个是command里使用"/conf/fix-ip.sh"作为启动项,先更新ip再启动实例;一个是加载pod ip到环境变量POD_IP,方便脚本加载。

四、创建service

创建好redis集群后还需要访问接口

apiVersion: v1
kind: Service
metadata:
  name: redis-cluster
spec:
  selector:
    run: redis-cluster
  ports:
  - port: 6379
    targetPort: 6379
    name: server
  - port: 16379
    targetPort: 16379
    name: gossip
  type: ClusterIP

五、坑

一开始是想用service的域名创建redis集群的,这样节点重启后就不需要更新ip,但是redis不支持使用域名,所以只能绕了一圈又回到固定ip的方法,和容器环境很不协调。

上一篇下一篇

猜你喜欢

热点阅读