kubernetes-20:redis-cluster容器化

目錄:

(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


<code>NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES

pod/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>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<code>


接下來我們要做redis集群初始化,如果我們現在進入redis操作會出現什麼情況呢?

我們進入其中的一個redis node中執行set, get嘗試操作,會提示錯誤:

root@redis-hkc-0:/data# redis-cli -h 10.244.0.111 -p 9720 -c


<code>10.244.0.111:9720>

10.244.0.111:9720> cluster info

cluster_state:fail

cluster_slots_assigned:16384

cluster_slots_ok:5461


cluster_slots_pfail:10923

cluster_slots_fail:0

cluster_known_nodes:6

cluster_size:3

cluster_current_epoch:6

cluster_my_epoch:3

cluster_stats_messages_ping_sent:1154655

cluster_stats_messages_sent:1154655

cluster_stats_messages_received:0

10.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/<code>


可以看到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.

解決方式:

1)、將需要新增的節點下aof、rdb等本地備份文件刪除;

2)、同時將新Node的集群配置文件刪除,即:刪除你redis.conf裡面cluster-config-file所在的文件;

3)、再次添加新節點如果還是報錯,則登錄新Node,./redis-cli–h x –p對數據庫進行清除:

Ip:7001> flushdb #清空當前數據庫


我圖省事(自己用嘛),直接刪除local pv重建目錄,重新容器化。

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發生變化,打印信息:

<code>>>> Performing hash slots allocation on 6 nodes...

Master[0] -> Slots 0 - 5460

Master[1] -> Slots 5461 - 10922

Master[2] -> Slots 10923 - 16383

Adding replica 10.244.0.188:9720 to 10.244.0.184:9720

Adding replica 10.244.0.189:9720 to 10.244.0.185:9720

Adding replica 10.244.0.187:9720 to 10.244.0.186:9720

M: f8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.184:9720

slots:[0-5460] (5461 slots) master

M: 150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720

slots:[5461-10922] (5462 slots) master

M: a44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720

slots:[10923-16383] (5461 slots) master

S: 3f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.187:9720

replicates a44ee1eaef7f89cd1013f10638d5d878dd982001


S: 699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720

replicates f8b4cc1d884eb3ced239c572e016a49cabd0313f

S: 3df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720

replicates 150da7a79af740c55a61124f1d422fb9fcd19459

Can 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 cluster

Waiting for the cluster to join

......

>>> Performing Cluster Check (using node 10.244.0.184:9720)

M: f8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.184:9720

slots:[0-5460] (5461 slots) master

1 additional replica(s)

S: 3df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720

slots: (0 slots) slave

replicates 150da7a79af740c55a61124f1d422fb9fcd19459

S: 699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720

slots: (0 slots) slave

replicates f8b4cc1d884eb3ced239c572e016a49cabd0313f

M: 150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720

slots:[5461-10922] (5462 slots) master

1 additional replica(s)

S: 3f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.187:9720

slots: (0 slots) slave


replicates a44ee1eaef7f89cd1013f10638d5d878dd982001

M: a44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720

slots:[10923-16383] (5461 slots) master

1 additional replica(s)

[OK] All nodes agree about slots configuration.

>>> Check for open slots...

>>> Check slots coverage...

[OK] All 16384 slots covered./<code>


我們使用命令行進入其中的一個節點:

[root@init-redis-cluster redis-5.0.7]# redis-cli -c -h 10.244.0.184 -p 9720

<code>10.244.0.184:9720> get a 1

(error) ERR wrong number of arguments for 'get' command

10.244.0.184:9720> cluster info

cluster_state:ok

cluster_slots_assigned:16384

cluster_slots_ok:16384

cluster_slots_pfail:0

cluster_slots_fail:0

cluster_known_nodes:6

cluster_size:3

cluster_current_epoch:6

cluster_my_epoch:1

cluster_stats_messages_ping_sent:160


cluster_stats_messages_pong_sent:150

cluster_stats_messages_sent:310

cluster_stats_messages_ping_received:145

cluster_stats_messages_pong_received:160

cluster_stats_messages_meet_received:5

cluster_stats_messages_received:310

10.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:9720

OK

10.244.0.186:9720> get a

"1"

10.244.0.186:9720>/<code>


可以看到,集群現在處於可用狀態。


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


查閱其內容便一目瞭然:

記錄集群內的其他節點信息,用於通信。


例:

<code>3f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.187:9720@19720 slave a44ee1eaef7f89cd1013f10638d5d878dd982001 0 1574686485562 4 connected

150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720@19720 myself,master - 0 1574686485000 2 connected 5461-10922

f8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.184:9720@19720 master - 0 1574686484000 1 connected 0-5460

