Redis的分布式模式有主從模式、哨兵模式和Cluster模式酪耳,相對(duì)來(lái)說(shuō)Cluster模式的機(jī)制更完善铡恕,內(nèi)存利用率更高。因?yàn)轫?xiàng)目在使用Redis進(jìn)行存儲(chǔ)時(shí)碰到了性能瓶頸脏答,所以準(zhǔn)備用Cluster模式嘗試部署分布式Redis糕殉。
ps:Redis分布式的介紹可以參考https://segmentfault.com/a/1190000022808576
一、配置文件
先配置一個(gè)ConfigMap殖告,后面會(huì)掛載到Redis的實(shí)例上阿蝶,里面有一個(gè)腳本和一個(gè)redis的配置文件,redis配置文件可以根據(jù)需求修改黄绩,腳本的作用后面會(huì)講羡洁。
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
二、啟動(dòng)節(jié)點(diǎn)
這里使用StatefulSet作為工作負(fù)載爽丹,因?yàn)閞edis集群的節(jié)點(diǎn)是有狀態(tài)的筑煮,這個(gè)狀態(tài)會(huì)記錄在之前配置指定的/data/nodes.conf文件里辛蚊,節(jié)點(diǎn)重啟后會(huì)根據(jù)這個(gè)文件的內(nèi)容恢復(fù)節(jié)點(diǎn)在集群里的狀態(tài),所以需要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
三袋马、創(chuàng)建集群
加載上面兩個(gè)配置文件后執(zhí)行:
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}')
這樣就創(chuàng)建好了redis集群,redis-server會(huì)寫(xiě)入/data/nodes.conf文件秸应,記錄集群狀態(tài)虑凛。因?yàn)樵趧?chuàng)建集群的時(shí)候是使用固定ip創(chuàng)建的,當(dāng)節(jié)點(diǎn)重啟后ip會(huì)發(fā)生變化灸眼,這個(gè)文件的信息就不準(zhǔn)確了卧檐,所以需要在啟動(dòng)時(shí)更新/data/nodes.conf。這個(gè)就是fix-ip.sh這個(gè)腳本的工作焰宣,如果文件存在霉囚,就更新ip,如果不存在就創(chuàng)建文件匕积。所以k8s的容器配置里有兩個(gè)點(diǎn)和單機(jī)不一樣:一個(gè)是command里使用"/conf/fix-ip.sh"作為啟動(dòng)項(xiàng)盈罐,先更新ip再啟動(dòng)實(shí)例;一個(gè)是加載pod ip到環(huán)境變量POD_IP闪唆,方便腳本加載盅粪。
四、創(chuàng)建service
創(chuàng)建好redis集群后還需要訪問(wèn)接口
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
五悄蕾、坑
一開(kāi)始是想用service的域名創(chuàng)建redis集群的票顾,這樣節(jié)點(diǎn)重啟后就不需要更新ip,但是redis不支持使用域名帆调,所以只能繞了一圈又回到固定ip的方法奠骄,和容器環(huán)境很不協(xié)調(diào)。