Azure Kubernetes(AKS)是微软Azure云上托管的Kubernetes群集,可以用于快速部署Kubernetes群集,结合Azure其它服务和功能,简化日常运维,轻松实现业务应用的弹性。
想必很多小伙伴已经在大量使用AKS服务。然而使用中不可避免会发现,当前Kubernetes社区蓬勃发展,版本更新比较频繁。这其实是好事,可以更快速地修复各种已发现的Bug,同时还能通过升级为我们带来各种创新的功能。
然而如何把已经部署的AKS群集升级到最新版本,以便获得各种新的功能?
对AKS托管版本的升级,可以一键式地把AKS群集原地升级,或对群集内的工作节点逐个滚动升级。对于小规模或非关键业务群集来说,使用AKS的托管升级功能非常方便;然而对于大规模群集或关键业务应用来说,上述一键式原地升级的方法存在升级整体时间周期长,升级有可能出现故障,并且如果发生故障将不能回滚等局限。
那么有没有什么操作简单效果好,能同时兼顾上述两种方法优势的做法?
蓝绿部署
从事过应用开发或运维的小伙伴,应该对这个概念很熟悉了。这种应用发布模式可将用户流量从先前版本的应用逐渐转移到几乎相同的新版本中(旧版本可称为蓝色环境,新版本可称为绿色环境)。一旦生产流量从蓝色完全转移到绿色环境,蓝色环境就可以改为待机以备出现意外时可回滚恢复,观察一段时间稳定后可彻底清理以节省资源。
其实对于AKS群集的升级,我们也可以采用类似的思路:新建一个AKS群集,使用蓝绿部署方式进行切换升级。借此即可实现秒级切换,备份群集可随时回滚,更加快捷和安全。
然而该方案的架构和操作略显复杂,本文将带领大家逐步搭建这样一套切换升级的架构方案。在下文的示例中,我们将使用经典Web应用场景,但也可拓展成其它AKS群集应用场景。
架构概述
上图展示了一个经典的Web应用架构图,我们选取了最精简的资源,以使演示和说明尽量简明扼要。
在一个虚拟网络中划分开3个子网,前1个子网放置应用网关,作为对外服务的负载均衡器;后面2个子网平时只有1个子网有1个AKS集群,部署了业务系统。另1个子网用于版本升级时创建新的AKS集群。AKS集群采用高级网络CNI,以简化网络模式,以及方便应用网关与其通信。
在AKS集群中部署Pod Identity,通过Azure AD的Pod Identity来授权AKS中的Pod可以管理应用网关。
AGIC全称为Application Gateway Ingress Controller,它除了可以把来自应用网关的网络流量分发到相应的Pod,还监视部分Kubernetes资源中的更改,可以在AKS伸缩时自动更新应用网关的后端池,以及在AKS集群切换时同步更新应用网关的后端池。使用AGIC动态更新应用网关的后端,这是我们实现蓝绿部署的核心思路。
资源部署
部署网络等基础资源
首先需要用CLI快速将当前环境的基础资源创建出来。
创建资源组:
AZ_REGION=ChinaNorth2
RESOURCE_GROUP=AKS_Upgrade
az group create -n $RESOURCE_GROUP -l $AZ_REGION
创建VNET和子网:
VNET_NAME=AksVnet
APPGW_SUBNET=AppGwSubnet
AKS_SUBNET=AksSubnet
network vnet create on $VNET_NAME \
-g $RESOURCE_GROUP \
-l $AZ_REGION \
--address-prefix 10.0.0.0/8 \
--subnet-name $APPGW_SUBNET --subnet-prefix 10.1.0.0/16
az network vnet subnet create \
-g $RESOURCE_GROUP \
-n $AKS_SUBNET \
--address-prefixes 10.240.0.0/16 \
--vnet-name $VNET_NAME
部署当前AKS版本的Azure资源
创建公有IP:
APPGW_IP=AppGatewayIp
az network public-ip create -n $APPGW_IP \
-g $RESOURCE_GROUP \
--allocation-method Static \
--sku Standard
创建应用网关:
APP_GATEWAY=AppGateway
az network application-gateway create -n $APP_GATEWAY \
-g $RESOURCE_GROUP \
-l $AZ_REGION \
--vnet-name $VNET_NAME \
--subnet $APPGW_SUBNET \
--sku Standard_v2 \
--public-ip-address $APPGW_IP
创建旧AKS集群。使用当前默认的主流AKS版本。先获取一下之前创建出的放置AKS集群的子网ID。
AKS_SUBNET_ID=$(az network vnet subnet show -g $RESOURCE_GROUP --vnet-name $VNET_NAME --name $AKS_SUBNET --query id -o tsv)
创建AKS集群(撰写本文时,主流AKS版本为1.19.11):
AKS_OLD=old
az aks create -n $AKS_OLD \
-g $RESOURCE_GROUP \
-l $AZ_REGION \
--generate-ssh-keys \
--network-plugin azure \
--enable-managed-identity \
--vnet-subnet-id $AKS_SUBNET_ID
将应用网关与当前版本AKS集成
我们将用Azure服务主体来授权AKS集群管理应用网关的配置。
首先连接AKS集群:
az aks get-credentials --resource-group $RESOURCE_GROUP --name $AKS_OLD
随后即可使用大家熟悉的kubectl来管理AKS集群。
安装Helm并运行以下命令来添加application-gateway-kubernetes-ingress Helm包。我们的AKS群集已启用Kubernetes RBAC,因此可使用以下命令:
kubectl create serviceaccount --namespace kube-system tiller-sa
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller-sa
helm repo add aad-pod-identity https://raw.githubusercontent.com/Azure/aad-pod-identity/master/charts
helm install aad-pod-identity aad-pod-identity/aad-pod-identity
上述命令将返回如下的结果:
NAME: aad-pod-identity
LAST DEPLOYED: Tue Jun 29 08:14:30 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
You have successfully installed AAD Pod Identity in your Kubernetes cluster!
…
稍等一两分钟后,运行如下命令:
kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
aad-pod-identity-mic-787c5958fd-kmx9b 1/1 Running 0 71s 10.240.0.33 aks-nodepool1-94448771-vmss000000 <none> <none>
aad-pod-identity-mic-787c5958fd-nkpv4 1/1 Running 0 72s 10.240.0.63 aks-nodepool1-94448771-vmss000001 <none> <none>
aad-pod-identity-nmi-mhp86 1/1 Running 0 72s 10.240.0.4 aks-nodepool1-94448771-vmss000000 <none> <none>
aad-pod-identity-nmi-sjpvw 1/1 Running 0 72s 10.240.0.35 aks-nodepool1-94448771-vmss000001 <none> <none>
aad-pod-identity-nmi-xnfxh 1/1 Running 0 72s 10.240.0.66 aks-nodepool1-94448771-vmss000002 <none> <none>
可以看到,相关的几个Pod也已经运行起来了。
随后使用Helm安装Application Gateway Ingress Controller:
helm repo add application-gateway-kubernetes-ingress https://appgwingress.blob.core.windows.net/ingress-azure-helm-package/
helm repo update
复制以下YAML文件,先保存为helm_agic.yaml,用于配置AGIC:
# This file contains the essential configs for the ingress controller helm chart
# Verbosity level of the App Gateway Ingress Controller
verbosityLevel: 3
################################################################################
# Specify which application gateway the ingress controller will manage
#
appgw:
subscriptionId: <subscriptionId>
resourceGroup: <resourceGroupName>
name: <applicationGatewayName>
environment: AzureChinaCloud
# Setting appgw.shared to "true" will create an AzureIngressProhibitedTarget CRD.
# This prohibits AGIC from applying config for any host/path.
# Use "kubectl get AzureIngressProhibitedTargets" to view and change this.
shared: false
################################################################################
# Specify which kubernetes namespace the ingress controller will watch
# Default value is "default"
# Leaving this variable out or setting it to blank or empty string would
# result in Ingress Controller observing all acessible namespaces.
#
# kubernetes:
# watchNamespace: <namespace>
################################################################################
# Specify the authentication with Azure Resource Manager
#
# Two authentication methods are available:
# - Option 1: AAD-Pod-Identity (https://github.com/Azure/aad-pod-identity)
# armAuth:
# type: aadPodIdentity
# identityResourceID: <identityResourceId>
# identityClientID: <identityClientId>
## Alternatively you can use Service Principal credentials
armAuth:
type: servicePrincipal
secretJSON: <<Generate value with: "az ad sp create-for-rbac --sdk-auth | base64 -w0">>
################################################################################
# Specify if the cluster is RBAC enabled or not
rbac:
enabled: true # true/false
我们逐个把上述配置文件中的参数值填写进去。
- <subscriptionId>:通过az account show --query id -o tsv获取;
- <resourceGroupName>:值取$RESOURCE_GROUP环境变量;
- <applicationGatewayName>:值取$APP_GATEWAY环境变量。
secretJSON的值使用az ad sp create-for-rbac --sdk-auth | base64 -w0命令获取,是一段800多字节的base64编码长字符串。
因为我们的AKS集群启用了RBAC,所以最后那个配置rbac设置为true。
最后执行以下命令安装:
helm install agic application-gateway-kubernetes-ingress/ingress-azure -f helm_agic.yaml
上述命令将返回如下结果:
W0629 08:16:47.733467 16087 warnings.go:70] apiextensions.k8s.io/v1beta1 CustomResourceDefinition is deprecated in v1.16+, unavailable in v1.22+; use apiextensions.k8s.io/v1 CustomResourceDefinition
NAME: agic
LAST DEPLOYED: Tue Jun 29 08:16:48 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Thank you for installing ingress-azure:1.4.0.
Your release is named agic.
The controller is deployed in deployment agic-ingress-azure.
Configuration Details:
----------------------
* AzureRM Authentication Method:
- Use AAD-Pod-Identity
* Application Gateway:
- Subscription ID : 3d07553f-f6a8-455f-9de6-876fbcc00bb4
- Resource Group : AKS_Upgrade
- Application Gateway Name : AppGateway
* Kubernetes Ingress Controller:
- Watching All Namespaces
- Verbosity level: 3
随后运行下列命令:
kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
aad-pod-identity-mic-787c5958fd-kmx9b 1/1 Running 0 4m54s 10.240.0.33 aks-nodepool1-94448771-vmss000000 <none> <none>
aad-pod-identity-mic-787c5958fd-nkpv4 1/1 Running 0 4m55s 10.240.0.63 aks-nodepool1-94448771-vmss000001 <none> <none>
aad-pod-identity-nmi-mhp86 1/1 Running 0 4m55s 10.240.0.4 aks-nodepool1-94448771-vmss000000 <none> <none>
aad-pod-identity-nmi-sjpvw 1/1 Running 0 4m55s 10.240.0.35 aks-nodepool1-94448771-vmss000001 <none> <none>
aad-pod-identity-nmi-xnfxh 1/1 Running 0 4m55s 10.240.0.66 aks-nodepool1-94448771-vmss000002 <none> <none>
agic-ingress-azure-8d9d85dd9-z8dwh 1/1 Running 0 2m37s 10.240.0.70 aks-nodepool1-94448771-vmss000002 <none> <none>
发现新建的agic-ingress-azure这个Pod也正常运行起来了。
至此,我们已经成功部署了相关资源并实现了应用网关与AKS的集成。在下篇文章中,将会涉及应用部署、AKS新集群部署以及AKS版本切换三个任务。敬请期待!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。