redis-cluster 集群的部署网上一堆,用 k8s 部署也不在少数,但都是抄来抄去,问题不少,实际操作分享进去的还是太少。
1、redis 启动配置文件,应用 CofigMap 来治理比拟不便,redis-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-config
namespace: default
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\}/${MY_POD_IP}/" ${REDIS_NODES}
exec "$@"
redis.conf: |+
port 7001
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
#cluster-announce-ip ${MY_POD_IP}
#cluster-announce-port 7001
#cluster-announce-bus-port 17001
logfile "/data/redis.log"
阐明:2 个文件,node-update.sh 用来 redis 启动时执行脚本,具体前面再介绍为何要减少一个启动脚本;redis.conf 为 redis 启动配置文件。
2、redis 长久化存储 pv,pv 应用 nfs 服务存储,集群 6 个节点别离创立 6 个 pv 不同存储,动态创立 pv 文件 redis-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv0
labels:
pv: nfs-pv0
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 192.168.11.242
path: /root/nfs/redis-cluster0
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv1
labels:
pv: nfs-pv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 192.168.11.242
path: /root/nfs/redis-cluster1
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv2
labels:
pv: nfs-pv2
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 192.168.11.242
path: /root/nfs/redis-cluster2
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv3
labels:
pv: nfs-pv3
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 192.168.11.242
path: /root/nfs/redis-cluster3
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv4
labels:
pv: nfs-pv4
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 192.168.11.242
path: /root/nfs/redis-cluster4
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv5
labels:
pv: nfs-pv5
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 192.168.11.242
path: /root/nfs/redis-cluster5
3、应用 StatefulSet 创立 redis-cluster 集群节点和 headless service
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: redis-cluster
name: redis-cluster
namespace: default
spec:
replicas: 6
selector:
matchLabels:
app: redis-cluster
serviceName: redis-cluster
template:
metadata:
labels:
app: redis-cluster
spec:
containers:
- command:
["/bin/bash", "/usr/local/etc/redis/update-node.sh", "redis-server", "/usr/local/etc/redis/redis.conf"]
#args:
# - /usr/local/etc/redis/redis.conf
# - --cluster-announce-ip
# - "$(MY_POD_IP)"
env:
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: TZ
value: Asia/Shanghai
image: 'redis:6.0.10'
imagePullPolicy: IfNotPresent
name: redis
ports:
- containerPort: 7001
hostPort: 7001
name: redis-port
protocol: TCP
volumeMounts:
- mountPath: /data
name: redis-cluster-data
subPath: data
readOnly: false
- mountPath: /usr/local/etc/redis
name: redis-config
readOnly: false
dnsPolicy: ClusterFirst
volumes:
- name: redis-config
configMap:
name: redis-config
volumeClaimTemplates: #PVC 模板
- metadata:
name: redis-cluster-data
namespace: default
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
labels:
app: redis-cluster
name: redis-cluster
namespace: default
spec:
ports:
- name: redis-port
port: 7001
protocol: TCP
targetPort: 7001
selector:
app: redis-cluster
type: ClusterIP
clusterIP: None
阐明 2 个点:第一,update-node.sh 脚本须要加上 bash 环境变量,否则脚本启动执行时提醒没有权限,这也是网上很多文章并没有提到的;
第二,env 环境变量中加了 2 个,${MY_POD_IP}是节点重启时更新 pod 的 ip 地址,TZ 就是时区更改;
4、初始化集群
redis-cluster 从 4.0 开始反对命令行间接初始化,不再须要装置 ruby 了。
kubectl exec -it redis-cluster-0 -- redis-cli -p 7001 --cluster create --cluster-replicas 1 $(kubectl get pods -l k8s.kuboard.cn/name=redis-cluster -o jsonpath='{range.items[*]}{.status.podIP}:7001')
5、验证集群
kubectl exec -it redis-cluster-0 -- redis-cli cluster info
redis-cluster 集群部署结束。
踩坑总结
问题 1,集群初始化时,始终期待 Waiting for the cluster to join
解决:最开始部署时,从应用 docker-comopose 部署的办法套用过去,因为 redis.conf 配置文件中参数 cluster-announce-ip 配置了宿主机的 ip,当初始化时集群节点之间须要通信,然而再 k8s 中宿主机 ip 曾经不实用,导致无奈通信统一卡住在那个地位。
禁用 #cluster-announce-ip
问题 2,集群创立时,[ERR] Node 10.244.7.224:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
解决:因为后面初始化集群时卡住,导致局部节点的 nodes.conf 文件中更新了新节点数据,须要删除数据。能够删除文件,也能够通过如下命令
redis-cli -p 7001 -c 登录每个 redis 节点重置:
flushdb
cluster reset
问题 3,pvc 如何和 pv 一对一绑定?
阐明:分动态和动静绑定
首先动态,之前始终没想明确,写好了 pv 的 yaml 文件,service 外面定义好 pvc 之后,如何让 pv 和 pvc 进行绑定?只有咱们定义的 pv 存储空间大小和 pvc 申请大小统一就会匹配绑定 bound, 当然也能够通过 lebel 标签来关联 pvc 到特定的 pv。
另外,redis 集群多个节点,长久化存储目录必定不能一样,如果 yaml 中间接指定 PVC 的名字,只能指定一个名字,这样是办不到关联到多个不同的 PV,于是须要 volumeClaimTemplates(PVC 模板)。
volumeClaimTemplates:
- metadata:
name: redis-cluster-data
namespace: default
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 1Gi
动静,因为 NFS 不反对动静存储,所以咱们须要借用这个存储插件 StorageClass, 关联 pvc, 动态创建 pv。分 3 个步骤,1,定义 storage;2,部署受权,因为 storage 主动创立 pv 须要通过 kube-apiserver, 所以要进行受权;3,部署主动创立 pv 的服务 nfs-client-provisioner;4,部署 redis 服务。
参考链接地址:
https://blog.csdn.net/qq_2561…
以上动态创建 pv 的确是个好方法,后续有工夫再实际操作下。
当然,如果嫌麻烦举荐应用 kuboard,手动点点体验也很不错,齐全不必本人这么麻烦了哈。
问题 4,测试一个节点重启,发现节点重启后,nodes.conf 中本人的 pod ip 不会更新,倒是其余节点之间通信会更新 pod ip。
解决:下面也提到过,增加一个启动脚本 update-node.sh,每次启动查找 podIP 后替换 nodes.conf 文件中 myself 节点的 ip 地址就能够解决。留神,网上很多都是通过容器启动时在参数 args 外面增加 pod ip 来更新,但我实际过并不行,他们说 5.0 能够,然而我换 5.0 也试过并不行。如果有能够的请留言,也有可能是我配置写的不对吧。
最初,以上内容尽管不多,但相对本人手敲的,心愿能分享给大家,这也是年前的最初一篇文章,欢送留言。