一、安装和配置Redis

1、无数据持久化的redis

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

 1apiVersion: apps/v1
 2kind: StatefulSet
 3metadata:
 4  name: redis
 5spec:
 6  selector:
 7    matchLabels:
 8      app: redis
 9  serviceName: redis
10  replicas: 3
11  template:
12    metadata:
13      labels:
14        app: redis
15    spec:
16      containers:
17      - name: redis
18        image: redis:latest
19        ports:
20        - containerPort: 6379
21        volumeMounts:
22        - name: data
23          mountPath: /data
24  volumeClaimTemplates:
25    - metadata:
26        name: data
27      spec:
28        accessModes: ['ReadWriteOnce']
29        storageClassName: "csi-disk"
30        resources:
31          requests:
32            storage: 1Gi

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

2、启用数据持久化

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

1containers:
2- name: redis
3  image: redis:latest
4  command:
5  - redis-server
6  - --save 60 1
7  ports:
8  - containerPort: 6379

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

1save 900 1
2save 300 10
3save 60 10000

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

1# 更新配置文件
2
3[root@testcce-92497 redis]# kubectl apply -f redis-save.yaml
4statefulset.apps/redis configured
5[root@testcce-92497 redis]# kubectl get  pods
6NAME      READY   STATUS              RESTARTS   AGE
7redis-0   1/1     Running             0          4m56s
8redis-1   1/1     Running             0          4m51s
9redis-2   0/1     ContainerCreating   0          3s

k8s-redis
k8s-redis

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

3、使用 redis.conf 配置文件

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

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

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

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

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

 1apiVersion: apps/v1
 2kind: StatefulSet
 3metadata:
 4  name: redis
 5spec:
 6  selector:
 7    matchLabels:
 8      app: redis
 9  serviceName: redis
10  replicas: 3
11  template:
12    metadata:
13      labels:
14        app: redis
15    spec:
16      containers:
17      - name: redis
18        image: redis:latest
19        command:
20        - redis-server
21        - "/redis-master/redis.conf"
22        ports:
23        - containerPort: 6379
24        volumeMounts:
25        - name: data
26          mountPath: /data
27        - name: config
28          mountPath: /redis-master
29      volumes:
30        - name: config
31          configMap:
32            name: example-redis-config
33            items:
34            - key: redis-conf
35              path: redis.conf
36
37  volumeClaimTemplates:
38    - metadata:
39        name: data
40      spec:
41        accessModes: ['ReadWriteOnce']
42        storageClassName: "csi-disk"
43        resources:
44          requests:
45            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

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

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

二、安装配置redis cluster

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

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

1、configmap配置

 1apiVersion: v1
 2kind: ConfigMap
 3metadata:
 4  name: redis-cluster
 5  namespace: redis
 6data:
 7  update-node.sh: |
 8    #!/bin/sh
 9    REDIS_NODES="/data/nodes.conf"
10    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}
11    exec "$@"    
12  redis.conf: |+
13    cluster-enabled yes
14    cluster-require-full-coverage no
15    cluster-node-timeout 15000
16    cluster-config-file /data/nodes.conf
17    cluster-migration-barrier 1
18    appendonly yes
19    protected-mode no    

2、StatefulSet实例配置

 1apiVersion: apps/v1
 2kind: StatefulSet
 3metadata:
 4  name: redis-cluster
 5  namespace: redis
 6spec:
 7  serviceName: redis-cluster
 8  replicas: 6
 9  selector:
10    matchLabels:
11      app: redis-cluster
12  template:
13    metadata:
14      labels:
15        app: redis-cluster
16    spec:
17      containers:
18      - name: redis
19        image: redis:alpine
20        ports:
21        - containerPort: 6379
22          name: client
23        - containerPort: 16379
24          name: gossip
25        command: ["/conf/update-node.sh", "redis-server", "/conf/redis.conf"]
26        env:
27        - name: POD_IP
28          valueFrom:
29            fieldRef:
30              fieldPath: status.podIP
31        volumeMounts:
32        - name: conf
33          mountPath: /conf
34          readOnly: false
35        - name: data
36          mountPath: /data
37          readOnly: false
38      volumes:
39      - name: conf
40        configMap:
41          name: redis-cluster
42          defaultMode: 0755
43  volumeClaimTemplates:
44  - metadata:
45      name: data
46    spec:
47      storageClassName: csi-disk
48      accessModes: [ "ReadWriteOnce" ]
49      resources:
50        requests:
51          storage: 1Gi

3、service配置

 1apiVersion: v1
 2kind: Service
 3metadata:
 4  name: redis-cluster
 5  namespace: redis
 6spec:
 7  type: ClusterIP
 8  ports:
 9  - port: 6379
10    targetPort: 6379
11    name: client
12  - port: 16379
13    targetPort: 16379
14    name: gossip
15  selector:
16    app: redis-cluster

4、使用kubectl指令配置生效

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

1kubectl create -f redis-config-map.yaml
2kubectl create -f redis-sts.yaml
3kubectl create -f redis-service.yaml

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

1#!/bin/bash
2# Find ClusterIPs of Redis nodes
3export REDIS_NODES=$(kubectl get pods  -l app=redis-cluster -n redis -o json | jq -r '.items | map(.status.podIP) | join(":6379 ")'):6379
4# Activate the Redis cluster
5kubectl exec -it redis-cluster-0 -n redis -- redis-cli --cluster create --cluster-replicas 1 ${REDIS_NODES}
6# Check if all went well
7for 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
redis-cluster-info