k8s StatefulSet启用Redis Cluster搭建

一、安装和配置Redis

1、无数据持久化的redis

这里先根据启用一个最简单的 Redis 服务:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      app: redis
  serviceName: redis
  replicas: 3
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:latest
        ports:
        - containerPort: 6379
        volumeMounts:
        - name: data
          mountPath: /data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ['ReadWriteOnce']
        storageClassName: "csi-disk"
        resources:
          requests:
            storage: 1Gi

启动登录后,会发现在/data 目录下没有数据,因为默认情况下redis是不进行数据持久化的,其只保留内存数据。

2、启用数据持久化

需要启用数据持久化也比较简单,增加一个command配置,在启动时使用相关参数就行了:

containers:
- name: redis
  image: redis:latest
  command:
  - redis-server
  - --save 60 1
  ports:
  - containerPort: 6379

这里的 --save 60 1 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,这里指60秒内有1次更新操作就写文件,这里是支持可以多个条件配合的,比如:

save 900 1
save 300 10
save 60 10000

分别表示 900 秒(15 分钟)内有 1 个更改,300 秒(5 分钟)内有 10 个更改以及 60 秒内有 10000 个更改就更新数据文件。

# 更新配置文件

[root@testcce-92497 redis]# kubectl apply -f redis-save.yaml
statefulset.apps/redis configured
[root@testcce-92497 redis]# kubectl get  pods
NAME      READY   STATUS              RESTARTS   AGE
redis-0   1/1     Running             0          4m56s
redis-1   1/1     Running             0          4m51s
redis-2   0/1     ContainerCreating   0          3s

k8s-redis

上图中我们看到的 dump.rdb 文件就是导出的数据文件。

3、使用 redis.conf 配置文件

如果自定义配置改动比较多,使用command命令不停的加参数显然不是一个好的选择,显然需要通过一个配置文件承载相关配置,直接使用 docker 容器比较简单,直接指定一个本地文件就可以了:

docker run -v /myredis/conf:/usr/local/etc/redis --name myredis redis redis-server /usr/local/etc/redis/redis.conf

在 k8s 里实际操作也差不多,只不过需要通过configmap的方式存配置文件,再通过 volume 卷的方式挂载到容器里。

[root@testcce-92497 redis]# vim redis.conf
[root@testcce-92497 redis]# kubectl create configmap example-redis-config --from-file=redis-conf
configmap/example-redis-config created
[root@testcce-92497 redis]# kubectl get configmaps example-redis-config -o yaml

配置文件的挂载方式可以参看 k8s 官方文档,使用如下yaml挂载:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      app: redis
  serviceName: redis
  replicas: 3
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:latest
        command:
        - redis-server
        - "/redis-master/redis.conf"
        ports:
        - containerPort: 6379
        volumeMounts:
        - name: data
          mountPath: /data
        - name: config
          mountPath: /redis-master
      volumes:
        - name: config
          configMap:
            name: example-redis-config
            items:
            - key: redis-conf
              path: redis.conf

  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ['ReadWriteOnce']
        storageClassName: "csi-disk"
        resources:
          requests:
            storage: 1Gi

注意,这里使用的 key: redis-conf 要和 kubectl get configmap example-redis-config -o yaml 里查到的 data 下的值保持一致,不然会找不到相应的 configmap 内容,会报错 MountVolume.SetUp failed for volume "config" : configmap references non-existent config key: redis.config

正确执行的话,可以在挂载的目录看到相应的配置文件:

[root@testcce-92497 ~]# kubectl exec -it redis-2 -- /bin/bash
root@redis-2:/data# ls /redis-master/
redis.conf

二、安装配置redis cluster

redis 有两种高可用模式:Redis Cluster 和 Redis Sentinel , 本篇幅重点是讲 Cluster 模式,其架构图如下所示,需要 6 个节点完成一个集群配置。

redis-cluster](https://www.361way.com/wp-content/uploads/2023/07/redis-cluster.png “redis-cluster”)

1、configmap配置

apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster
  namespace: redis
data:
  update-node.sh: |
    #!/bin/sh
    REDIS_NODES="/data/nodes.conf"
    sed -i -e "/myself/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/${POD_IP}/" ${REDIS_NODES}
    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

2、StatefulSet实例配置

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
  namespace: redis
spec:
  serviceName: redis-cluster
  replicas: 6
  selector:
    matchLabels:
      app: redis-cluster
  template:
    metadata:
      labels:
        app: redis-cluster
    spec:
      containers:
      - name: redis
        image: redis:alpine
        ports:
        - containerPort: 6379
          name: client
        - containerPort: 16379
          name: gossip
        command: ["/conf/update-node.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:
      storageClassName: csi-disk
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

3、service配置

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

4、使用kubectl指令配置生效

执行前需要注意,这里使用的都是redis这个namespace,所以需要先通过kubectl create ns redis创建对应的命名空间。

kubectl create -f redis-config-map.yaml
kubectl create -f redis-sts.yaml
kubectl create -f redis-service.yaml

这时候还没完成集群激活操作,可以使用如下脚本执行完成集群激活操作:

#!/bin/bash
# Find ClusterIPs of Redis nodes
export REDIS_NODES=$(kubectl get pods  -l app=redis-cluster -n redis -o json | jq -r '.items | map(.status.podIP) | join(":6379 ")'):6379
# Activate the Redis cluster
kubectl exec -it redis-cluster-0 -n redis -- redis-cli --cluster create --cluster-replicas 1 ${REDIS_NODES}
# Check if all went well
for x in $(seq 0 5); do echo "redis-cluster-$x"; kubectl exec redis-cluster-$x -n redis -- redis-cli role; echo; done

注意,该脚本运行需要依赖 jq 指令,需要提前完成安装 。

redis-cluster-info

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注