a44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720@19720 master - 0 1574686486000 3 connected 10923-16383

699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720@19720 slave f8b4cc1d884eb3ced239c572e016a49cabd0313f 0 1574686486563 5 connected

3df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720@19720 slave 150da7a79af740c55a61124f1d422fb9fcd19459 0 1574686484560 6 connected

vars currentEpoch 6 lastVoteEpoch 0/<code>

第一個字段是節點 ID,一個40個字符的隨機字符串,當一個節點被創建時不會再發生變化(除非CLUSTER RESET HARD被使用),所以當pod重啟前我們只要nodeId對應的ip:port改掉即可,就可以保證集群的正常使用。


(2).容器重啟導致節點ip變化的問題解決


2.1.相關配置方式


<code>在redis-configmap.yaml中有這麼一段腳本:

fix-ip.sh: |

#!/bin/sh

CLUSTER_CONFIG="/data/nodes.conf"

if [ -f ${CLUSTER_CONFIG} ]; then

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} #改

nodes.conf中本機的ip地址,因為pod每次重啟後會導致ip改變。

fi

exec "$@"/<code>


這個腳本在容器啟動後執行,修改當前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

<code>NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES

redis-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>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<code>


我們接下來選擇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

<code>a44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720@19720 master - 0 1574688847000 3 connected 10923-16383

f8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.192:9720@19720 master - 1574688835599 1574688833292 1 disconnected 0-5460

699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720@19720 slave f8b4cc1d884eb3ced239c572e016a49cabd0313f 0 1574688844318 5 connected

150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720@19720 master - 0 1574688847000 2 connected 5461-10922

3df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720@19720 slave 150da7a79af740c55a61124f1d422fb9fcd19459 0 1574688845000 6 connected

3f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.187:9720@19720 myself,slave a44ee1eaef7f89cd1013f10638d5d878dd982001 0 1574688844000 4 connected

vars currentEpoch 6 lastVoteEpoch 0/<code>


我們再進入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

<code>3df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720@19720 slave 150da7a79af740c55a61124f1d422fb9fcd19459 0 1574688845431 6 connected

150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720@19720 master - 0 1574688846433 2 connected 5461-10922

3f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.187:9720@19720 slave a44ee1eaef7f89cd1013f10638d5d878dd982001 0 1574688847000 4 connected

f8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.192:9720@19720 master - 1574688835609 1574688834406 1 disconnected 0-5460

699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720@19720 myself,slave f8b4cc1d884eb3ced239c572e016a49cabd0313f 0 1574688847000 5 connected

a44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720@19720 master - 0 1574688846000 3 connected 10923-16383

vars currentEpoch 6 lastVoteEpoch 0/<code>


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


<code>NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES

redis-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>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<none>/<code>


查看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

<code>a44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720@19720 master - 0 1574688847000 3 connected 10923-16383

f8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.192:9720@19720 master - 1574688835599 1574688833292 1 disconnected 0-5460

699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720@19720 slave f8b4cc1d884eb3ced239c572e016a49cabd0313f 0 1574688844318 5 connected

150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720@19720 master - 0 1574688847000 2 connected 5461-10922

3df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720@19720 slave 150da7a79af740c55a61124f1d422fb9fcd19459 0 1574688845000 6 connected

3f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.194:9720@19720 myself,slave a44ee1eaef7f89cd1013f10638d5d878dd982001 0 1574688844000 4 connected

vars currentEpoch 6 lastVoteEpoch 0/<code>


查看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

<code>3df0d7b40c1a52a1ded516372037121da012331e 10.244.0.189:9720@19720 slave 150da7a79af740c55a61124f1d422fb9fcd19459 0 1574834074462 6 connected

150da7a79af740c55a61124f1d422fb9fcd19459 10.244.0.185:9720@19720 master - 0 1574834075000 2 connected 5461-10922

3f99b19459bd62400f92b9f9ea246f465b035eb2 10.244.0.194:9720@19720 slave a44ee1eaef7f89cd1013f10638d5d878dd982001 1574834069654 1574834068000 4 disconnected

f8b4cc1d884eb3ced239c572e016a49cabd0313f 10.244.0.192:9720@19720 master - 0 1574834077000 1 connected 0-5460

699b9e9e9f69bf65055f1f077c02175f2c91385f 10.244.0.188:9720@19720 myself,slave f8b4cc1d884eb3ced239c572e016a49cabd0313f 0 1574834077000 5 connected

a44ee1eaef7f89cd1013f10638d5d878dd982001 10.244.0.186:9720@19720 master - 0 1574834077469 3 connected 10923-16383

vars currentEpoch 6 lastVoteEpoch 0/<code>


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).相關文章閱讀



kubernetes-20:redis-cluster容器化


分享到:


相關文章: