Redis(Remote Dictionary Server 遠程字典服務)是一個ANSI C語言編寫的開源內存Key-Value數據庫,廣泛用於數據庫與應用之間的預留緩存(Cache-Aside)、網頁靜態內容緩存、用戶會話緩存、作業消息隊列以及分布式事務等場景。業績知名企業都在使用Redis,例如GitHub、Twitter、StackOverflow、Snapchat等等。
Redis 有三種使用模式,單實例、主備和集群。Redis 群集是一組 Redis 實例,通過數據分片(Sharding)來擴展數據庫。一個 Redis 集群包含 16384個哈希槽(Hash Slot),數據庫中的每個鍵都屬於這 16384 個哈希槽的其中一個, 集群使用公式 CRC16(key) % 16384 來計算鍵 key 屬於哪個槽,例如一個三節點集群, 節點 A 負責處理 0 號至 5500 號哈希槽,節點 B 負責處理 5501 號至 11000 號哈希槽,節點 C 負責處理 11001 號至 16384 號哈希槽。群集中的每個實例成員無論是主副本(Master)還是輔助副本(Slave)都管理哈希槽的子集,而且可以在不停機的情況下增加或減少節點。如果Master無法訪問,則其Slave將提升為Master繼續提供服務。群集內部通過內部總線通信,使用gossip協議傳播有關群集的信息或發現新節點。
Azure Kubernetes 服務 (AKS) 是全托管Kubernetes 環境。 AKS 通過將大量管理工作卸載到 Azure,用戶可以快速、輕松地部署和管理容器化的應用程序。AKS還可以按需預配、升級和縮放資源。Kubernetes 主節點由 Azure 管理,用戶只管理和維護工作節點。AKS服務本身免費,用戶只需支付群集中的工作節點虛擬機的費用,不需支付主節點的費用,比自建Kubernetes集群省去主節點費用。
如何基於AKS部署一套Redis集群?下面我們在3節點AKS集群上部署一套3節點Redis集群,Redis采用AOF模式進行持久化。每個Redis實例需要自己的配置文件和可讀寫持久化磁盤,因此我們需要結合使用K8S StatefulSets和PersistentVolumes來解決相關挑戰。部署過程使用了Azure CLI命令行工具,請自行安裝。
1. 創建AKS Cluster
創建腳本如下,詳細說明請參看官方文檔。此處需要注意3點:
- 目前Redis Cluster不支持網絡地址轉換,創建AKS時用Azure CNI (Container Networking Interface)高級網絡,不用Kubenet。
- Azure AD service principal(服務主體)是AKS集群配置的一部分,因為AKS需要授權調用虛擬網絡API
- AKS集群采用VM可用性集模式,各節點位於不同物理機架的服務器上,避免單點故障。
#/bin/sh
RESOURCEGROUP=rg-rediscluster
str=`az ad sp create-for-rbac --skip-assignment -o tsv`
APPID=`echo $str | awk -F " " '{print $1}'`
PASSWD=`echo $str | awk -F " " '{print $4}'`
echo "AppId:" $APPID
echo "Password:" $PASSWD
sleep 10
az group create --name $RESOURCEGROUP --location westus2
az network vnet create -g $RESOURCEGROUP -n vnet1 --address-prefix 192.168.0.0/16 --subnet-name subnet1 --subnet-prefix 192.
168.1.0/24
VNET_ID=$(az network vnet show --resource-group $RESOURCEGROUP --name vnet1 --query id -o tsv)
SUBNET_ID=$(az network vnet subnet list --resource-group $RESOURCEGROUP --vnet-name vnet1 --query [].id --output tsv)
az role assignment create --assignee $APPID --scope $VNET_ID --role Contributor
az aks create \
--resource-group $RESOURCEGROUP \
--name rediscluster \
--node-count 3 \
--node-vm-size Standard_DS2_v2 \
--vm-set-type AvailabilitySet \
--network-plugin azure \
--vnet-subnet-id $SUBNET_ID \
--docker-bridge-address 172.17.0.1/16 \
--dns-service-ip 10.2.0.10 \
--service-cidr 10.2.0.0/24 \
--load-balancer-sku Standard \
--service-principal $APPID \
--client-secret $PASSWD \
--generate-ssh-keys \
--output json
az aks get-credentials -g $RESOURCEGROUP -n redisakscluster
kubectl get nodes
2. 創建Redis
執行下面2個kubectl命令來創建Redis Cluster,因為要創建持久卷因此創建6個PodS用時約4-5分鍾。
$ kubectl apply -f redis-sts.yaml
configmap/redis-cluster created
statefulset.apps/redis-cluster created
redis-sts.yaml文件請參看:
https://raw.githubusercontent.com/yongboyang/AzureCLITools/master/RedisClusterAKS/redis-sts.yaml
redis-svc.yaml文件請參看:
https://raw.githubusercontent.com/yongboyang/AzureCLITools/master/RedisClusterAKS/redis-svc.yaml
$ kubectl apply -f redis-svc.yaml
service/redis-cluster created
$ kubectl get pods
$kubectl get pv
$kubectl describe pods redis-cluster-0 | grep pvc
我們也可以通過K8S Dashboard圖形界面檢查。
$ kubectl create clusterrolebinding kubernetes-dashboard --clusterrole=cluster-admin --serviceaccount=kube-system:kubernetes-dashboard
$ az aks browse --resource-group rg-rediscluster --name redisakscluster
Merged "redisakscluster" as current context in /tmp/tmpeea9jjwe
Proxy running on http://127.0.0.1:8001/
Press CTRL+C to close the tunnel...
Forwarding from 127.0.0.1:8001 -> 9090
Forwarding from [::1]:8001 -> 9090
3. 部署Redis 集群
執行這個命令行,通過redis-cli配置Redis 集群。
$ kubectl exec -it redis-cluster-0 -- redis-cli --cluster create --cluster-replicas 1 $(kubectl get pods -l app=redis-cluster -o jsonpath='{range.items[*]}{.status.podIP}:6379 ')
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.1.56:6379 to 192.168.1.91:6379
Adding replica 192.168.1.81:6379 to 192.168.1.46:6379
Adding replica 192.168.1.40:6379 to 192.168.1.26:6379
......
......
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
4. 檢查集群基本功能
$ kubectl exec -it redis-cluster-0 -- redis-cli cluster info
$ for x in $(seq 0 5); do echo "redis-cluster-$x"; kubectl exec redis-cluster-$x -- redis-cli role; echo; done
登錄進到redis-cluster-0中,查看掛載的1GB的持久化卷已經存在,通過 redis-cli -h localhost -p 6379 -c 命令訪問Redis集群正常工作。
5. 模擬節點故障,測試Master/Slave自動切換
$ kubectl delete pod -n redis-cluster-0
刪除Pod redis-cluster-0之后,redis-cluster-3自動切換到master;redis-cluster-0恢復后,自動切換成slave角色。
到這里,基於AKS部署Redis集群結束。
附錄:
以上部署腳本您可用Git克隆到本地
$ git clone https://github.com/yongboyang/AzureCLITools.git
$ cd RedisClusterAKS