目錄:(1).redis容器化
1.容器化redis-cluster各個節點例項
2.初始化redis-cluster叢集
3.叢集節點檔案說明
3.1.appendonly.aof
3.2.dump.rdb
3.3.PDB和AOF的優先順序
3.4.nodes.conf
(2).容器重啟導致節點ip變化的問題解決2.1.相關配置方式
2.2.整個操作過程演示
2.3.應用如何適配
(3).配置檔案說明(4).相關文章閱讀筆者使用Redis容器化只用與本地環境,用於自己一些專案的除錯(https://github.com/hepyu/saf)。
故,是一個簡單實現,pod親和性等生產級別配置沒有做過多考慮。
(1).redis容器化1.容器化redis-cluster各個節點例項
先執行local pv所使用的本地pv目錄:
https://github.com/hepyu/k8s-app-config/blob/master/yaml/init.sh
yaml配置檔案位於:
https://github.com/hepyu/k8s-app-config/tree/master/yaml/min-cluster-allinone/redis-cluster-min
執行命令容器化redis-cluster:sh ./deploy.sh
檢視redis容器化節點例項
kubectl get all -n redis-cluster-min -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESpod/redis-hkc-0 1/1 Running 0 8d 10.244.0.108 future <none> <none>pod/redis-hkc-1 1/1 Running 0 8d 10.244.0.109 future <none> <none>pod/redis-hkc-2 1/1 Running 0 8d 10.244.0.110 future <none> <none>pod/redis-hkc-3 1/1 Running 0 8d 10.244.0.111 future <none> <none>pod/redis-hkc-4 1/1 Running 0 8d 10.244.0.112 future <none> <none>pod/redis-hkc-5 1/1 Running 0 8d 10.244.0.113 future <none> <none>
接下來我們要做redis叢集初始化,如果我們現在進入redis操作會出現什麼情況呢?
我們進入其中的一個redis node中執行set, get嘗試操作,會提示錯誤:
root@redis-hkc-0:/data# redis-cli -h 10.244.0.111 -p 9720 -c
10.244.0.111:9720>10.244.0.111:9720> cluster infocluster_state:failcluster_slots_assigned:16384cluster_slots_ok:5461cluster_slots_pfail:10923cluster_slots_fail:0cluster_known_nodes:6cluster_size:3cluster_current_epoch:6cluster_my_epoch:3cluster_stats_messages_ping_sent:1154655cluster_stats_messages_sent:1154655cluster_stats_messages_received:010.244.0.111:9720>10.244.0.111:9720>10.244.0.111:9720>10.244.0.111:9720> set a 1(error) CLUSTERDOWN The cluster is down
可以看到cluster info是可以顯示cluster的資訊,但是執行set/get方法時提示cluster down,這是因為我們沒有完成redis-cluster的初始化。
2.初始化redis-cluster叢集
我們再開一個容器進行此項操作,為此我專門製作了一個image專門用於進行redis-cluster初始化,工程位於:
https://github.com/hepyu/redis-cluster-initialize-image
(需要注意,我用的redis版本是5.x)。
git clone 後直接執行docker.build.sh完成image製作。
執行命令進入容器
kubectl run -i --tty init-redis-cluster --image=hpy253215039/redis-cluster-initialize-image:0.1 --restart=Never /bin/bash
(第二次進入執行:kubectl exec -it init-redis-cluster -- /bin/bash)
進入容器後,cd /app/3rd/redis-5.0.7/src,執行:
Redis-5.0已經捨棄了redis-trib.py的方式初始化叢集,改用redis-cli初始化叢集:
redis-cli --cluster create --cluster-replicas 1 10.244.0.173:9720 10.244.0.109:9720 10.244.0.110:9720 10.244.0.111:9720 10.244.0.112:9720 10.244.0.113:9720
有可能會報錯:
Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
解決方式:
3)、再次新增新節點如果還是報錯,則登入新Node,./redis-cli–h x –p對資料庫進行清除:
Ip:7001> flushdb #清空當前資料庫
redis-cli --cluster create --cluster-replicas 1 10.244.0.184:9720 10.244.0.185:9720 10.244.0.186:9720 10.244.0.187:9720 10.244.0.188:9720 10.244.0.189:9720
可以發現IP發生變化,列印資訊:
>>> Performing hash slots allocation on 6 nodes...Master[0] -> Slots 0 - 5460Master[1] -> Slots 5461 - 10922Master[2] -> Slots 10923 - 16383Adding replica 10.244.0.188:9720 to 10.244.0.184:9720Adding replica 10.244.0.189:9720 to 10.244.0.185:9720Adding replica 10.244.0.187:9720 to 10.244.0.186:9720M: f8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.184:9720slots:[0-5460] (5461 slots) masterM: 150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720slots:[5461-10922] (5462 slots) masterM: a44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720slots:[10923-16383] (5461 slots) masterS: 3f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.187:9720replicates a44ee1eaef7f89cd1013f10638d5d878dd982001S: 699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720replicates f8b4cc1d884eb3ced239c572e016a49cabd0313fS: 3df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720replicates 150da7a79af740c55a61124f1d422fb9fcd19459Can I set the above configuration? (type 'yes' to accept): yes>>> Nodes configuration updated>>> Assign a different config epoch to each node>>> Sending CLUSTER MEET messages to join the clusterWaiting for the cluster to join......>>> Performing Cluster Check (using node 10.244.0.184:9720)M: f8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.184:9720slots:[0-5460] (5461 slots) master1 additional replica(s)S: 3df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720slots: (0 slots) slavereplicates 150da7a79af740c55a61124f1d422fb9fcd19459S: 699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720slots: (0 slots) slavereplicates f8b4cc1d884eb3ced239c572e016a49cabd0313fM: 150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720slots:[5461-10922] (5462 slots) master1 additional replica(s)S: 3f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.187:9720slots: (0 slots) slavereplicates a44ee1eaef7f89cd1013f10638d5d878dd982001M: a44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720slots:[10923-16383] (5461 slots) master1 additional replica(s)[OK] All nodes agree about slots configuration.>>> Check for open slots...>>> Check slots coverage...[OK] All 16384 slots covered.
我們使用命令列進入其中的一個節點:
[root@init-redis-cluster redis-5.0.7]# redis-cli -c -h 10.244.0.184 -p 9720
10.244.0.184:9720> get a 1(error) ERR wrong number of arguments for 'get' command10.244.0.184:9720> cluster infocluster_state:okcluster_slots_assigned:16384cluster_slots_ok:16384cluster_slots_pfail:0cluster_slots_fail:0cluster_known_nodes:6cluster_size:3cluster_current_epoch:6cluster_my_epoch:1cluster_stats_messages_ping_sent:160cluster_stats_messages_pong_sent:150cluster_stats_messages_sent:310cluster_stats_messages_ping_received:145cluster_stats_messages_pong_received:160cluster_stats_messages_meet_received:5cluster_stats_messages_received:31010.244.0.184:9720>10.244.0.184:9720>10.244.0.184:9720> set a 1-> Redirected to slot [15495] located at 10.244.0.186:9720OK10.244.0.186:9720> get a"1"10.244.0.186:9720>
可以看到,叢集現在處於可用狀態。
3.叢集節點檔案說明
我們隨意找一個本地儲存:/datavip/k8s-data/redis-cluster-min-pv-local-0,其目錄結構如下:
appendonly.aof
dump.rdb
nodes.conf
3.1.appendonly.aof
以日誌的形式來記錄每個寫操作,將redis執行過的所有寫指令記錄下來(讀操作不記錄),只許追加檔案但不可以改寫檔案,redis啟動之初會讀取該檔案重新構建資料,換言之,redis重啟的話就根據日誌檔案的內容將寫指令從前到後執行一次以完成資料的恢復工作。
這也是為什麼我們在使用redis時會有一些禁手,比如:不允許用keys等操作,因為其執行時間的方差差異太大,有可能直接把整個叢集堵死。筆者曾經工作的一家公司,有同學用keys,直接把redis-cluster生產叢集的tps幹到<1。
3.2.dump.rdb
指在指定的時間間隔內將記憶體中的資料集快照寫入磁碟,實際的操作過程是fork一個子程序,先將資料集寫入臨時檔案,寫入成功後,再替換之前的檔案,用二進位制壓縮儲存(binlog)。儲存的檔案為:dum.rdb
RDB需要fork子程序來進行持久化。如果資料集太大,fork系統呼叫可能消耗較多時間,甚至導致redis暫停服務( n ms-1s)。AOF也需要fork,但是你可以在不影響永續性的前提下控制多久重寫一次日誌。
3.3.PDB和AOF的優先順序
Redis 4.0 之後新增的方式,混合持久化(同時開啟RDB和AOF模式),是結合了 RDB 和 AOF 的優點,在寫入的時候,先把當前的資料以 RDB 的形式寫入檔案的開頭,再將後續的操作命令以 AOF 的格式存入檔案,這樣既能保證 Redis 重啟時的速度,又能簡單資料丟失的風險。
我們線上是兩個都開著。
3.4.nodes.conf
查閱其內容便一目了然:
記錄叢集內的其他節點資訊,用於通訊。
例:
3f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.187:9720@19720 slave a44ee1eaef7f89cd1013f10638d5d878dd982001 0 1574686485562 4 connected150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720@19720 myself,master - 0 1574686485000 2 connected 5461-10922f8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.184:9720@19720 master - 0 1574686484000 1 connected 0-5460a44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720@19720 master - 0 1574686486000 3 connected 10923-16383699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720@19720 slave f8b4cc1d884eb3ced239c572e016a49cabd0313f 0 1574686486563 5 connected3df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720@19720 slave 150da7a79af740c55a61124f1d422fb9fcd19459 0 1574686484560 6 connectedvars currentEpoch 6 lastVoteEpoch 0
第一個欄位是節點 ID,一個40個字元的隨機字串,當一個節點被建立時不會再發生變化(除非CLUSTER RESET HARD被使用),所以當pod重啟前我們只要nodeId對應的ip:port改掉即可,就可以保證叢集的正常使用。
(2).容器重啟導致節點ip變化的問題解決
2.1.相關配置方式
在redis-configmap.yaml中有這麼一段指令碼:fix-ip.sh: |#!/bin/shCLUSTER_CONFIG="/data/nodes.conf"if [ -f ${CLUSTER_CONFIG} ]; thenif [ -z "${POD_IP}" ]; thenecho "Unable to determine Pod IP address!"exit 1fiecho "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} #改nodes.conf中本機的ip地址,因為pod每次重啟後會導致ip改變。fiexec "$@"
這個指令碼在容器啟動後執行,修改當前redis節點例項的nodes.conf,將本機例項的node編號對應的ip換成新的podIP。由於nodes.conf是由redis-cluster叢集維護,所以當這個節點例項啟動時,redis-cluster也會將nodes.conf的本地修改同步到當前叢集內的其他redis節點的nodes.conf檔案,會有一個sync操作。
在redis-statefulset.yaml中的啟動命令:
command: ["/conf/fix-ip.sh", "redis-server", "/conf/redis.conf"]
先執行fix-ip.sh修改nodes.conf,然後再啟動redis-server,這樣才能保證redis-cluster將nodes.conf的更改同步到其他節點例項。
2.2.整個操作過程演示
叢集最初IP:
[root@future redis-cluster-min]# kubectl get pod -n redis-cluster-min -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESredis-hkc-0 1/1 Running 0 38h 10.244.0.192 future <none> <none>redis-hkc-1 1/1 Running 0 39h 10.244.0.185 future <none> <none>redis-hkc-2 1/1 Running 0 39h 10.244.0.186 future <none> <none>redis-hkc-3 1/1 Running 0 39h 10.244.0.187 future <none> <none>redis-hkc-4 1/1 Running 0 39h 10.244.0.188 future <none> <none>redis-hkc-5 1/1 Running 0 39h 10.244.0.189 future <none> <none>
我們接下來選擇redis-hkc-3重啟,然後觀察其nodes.conf檔案變化,重啟前,我們先進入redis-hkc-3檢視一下這個例項的nodes.conf中hkc-3的node標識:
[root@future redis-cluster-min]# kubectl exec -it -n redis-cluster-min redis-hkc-3 -- /bin/bash
root@redis-hkc-3:/data# cat nodes.conf
a44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720@19720 master - 0 1574688847000 3 connected 10923-16383f8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.192:9720@19720 master - 1574688835599 1574688833292 1 disconnected 0-5460699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720@19720 slave f8b4cc1d884eb3ced239c572e016a49cabd0313f 0 1574688844318 5 connected150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720@19720 master - 0 1574688847000 2 connected 5461-109223df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720@19720 slave 150da7a79af740c55a61124f1d422fb9fcd19459 0 1574688845000 6 connected3f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.187:9720@19720 myself,slave a44ee1eaef7f89cd1013f10638d5d878dd982001 0 1574688844000 4 connectedvars currentEpoch 6 lastVoteEpoch 0
我們再進入redis-hkc-4,看一下redis-hkc-3節點的Node標識在redis-hkc-4的nodes.conf中的配置:
[root@future redis-cluster-min]# kubectl exec -it -n redis-cluster-min redis-hkc-4 -- /bin/bash
root@redis-hkc-4:/data# cat nodes.conf
3df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720@19720 slave 150da7a79af740c55a61124f1d422fb9fcd19459 0 1574688845431 6 connected150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720@19720 master - 0 1574688846433 2 connected 5461-109223f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.187:9720@19720 slave a44ee1eaef7f89cd1013f10638d5d878dd982001 0 1574688847000 4 connectedf8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.192:9720@19720 master - 1574688835609 1574688834406 1 disconnected 0-5460699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720@19720 myself,slave f8b4cc1d884eb3ced239c572e016a49cabd0313f 0 1574688847000 5 connecteda44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720@19720 master - 0 1574688846000 3 connected 10923-16383vars currentEpoch 6 lastVoteEpoch 0
OK,現在我們殺掉redis-hkc-3這個pod:
kubectl delete -n redis-cluster-min pod redis-hkc-3
然後檢視新POD,發現redis-hkc-3的ip變成10.244.0.194:
[root@future redis-cluster-min]# kubectl get pod -n redis-cluster-min -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESredis-hkc-0 1/1 Running 0 40h 10.244.0.192 future <none> <none>redis-hkc-1 1/1 Running 0 41h 10.244.0.185 future <none> <none>redis-hkc-2 1/1 Running 0 41h 10.244.0.186 future <none> <none>redis-hkc-3 1/1 Running 0 12s 10.244.0.194 future <none> <none>redis-hkc-4 1/1 Running 0 41h 10.244.0.188 future <none> <none>redis-hkc-5 1/1 Running 0 41h 10.244.0.189 future <none> <none>
檢視redis-hkc-3的nodes.conf,可以看到對應的ip被自動修改為新IP:10.244.0.194:
[root@future redis-cluster-min]# kubectl exec -it -n redis-cluster-min redis-hkc-3 -- /bin/bash
root@redis-hkc-3:/data# cat nodes.conf
a44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720@19720 master - 0 1574688847000 3 connected 10923-16383f8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.192:9720@19720 master - 1574688835599 1574688833292 1 disconnected 0-5460699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720@19720 slave f8b4cc1d884eb3ced239c572e016a49cabd0313f 0 1574688844318 5 connected150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720@19720 master - 0 1574688847000 2 connected 5461-109223df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720@19720 slave 150da7a79af740c55a61124f1d422fb9fcd19459 0 1574688845000 6 connected3f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.194:9720@19720 myself,slave a44ee1eaef7f89cd1013f10638d5d878dd982001 0 1574688844000 4 connectedvars currentEpoch 6 lastVoteEpoch 0
檢視redis-hkc-4的nodes.conf,可以看到redis-hkc-3節點對應的ip被自動修改為新IP:10.244.0.194,說明redis-hkc-3啟動是,redis-cluster叢集將redis-hkc-3的nodes.conf變更同步到了叢集的其他節點:
[root@future redis-cluster-min]# kubectl exec -it -n redis-cluster-min redis-hkc-4 -- /bin/bash
root@redis-hkc-4:/data# cat nodes.conf
3df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720@19720 slave 150da7a79af740c55a61124f1d422fb9fcd19459 0 1574834074462 6 connected150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720@19720 master - 0 1574834075000 2 connected 5461-109223f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.194:9720@19720 slave a44ee1eaef7f89cd1013f10638d5d878dd982001 1574834069654 1574834068000 4 disconnectedf8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.192:9720@19720 master - 0 1574834077000 1 connected 0-5460699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720@19720 myself,slave f8b4cc1d884eb3ced239c572e016a49cabd0313f 0 1574834077000 5 connecteda44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720@19720 master - 0 1574834077469 3 connected 10923-16383vars currentEpoch 6 lastVoteEpoch 0
2.3.應用如何適配
要求應用程式初始化redis-cluster時,address中不能使用ip,要換成域名。這樣即使POD重啟IP反生變化,也不會波及到應用程式(其實在重啟POD的過程中,對應用會有短時間影響)。
如,在本例配置下:
redis.cluster.address=redis-hkc-0.redis-hkc.redis-cluster-min.svc.cluster.local:9720,redis-hkc-1.redis-hkc.redis-cluster-min.svc.cluster.local:9720,redis-hkc-2.redis-hkc.redis-cluster-min.svc.cluster.local:9720,redis-hkc-3.redis-hkc.redis-cluster-min.svc.cluster.local:9720,redis-hkc-4.redis-hkc.redis-cluster-min.svc.cluster.local:9720,redis-hkc-5.redis-hkc.redis-cluster-min.svc.cluster.local:9720
(3).配置檔案說明
4個配置檔案:
redis-configmap.yaml
redis-pv-local.yaml
redis-service.yaml
redis-statefulset.yaml
1.redis-configmap.yaml
主要放置fix-ip指令碼(POD重啟前修改nodes.conf)和redis.conf配置檔案。
2.redis-pv-local.yaml
本地儲存,生產雲環境使用NAS雲盤(要做充分效能/壓力測試)。
3.redis-service.yaml
headless service。
這裡的Headless Services主要是使用它作為標識每個redis-node的域名,這樣應用程式直接配置6個域名和埠即可,不需要使用ip,其格式為:
$(podname).(headless server name).namespace.svc.cluster.local
即:
redis-hkc-0.redis-hkc.redis-cluster-min.svc.cluster.local:9720,其始終執行有狀態下編號為1的pod,達到與PodIP的無關性。
4.redis-statefulset.yaml
主要配置檔案,用於定義有狀態容器:redis-cluster。
關鍵配置:
command: ["/conf/fix-ip.sh", "redis-server", "/conf/redis.conf"]
(4).相關文章閱讀