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