在微软云AKS上部署弹性应用
Azure Kubernetes 服务 (AKS)是微软云Azure上托管的Kubernetes 群集,可以用于快速部署Kubernetes 群集,结合Azure其它服务和功能,简化日常运维,轻松实现业务应用的弹性。本文是一个动手小实验,演示弹性部署的基本步骤。适用的场景是在AKS背后的虚拟机意外停机时,通过Kubernetes 的配置实现自动故障转移。阅读本文需要掌握Kubernetes的基本知
Azure Kubernetes 服务 (AKS)是微软云Azure上托管的Kubernetes 群集,可以用于快速部署Kubernetes 群集,结合Azure其它服务和功能,简化日常运维,轻松实现业务应用的弹性。本文是一个动手小实验,演示弹性部署的基本步骤。适用的场景是在AKS背后的虚拟机意外停机时,通过Kubernetes 的配置实现自动故障转移。
阅读本文需要掌握Kubernetes的基本知识和操作,以及AKS的基本概念和部署。
基本部署
应用
演示用的应用源码在这里
https://github.com/xfsnow/pipelines-javascript-docker/
请先fork到自己的GitHub账号下。
这个应用是个非常简单的Node.js 应用,用来输出时间和运行的主机名,用以演示负载均衡后具体运行在哪个后端上。主要文件只有一个
输出内容就是下面这行:
res.send('Hello world! Now is '+now+'.\nRunning on '+os.hostname()+'.');
Kubernetes的部署文件主要是manifests/hello-deployment.yml,以 4 个replica部署一个deployment。这个配置文件的声明和作用都写在相关注释里了。核心原理是使用
# 通过 toleration 来检测节点状态,一旦发现节点不可用,则不再置放 pod
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 1
- key: "node.kubernetes.io/not-ready"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 1
以及
#健康检查,通过 httpGet 检查应用运行状态
livenessProbe:
httpGet:
port: 80
scheme: HTTP
path: /
# 初始化延迟 3 秒,用于应用首次启动时等待的时间,避免首次启动慢误判为失败。
initialDelaySeconds: 10
# 之后检查的间隔时间
periodSeconds: 1
# 超时多久认为是失败
timeoutSeconds: 3
另有一个hello-service.yml,部署了一个负载均衡器,暴露出公网IP对外提供服务。这个负载均衡器也还有健康检查,在发现后端pod不可用时,会把其撤掉,然后再把新生成的pod挂载上来。
Azure资源
一个ACR,用于保存容器镜像,注意目前只有东2区域可以支持az acr build 命令在本地直接构建并推送到ACR。所以我们创建的ACR资源在东2区,而AKS集群可以在任何一个国内的区域。
# 定义环境变量
REGION_NAME=ChinaEast2
RESOURCE_GROUP=aksResilience
AKS_CLUSTER_NAME=aksResilience
ACR_NAME=acr$RANDOM
#创建资源组
az group create --location $REGION_NAME --name $RESOURCE_GROUP
# 创建ACR
az acr create --resource-group $RESOURCE_GROUP --name $ACR_NAME --location $REGION_NAME --sku Standard
列表看一下结果
az acr list -o table
NAME RESOURCE GROUP LOCATION SKU LOGIN SERVER CREATION DATE ADMIN ENABLED
-------- ---------------- ----------- ----- ------------------- -------------------- ---------------
acr11044 aksResilience chinaeast2 Standard acr11044.azurecr.cn 2021-02-05T03:12:36Z False
#创建 AKS 集群
az aks create \
--resource-group $RESOURCE_GROUP \
--name $AKS_CLUSTER_NAME \
--location $REGION_NAME \
--node-count 2 \
--enable-addons monitoring \
--generate-ssh-keys
这步比较慢,请耐心等待,直到有返回结果。
列一下 AKS集群
az aks list -o table
Name Location ResourceGroup KubernetesVersion ProvisioningState Fqdn
------------- ----------- --------------- ------------------- -------------------
aksResilience chinanorth2 aksResilience 1.18.14 Succeeded
# 把 ACR 绑定到AKS集群上,这样就可以自动验证从ACR拉取镜像到AKS集群了
az aks update \
--name $AKS_CLUSTER_NAME \
--resource-group $RESOURCE_GROUP \
--attach-acr $ACR_NAME
这步比较慢,请耐心等待,直到有返回结果。
到此,Azure资源已创建完毕,总共1个AKS集群,包含1个虚拟机扩展集,其中有2台虚拟机。
列一下 AKS集群背后的虚拟机扩展集。注意这里的虚拟机扩展集由Azure自动创建在另一个资源组里。
az vmss list -o table
Name ResourceGroup Location Zones Capacity Overprovision UpgradePolicy
--------------------------- ------------------------------------------ ----------- ------- ---------- --------------- ---------------
aks-nodepool1-40474697-vmss MC_AKSRESILIENCE_AKSRESILIENCE_CHINANORTH2 chinanorth2 2 False Manual
最后列一下虚拟机扩展集中的实例
az vmss list-instances \
> -g MC_AKSRESILIENCE_AKSRESILIENCE_CHINANORTH2 \
> -n aks-nodepool1-40474697-vmss \
> -o table \
> --query "[].{instanceId:instanceId, Name:name, State:provisioningState}"
InstanceId Name State
------------ ----------------------------- ---------
0 aks-nodepool1-40474697-vmss_0 Succeeded
1 aks-nodepool1-40474697-vmss_1 Succeeded
部署Kubernetes
构建镜像推送到镜像注册表。
git clone https://github.com/xfsnow/pipelines-javascript-docker/
拉取源码。
先构建并推送镜像
cd app
az acr build \
--resource-group $RESOURCE_GROUP \
--registry $ACR_NAME \
--image helloworld:1.0 .
然后获取镜像注册表具体的URL
az acr repository show -n $ACR_NAME --repository helloworld --query "registry"
"acr11044.azurecr.cn"
记下这个形如acr11044.azurecr.cn的URL,后面接上helloworld:1.0就是完整的镜像拉取地址,形如
acr11044.azurecr.cn/helloworld:1.0
cd manifests,
找到 hello-deployment.yml 中的这行
# 容器镜像使用 Azure 上的 ACR 服务。
image: snowpeak.azurecr.cn/helloworld:1.3
替换成你自己的 ACR 镜像的URL “acr11044.azurecr.cn/helloworld:1.0”。
连接AKS集群并部署镜像
连接AKS集群
az aks get-credentials --resource-group $RESOURCE_GROUP --name $AKS_CLUSTER_NAME
先查看一下AKS集群中的节点
kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUN
TIME
aks-nodepool1-40474697-vmss000000 Ready agent 142m v1.18.14 10.240.0.4 <none> Ubuntu 18.04.5 LTS 5.4.0-1035-azure docker://19.3
.14
aks-nodepool1-40474697-vmss000001 Ready agent 142m v1.18.14 10.240.0.5 <none> Ubuntu 18.04.5 LTS 5.4.0-1035-azure docker://19.3
.14
再看一下pod。
kubectl get pods -o wide
No resources found in default namespace.
此时尚未部署镜像,所以没有资源。
然后用 cd ../manifests/ 来到Kubernetes 配置文件目录下。
kubectl apply -f hello-deployment.yml和 kubectl apply -f hello-service.yml 部署到 AKS 集群中。部署好的集群初始是这样的。
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
helloworld-869d58f588-5tmpf 1/1 Running 0 71s 10.244.1.6 aks-nodepool1-40474697-vmss000001 <none> <none>
helloworld-869d58f588-bt54r 1/1 Running 0 71s 10.244.1.7 aks-nodepool1-40474697-vmss000001 <none> <none>
helloworld-869d58f588-qh6hn 1/1 Running 0 71s 10.244.0.6 aks-nodepool1-40474697-vmss000000 <none> <none>
helloworld-869d58f588-w8xbx 1/1 Running 0 71s 10.244.0.7 aks-nodepool1-40474697-vmss000000 <none> <none>
这是运行起来的4个pod,每个节点上2个pod。
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloworld LoadBalancer 10.0.116.133 139.217.112.135 80:30754/TCP 7d17h
这是部署起来的LoadBalancer,外网IP 139.217.112.135 可以直接访问,返回的结果如下:
curl http://139.217.112.135/;
Hello world! Now is 2021-02-04 08:26:52.924.
Running on helloworld-745c979464-q54vd.
这里Running on helloworld-745c979464-q54vd. 正是上述1个pod的名称。
如果连续请求多次,会看到请求大致均匀地分发到4个后端pod上。
while(true); do curl --connect-timeout 2 http://139.217.112.135/; echo -e '\n'; sleep 0.5; done
Hello world! Now is 2021-02-04 08:34:19.523.
Running on helloworld-745c979464-q54vd.
Hello world! Now is 2021-02-04 08:34:20.160.
Running on helloworld-745c979464-ljrcv.
Hello world! Now is 2021-02-04 08:34:20.798.
Running on helloworld-745c979464-97v26.
Hello world! Now is 2021-02-04 08:34:21.427.
Running on helloworld-745c979464-q54vd.
Hello world! Now is 2021-02-04 08:34:22.56.
Running on helloworld-745c979464-l2jpm.
Hello world! Now is 2021-02-04 08:34:22.697.
Running on helloworld-745c979464-ljrcv.
Hello world! Now is 2021-02-04 08:34:23.368.
Running on helloworld-745c979464-l2jpm.
Hello world! Now is 2021-02-04 08:34:24.6.
Running on helloworld-745c979464-ljrcv.
Hello world! Now is 2021-02-04 08:34:24.659.
Running on helloworld-745c979464-l2jpm.
模拟故障
我们手工停止一台虚拟机,模拟虚拟机发生故障的情况。
- 我们先打开实时观察 pod 运行状况
kubectl get po -o wide -w
- 再开一个新窗口运行
while(true); do curl --connect-timeout 2 http://139.217.112.135/; echo -e '\n'; sleep 0.5; done
来看访问应用的情况
- 再开一个窗口执行停止一台虚拟机的命令
az vmss stop -g MC_DEMO_HELLOWORLD_CHINANORTH2 -n aks-agentpool-11798053-vmss --instance-id 0
- 回到第一个窗口,查看 pod 运行情况,看到类似如下的返回。
kubectl get po -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
helloworld-9bbdbf45b-2hnz4 1/1 Running 0 119s 10.240.0.152 aks-agentpool-11798053-vmss000001 <none> <none>
helloworld-9bbdbf45b-64qt4 1/1 Terminating 0 6m41s 10.240.0.106 aks-agentpool-11798053-vmss000000 <none> <none>
helloworld-9bbdbf45b-gczpn 1/1 Running 0 6m37s 10.240.0.135 aks-agentpool-11798053-vmss000001 <none> <none>
helloworld-9bbdbf45b-l6dxm 1/1 Terminating 0 5m11s 10.240.0.68 aks-agentpool-11798053-vmss000000 <none> <none>
helloworld-9bbdbf45b-rhn2m 1/1 Terminating 0 4m45s 10.240.0.42 aks-agentpool-11798053-vmss000000 <none> <none>
helloworld-9bbdbf45b-smtft 1/1 Running 0 118s 10.240.0.185 aks-agentpool-11798053-vmss000001 <none> <none>
helloworld-9bbdbf45b-tmdkr 1/1 Running 0 119s 10.240.0.149 aks-agentpool-11798053-vmss000001 <none> <none>
第1个节点上的pod显示正在停止,而新的pod运行在第2个节点上。
- 再来到运行curl的窗口查看
while(true); do curl --connect-timeout 2 http://139.217.112.135/; echo -e '\n'; sleep 0.5; done
curl: (28) Connection timed out after 2013 milliseconds
…
curl: (28) Connection timed out after 2009 milliseconds
…
Hello world! Now is 2021-02-04 01:40:37.752.
Running on helloworld-9bbdbf45b-2vjxt.
Hello world! Now is 2021-02-04 01:40:38.409.
Running on helloworld-9bbdbf45b-vpvn6.
Hello world! Now is 2021-02-04 01:40:39.57.
Running on helloworld-9bbdbf45b-2vjxt.
Hello world! Now is 2021-02-04 01:40:39.736.
在出现若干次超时后,返回结果恢复正常了,并且主机名出现了新的pod名称。
仔细查看输出内容的时间,可以看到超时经历的时间不超过1分钟。
- 最后我们再恢复节点运行
可以看到原来停止的节点上的pod显示为正常Terminating并最终消失,现有4个pod都运行在第2个节点上。可以通过设置replicas 来重新均衡置放pod。
资源清理
az group delete --name $RESOURCE_GROUP --yes
删除该资源组及其所有资源,实验结束。
更多推荐
所有评论(0)