一、安装和配置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
上图中我们看到的 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 个节点完成一个集群配置。
](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 指令,需要提前完成安装 。