美文网首页
在Kubernetes上部署Redis集群

在Kubernetes上部署Redis集群

作者: zizhazhu | 来源:发表于2022-01-11 18:34 被阅读0次

    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的方法,和容器环境很不协调。

    相关文章

      网友评论

          本文标题:在Kubernetes上部署Redis集群

          本文链接:https://www.haomeiwen.com/subject/fyimcrtx.html