概要
前回 k8s 上に Redis Sentinel 環境を構築するところまでやってみました
今回は Redis Cluster に挑戦したいと思います
StatefulSet と ConfigMap を使って構築しています
環境
- macOS 10.14.5
- minikube v0.28.2
- Redis 5.0.5
ConfigMap
vim redis_cluster_configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-cluster
data:
redis.conf: |+
port 6379
cluster-enabled yes
cluster-config-file /data/nodes.conf
cluster-node-timeout 5000
appendonly yes
kubectl apply -f redis_cluster_configmap.yml
StatefulSet
vim redis_cluster_sts.yml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-cluster
spec:
selector:
matchLabels:
app: redis
serviceName: "redis"
replicas: 6
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis
command: ["redis-server", "/conf/redis.conf"]
ports:
- containerPort: 6379
name: client
- containerPort: 16379
name: gossip
volumeMounts:
- name: data
mountPath: /data
- name: conf
mountPath: /conf
volumes:
- name: conf
configMap:
name: redis-cluster
defaultMode: 0755
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
kubectl apply -f redis_cluster_sts.yml
kubectl exec redis-cluster-0 redis-cli info cluster
# Cluster
cluster_enabled:1
Headless Service
あとからわかったのですが redis-cli --cluster create
はホスト名では使えないようです
なので Headless Service のデプロイは不要です
vim redis_cluster_service.yml
apiVersion: v1
kind: Service
metadata:
name: redis
labels:
app: redis
spec:
ports:
- port: 6379
name: client
- port: 16379
name: gossip
clusterIP: None
selector:
app: redis
kubectl apply -f redis_cluster_service.yml
kubectl run -i --tty --image busybox:1.28 dns-test --restart=Never --rm
/ # nslookup redis-cluster-0.redis
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: redis-cluster-0.redis
Address 1: 172.17.0.7 redis-cluster-0.redis.default.svc.cluster.local
クラスタ作成
kubectl exec -it redis-cluster-0 -- \
redis-cli --cluster create \
172.17.0.7:6379 \
172.17.0.8:6379 \
172.17.0.9:6379 \
172.17.0.10:6379 \
172.17.0.11:6379 \
172.17.0.12:6379 \
--cluster-replicas 1
kubectl exec redis-cluster-0 -- redis-cli --cluster info 172.17.0.7:6379
172.17.0.7:6379 (922c7825...) -> 0 keys | 5461 slots | 1 slaves.
172.17.0.9:6379 (189ed07f...) -> 0 keys | 5461 slots | 1 slaves.
172.17.0.8:6379 (a7d9f418...) -> 0 keys | 5462 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
kubectl exec redis-cluster-0 -- redis-cli cluster nodes
189ed07f5f7d736d623e5da3b384193ac620f777 172.17.0.9:6379@16379 master - 0 1559107652051 3 connected 10923-16383
a7d9f418035595e68231b2baf079c65064a43a96 172.17.0.8:6379@16379 master - 0 1559107651000 2 connected 5461-10922
922c7825f518a6af2d29ce934c09f43d72f97951 172.17.0.7:6379@16379 myself,master - 0 1559107650000 1 connected 0-5460
8c6c41a4179261abad6f521ce0e21a6c05aed317 172.17.0.10:6379@16379 slave 189ed07f5f7d736d623e5da3b384193ac620f777 0 1559107651347 4 connected
7534abbae8a6ffe4183eb45b294507e19fed5516 172.17.0.11:6379@16379 slave 922c7825f518a6af2d29ce934c09f43d72f97951 0 1559107651548 5 connected
a000022e75dbbeaadecd48b21c2a9322bad73c28 172.17.0.12:6379@16379 slave a7d9f418035595e68231b2baf079c65064a43a96 0 1559107651000 6 connected
failover 動作確認
kubectl delete po redis-cluster-0
kubectl exec redis-cluster-1 -- redis-cli --cluster info 172.17.0.8:6379
172.17.0.9:6379 (189ed07f...) -> 0 keys | 5461 slots | 1 slaves.
172.17.0.11:6379 (7534abba...) -> 0 keys | 5461 slots | 1 slaves.
172.17.0.8:6379 (a7d9f418...) -> 0 keys | 5462 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
kubectl exec redis-cluster-1 -- redis-cli cluster nodes
a000022e75dbbeaadecd48b21c2a9322bad73c28 172.17.0.12:6379@16379 slave a7d9f418035595e68231b2baf079c65064a43a96 0 1559107872000 6 connected
8c6c41a4179261abad6f521ce0e21a6c05aed317 172.17.0.10:6379@16379 slave 189ed07f5f7d736d623e5da3b384193ac620f777 0 1559107873547 4 connected
189ed07f5f7d736d623e5da3b384193ac620f777 172.17.0.9:6379@16379 master - 0 1559107872541 3 connected 10923-16383
922c7825f518a6af2d29ce934c09f43d72f97951 172.17.0.7:6379@16379 slave 7534abbae8a6ffe4183eb45b294507e19fed5516 0 1559107873000 7 connected
a7d9f418035595e68231b2baf079c65064a43a96 172.17.0.8:6379@16379 myself,master - 0 1559107871000 2 connected 5461-10922
7534abbae8a6ffe4183eb45b294507e19fed5516 172.17.0.11:6379@16379 master - 0 1559107872843 7 connected 0-5460
ノード追加
vim redis_cluster_sts.yml
replicas: 6
-> replicas: 8
kubectl apply -f redis_cluster_sts.yml
kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE
redis-cluster-0 1/1 Running 0 36m 172.17.0.7 minikube
redis-cluster-1 1/1 Running 0 1h 172.17.0.8 minikube
redis-cluster-2 1/1 Running 0 1h 172.17.0.9 minikube
redis-cluster-3 1/1 Running 0 1h 172.17.0.10 minikube
redis-cluster-4 1/1 Running 0 1h 172.17.0.11 minikube
redis-cluster-5 1/1 Running 0 1h 172.17.0.12 minikube
redis-cluster-6 1/1 Running 0 31m 172.17.0.13 minikube
redis-cluster-7 1/1 Running 0 1m 172.17.0.14 minikube
kubectl exec -it redis-cluster-1 -- redis-cli --cluster add-node 172.17.0.13:6379 172.17.0.8:6379
=> cdea61f96f575df26eb4828dfa5ab937a3f9f27f
kubectl exec -it redis-cluster-1 -- redis-cli --cluster add-node 172.17.0.14:6379 172.17.0.8:6379 --cluster-slave --cluster-master-id cdea61f96f575df26eb4828dfa5ab937a3f9f27f
=> 040da0752197c7bf366f398df1653927f4ff1bef
kubectl exec redis-cluster-1 -- redis-cli --cluster info 172.17.0.8:6379
172.17.0.9:6379 (189ed07f...) -> 0 keys | 5461 slots | 1 slaves.
172.17.0.11:6379 (7534abba...) -> 0 keys | 5461 slots | 1 slaves.
172.17.0.8:6379 (a7d9f418...) -> 0 keys | 5462 slots | 1 slaves.
172.17.0.13:6379 (cdea61f9...) -> 0 keys | 0 slots | 1 slaves.
[OK] 0 keys in 4 masters.
0.00 keys per slot on average.
reshared
kubectl exec -it redis-cluster-1 -- redis-cli --cluster reshard 172.17.0.8:6379
インタラクティブモードになるので以下の順番で入力します
- 4096
- cdea61f96f575df26eb4828dfa5ab937a3f9f27f
- all
- yes
スロットが正常に reshard されているか確認します
kubectl exec redis-cluster-1 -- redis-cli --cluster info 172.17.0.8:6379
172.17.0.8:6379 (a7d9f418...) -> 0 keys | 4096 slots | 1 slaves.
172.17.0.13:6379 (cdea61f9...) -> 0 keys | 4096 slots | 1 slaves.
172.17.0.9:6379 (189ed07f...) -> 0 keys | 4096 slots | 1 slaves.
172.17.0.11:6379 (7534abba...) -> 0 keys | 4096 slots | 1 slaves.
[OK] 0 keys in 4 masters.
0.00 keys per slot on average.
ノード削除
kubectl exec -it redis-cluster-1 -- redis-cli --cluster reshard 172.17.0.8:6379
インタラクティブモードになるので以下の順番で入力します
- 4096
- a7d9f418035595e68231b2baf079c65064a43a96
- cdea61f96f575df26eb4828dfa5ab937a3f9f27f
- done
- yes
reshard 後削除します
kubectl exec -it redis-cluster-1 -- redis-cli --cluster del-node 172.17.0.13:6379 cdea61f96f575df26eb4828dfa5ab937a3f9f27f
kubectl exec redis-cluster-1 -- redis-cli --cluster info 172.17.0.8:6379
172.17.0.8:6379 (a7d9f418...) -> 0 keys | 8192 slots | 2 slaves.
172.17.0.9:6379 (189ed07f...) -> 0 keys | 4096 slots | 1 slaves.
172.17.0.11:6379 (7534abba...) -> 0 keys | 4096 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
kubectl exec -it redis-cluster-1 -- redis-cli --cluster del-node 172.17.0.14:6379 040da0752197c7bf366f398df1653927f4ff1bef
rebalance
kubectl exec -it redis-cluster-1 -- redis-cli --cluster rebalance 172.17.0.8:6379
kubectl exec redis-cluster-1 -- redis-cli --cluster info 172.17.0.8:6379
172.17.0.8:6379 (a7d9f418...) -> 0 keys | 5462 slots | 1 slaves.
172.17.0.9:6379 (189ed07f...) -> 0 keys | 5461 slots | 1 slaves.
172.17.0.11:6379 (7534abba...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
Tips
一度削除したノードがある場合は Pods の他に PersistentVolume も削除しないと前の nodes.conf が残っているため再度 add-node
できません
[ERR] Node 172.17.0.13:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
一度 StatefulSet でスケールダウンさせ PersistentVolume を削除するか Pod からアンマウントして PersistentVolume を削除してからスケールアウトして新規で Pod を作成する必要がある
もしくは強制的に pvc -> pv -> pod を削除します
kubectl delete pvc data-redis-cluster-6
kubectl delete pv pvc-2b491981-81d3-11e9-b396-08002719d78a
kubectl delete po redis-cluster-6
で再度 add-node できます
あとしまつ
kubectl delete sts redis-cluster
for i in {0..7}; do kubectl delete pvc data-redis-cluster-$i; done
kubectl delete svc redis
最後に
k8s 上で StatefulSet を使って RedisCluster を構築してみました
Headless Service が使えないので、正直 StatefulSet である必要はないかもしれませんが公式の使用パターンでも推奨しているので特に理由がなければ StatefulSet でいいかなと思います
それよりも Redis Cluster でノードを追加するときにホスト名ベースで追加できるように対応してほしいなと感じました
そうすれば Headless Service が使えるのでもっとキレイにできるようになると思います
0 件のコメント:
コメントを投稿