擁抱藍綠部署,推動AKS群集版本平滑升級

微軟技術棧發表於2021-11-23

Azure Kubernetes(AKS)是微軟Azure雲上託管的Kubernetes群集,可以用於快速部署Kubernetes群集,結合Azure其它服務和功能,簡化日常運維,輕鬆實現業務應用的彈性。

想必很多小夥伴已經在大量使用AKS服務。然而使用中不可避免會發現,當前Kubernetes社群蓬勃發展,版本更新比較頻繁。這其實是好事,可以更快速地修復各種已發現的Bug,同時還能通過升級為我們帶來各種創新的功能。

然而如何把已經部署的AKS群集升級到最新版本,以便獲得各種新的功能?

對AKS託管版本的升級,可以一鍵式地把AKS群集原地升級,或對群集內的工作節點逐個滾動升級。對於小規模或非關鍵業務群集來說,使用AKS的託管升級功能非常方便;然而對於大規模群集或關鍵業務應用來說,上述一鍵式原地升級的方法存在升級整體時間週期長,升級有可能出現故障,並且如果發生故障將不能回滾等侷限。

那麼有沒有什麼操作簡單效果好,能同時兼顧上述兩種方法優勢的做法?
977cc54b573d5770dec335b4396b964f.png

藍綠部署

從事過應用開發或運維的小夥伴,應該對這個概念很熟悉了。這種應用釋出模式可將使用者流量從先前版本的應用逐漸轉移到幾乎相同的新版本中(舊版本可稱為藍色環境,新版本可稱為綠色環境)。一旦生產流量從藍色完全轉移到綠色環境,藍色環境就可以改為待機以備出現意外時可回滾恢復,觀察一段時間穩定後可徹底清理以節省資源。

其實對於AKS群集的升級,我們也可以採用類似的思路:新建一個AKS群集,使用藍綠部署方式進行切換升級。藉此即可實現秒級切換,備份群集可隨時回滾,更加快捷和安全。

然而該方案的架構和操作略顯複雜,本文將帶領大家逐步搭建這樣一套切換升級的架構方案。在下文的示例中,我們將使用經典Web應用場景,但也可擴充成其它AKS群集應用場景。

架構概述

2104966ded6fd4ed2bab0cdafdbfce27.png
上圖展示了一個經典的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版本切換三個任務。敬請期待!

相關文章