Azure - AKS - 使用 AGIC 當作 AKS Ingress
前言
用過 K8S 的朋友都知道,目前讓 K8S 對外提供端點,不外乎透過 ClusterIP、Nodeport、Load Balancer、Ingress 這幾種方法,而地端 K8S 下,最常用的應該就是 NodePort,畢竟地端的 Load Balancer 需要自建 QQ ...( 不過在雲上的 AKS 自動送你了 ),但就算有了 Load Balancer,但 LB 能提供的 Port 還是那幾個,遠遠不能滿足裡面那麼多的應用程式,所以我們可能希望透過網址的方式進行 mapping,讓不同的網址對應到後面的 Service,又或是透過 url path 進行導向,而這就是 Ingress 的功用。
Ingress 有很多種,包含使用 Nginx、Traefik 或是一整包包好的 Istio ,都可以做到上述講的這些功能,但在 AKS 的選擇上,小弟更喜歡用 AGIC ( Application Gateway Ingress Control )。
AGIC
如下是官網提供的 AGIC 架構圖,其實 AGIC 就是一個放在 AKS 裡面的 Azure Application Gateway 的監控程式,他可以監控 AKS 的 Ingress yaml,並且自動地去修改 Application Gateway 的設定,換言之,若我們使用了其他的 Ingress,這些 Ingress 會在 AKS 裡面運作,在裡面去處理流量的導向,而 AGIC 的監控,雖然在裡面,但真實流量的導向的處理,則是在外部的 Application Gateway。因為他就是一個外部的雲端服務,所以不會消耗掉 AKS 裡面 Node 的資源,而且透過雲上的特性,也可以輕易的縮放 ( 但小弟也沒什麼流量就是了...= =|| ),除此之外,Application Gateway 也提供了內建的 WAF 等機制,最重要的是,使用的方式,也和一般的 Ingress 差不多,搭配 YAML 的設定,就可以同步到 Application Gateway 上。
安裝 AGIC
目前安裝 AGIC 有兩種做法,以前很可憐的,只能透過 Helm 進行部署,而且還要去設定權限的部分,畢竟,我們要能讓 AGIC 去自動地去 Application Gateway 調整裡面的設定嘛~
而現在 AGIC 已經變成 AKS 的 addons 之一 ( ACI 的整合功能也是 addons 之一的功能 ),雖然這個 addons 還在 Preview ( 謎之聲 : 最近的文章怎麼都是 Preview XDD )。但基於方便安裝的立場上,而且還提供了自動更新等機制,覺得可以拿來使用了。 ( 請注意,Preview 功能是不提供 Support 的 )。
而開始前,還是要注意一下 AGIC 使用 Helm 和 addons 安裝的差異。
- addons 版本目前 ( 未來會改 ),不支援其他服務共用一個 Application Gateway,因為 addons 不能設定 ProhibitedTargets。在 Helm 的時代,我們可以啟用 Heml 設定檔 裡面的 appgw.shared=true,並加上 ProhibitedTargets CRD 的 yaml 設定,來讓 Application Gateway 同時提供給 AKS 和 VM 等服務使用。 ( 例如,要進入 VM 的網址為 vm.study4.tw,而我們可以在 ProhibitedTargets CRD 的 yaml 裡面去設定,若網址為 vm.study4.tw 的部分,AGIC 不會自動覆蓋掉我們在 Application Gateway 的設定,如果沒此功能,我們在 Application Gateway 的設定,會被 AGIC 秒改.. 詳細資料 )
- 同上,換言之,addons 就只能提供給這個 AKS 使用
-
底下的值,無法使用
而最終的對應表,就如官方下圖。
在 addons 的情境如下
- 1 AGIC : 1 AG : 正常情境
- 1 AGIC : 2 AG : 目前沒辦法 1 AGIC 對應到多個 AG
- 2 AGIC : 1 AG : addons 預設只能開一個 AGIC
- 2 AGIC : 2 AG : addons 預設只能開一個 AGIC
在 Helm 底下,的情境如下
- 1 AGIC : 1 AG : 正常情境
- 1 AGIC : 2 AG : 目前沒辦法 1 AGIC 對應到多個 AG
- 2 AGIC : 1 AG : 同樣因為可以設定 ProhibitedTargets,所以支援放兩個以上的 AGIC 對到同一個 AG
- 2 AGIC : 2 AG : 可行,如 1 AGIC : 1 AG 的情境
若有設定多組的 AKS 叢集,目前支援度就不高,如下圖所示
- 1 AGIC : 1 AG : 因為是 AKS 叢集,所以這個情境不合理
- 1 AGIC : 2 AG : 同上,因為是 AKS 叢集,不可能只有一個 AGIC
- 2 AGIC : 1 AG : 同樣因為可以設定 ProhibitedTargets,所以支援放兩個以上的 AGIC 對到同一個 AG
- 2 AGIC : 2 AG : 因為是 AKS 叢集,目前多組的 AG 沒辦法讓流量自動分散到不同的 AKS 叢集上
建立 Application Gateway
再將 Application Gateway 透過 AGIC 整合 AKS 之前,當然還是要先準備 Application Gateway,如果目前連 AKS 都沒有,這邊提供兩種做法,一個是 az cli,一個是 UI ( 但其實最近越來越喜歡用 az cli XDD )
另外,開始前,請先切一個 Application Gateway 專用的網段。至於為何要切 /24,底下為文件敘述。
應用程式閘道 (Standard_v2 或 WAF_v2 SKU) 最多可支援125個實例 (125 個實例 IP 位址 + 1 個私人前端 IP + 5 個 Azure 保留) –因此建議的子網大小下限為/24
所以~~
- 要最大可以到 125 個 instance,就要切 /24
- 若要使用私人端點,Standard_v2 必須要一個私人前端 IP,所以要 + 1
- 預設會 5 個保留 ( 前四個和最後一個 IP 位址 )
- 如果不會開那麼多個 instance 的話,可以少切一點
而建立 Application Gateway,當然一樣可以透過 az cli 來建立,如下。而這邊我們會用兩個 az cli 來建立 Application Gateway。
透過 az cli
第一步,是建立 Public IP,因為 Application Gateway 是對外的,當然要有對外的公用 IP,但這邊有個選項是很有趣的,稱為 --ip-tags 'RoutingPreference=Internet',意思是說,當啟用了這個選項後,任何從 Application Gateway 出去的數據,都會走 Internet。你或許或說,不是全部都是走 Internet 嗎!? No.No.非也,如果啟用了這個選項,而且 Application Gateway 架設在東日本,那他會從東日本的 ISP,東繞繞,西繞繞,繞到不同的 ISP 回到台灣。
而預設的情況下,則會走 Azure 的骨幹,換言之,若是東日本,然後台灣資料中心也已經完工了,那出來的資料,就會從東日本走 MS 骨幹到台灣資料中心,再出來到目的地,而不會透過東日本的 ISP 業者。
當然,以效能來說,自然是 MS 骨幹的延遲最低了,但走 Internet 的話,會比較便宜喔。
另外,這邊建議選擇 --sku standard,因為只有 standard 才有支援 Zone-redundant ( 自動啟用,沒錯,連 IP 有 XDDD )。當然,如果想特別針對某一個 zone,可以加上 --zone 1 的參數。
# 建立 Public 首碼,讓我們的 ip 可以連續 ( 一次最多 /28 - 16個 , 最小 /31 - 2個 ip)
az network public-ip prefix create \
--length 28 \
--location JapanEast \
--name PublicIPPrefix-Study4Dev-JE \
--resource-group study4dev-je
# 如果想讓網路省錢,可以加上 --ip-tags 'RoutingPreference=Internet' 讓他走 Internet,而不是 Azure 骨幹
#( 請先註冊 az feature register --namespace Microsoft.Network --name AllowRoutingPreferenceFeature )
az network public-ip create \
-n PublicIP-AG-AKS-Study4Dev-JE \
-g study4dev-je \
--allocation-method Static \
--sku Standard \
--public-ip-prefix PublicIPPrefix-Study4Dev-JE
建立 Application Gateway,這邊我們可以使用 --zones 1,2,3,來讓 Application Gateway 達到 Zone-redundant,但真的能不能達到高可用性,還是要看後面的 Work Node 的情況,如果大家還記得,之前小弟的 Work Node,基本上為了配合 PPG,所以只部署在 zone 1,所以雖然 Application Gateway 已經有了 Zone-redundant,但 zone 1 掛掉後,基本上,服務還是全死 XDDDD,不過這邊還是讓 Application Gateway 啟用 zones 1,2,3 吧~
# 建立 Application Gateway
# 目前使用 AZ CLI 建立 Standard_v2 必須指定 private ip addrss,所以要在 Application Gateway 的範圍內建立
# 底下只會建立一個 AG Instance
az network application-gateway create \
-n AG-AKS-Study4dev-JE \
-l JapanEast \
-g study4dev-je \
--sku Standard_v2 \
--public-ip-address \
PublicIP-AG-Study4Dev-JE \
--vnet-name Study4Dev-JE-VNet \
--subnet ApplicationGateway \
--http2 enabled \
--private-ip-address 10.99.181.80 \
--capacity 1 \
--zones {1,2,3}
# 只能建立完後,在默默地刪掉 QQ
# issue https://github.com/MicrosoftDocs/azure-docs/issues/64433
az network application-gateway frontend-ip delete \
--resource-group study4dev-je \
--gateway-name AG-AKS-Study4dev-JE \
--name appGatewayPrivateFrontendIP
透過 UI 建立
- 目前搭配 AGIC,一定要 v2,若有需要,也可以開 WAF V2。
- 因小弟流量小到可憐,所以就沒開自動縮放
- 同上,所以預設只一個 instance
- AG 要先切好一個子網路,專門給 AG 使用
這一步驟,只是設定一個 Public IP
未來會透過 AGIC,自動設定完這些參數,但初期透過 UI 建立的時候,這些還是必填....
這邊也是必填....
這邊也是必填....
這邊也是必填.... ( 未來可不可以改成不要填啊 QQ )
以上,就建立完成,完成後,我們可以透過屬性取得 ID。
結論,還是指令比較方便 QQ ( 懶 )
安裝 AGIC
因為目前是 Preview,所還是要先註冊功能
# 確認是否有安裝 aks-preview 外掛套件
az extension list
# 若沒安裝過外掛套件,請先安裝
az extension add --name aks-preview
# 若有安裝過請先更新
az extension update --name aks-preview
# 註冊功能
az feature register --name AKS-IngressApplicationGatewayAddon --namespace microsoft.containerservice
# 確認是否註冊完畢
az feature list -o table --query "[?contains(name, 'microsoft.containerservice/AKS-IngressApplicationGatewayAddon')].{Name:name,State:properties.state}"
# 重新整理功能
az provider register --namespace Microsoft.ContainerService
方案一 在 AKS 建立時自動建立
這邊是第一個方案,用於下指令建立 AKS 的時候,可以順便把 AGIC 和 AG 帶起來,主要是透過這三行指令 -a ingress-appgw --appgw-name myApplicationGateway --appgw-subnet-prefix "10.2.0.0/16"
完整範例如下,若要透過指令建置,可以參考小弟的這篇
# 建立 AKS 時,自動產生 AG
az aks create \
-n myCluster \
-g myResourceGroup \
--network-plugin azure \
--enable-managed-identity \
-a ingress-appgw \
--appgw-name myApplicationGateway \
--appgw-subnet-prefix "10.2.0.0/16" \
--generate-ssh-keys
方案二 已經有 AG 的情況下
這個情境是,當我們已經有 AG 的情況下,希望附加到 AKS 上。
# 設定 appgwId
appgwId=xxxxx/xxxxxx/xxxxx
# 懶惰一點也可以直接透過底下指令
appgwId=$(az network application-gateway show -n AG-AKS-Study4Dev-JE -g study4dev-je -o tsv --query "id")
# 啟用 agic addons
az aks enable-addons \
-n aks-study4dev-je \
-g study4dev-je \
-a ingress-appgw \
--appgw-id $appgwId
# 若想關閉可以透過底下關閉
az aks disable-addons \
-n aks-study4dev-je \
-g study4dev-je \
-a ingress-appgw
完成與測試
完成後,會產生一個監控用的 Pod。
若要簡單測試,可以安裝底下的 yaml
# 安裝 asp.net pod ,裡面包含 ingress
kubectl apply -f https://raw.githubusercontent.com/Azure/application-gateway-kubernetes-ingress/master/docs/examples/aspnetapp.yaml
kubectl get ingress
# 測試完成後刪除 asp.net pod
kubectl delete -f https://raw.githubusercontent.com/Azure/application-gateway-kubernetes-ingress/master/docs/examples/aspnetapp.yaml
Note : 目前不確定是否因小弟的 AKS 有開 AAD 整合,所以 AGIC 會出現
403 錯誤 Unexpected status code '403' while performing a GET on Application Gateway. You can use .....
的錯誤,所以要針對 Resource 加入 Reader 的權限,而 AG 要給予 Contributor 的權限。
指令下完後,要稍微等一下,等待權限生效。
# 對 Resource 給予 Reader 的權限
az role assignment create --role Reader --scope /subscriptions/xxxx-xxxx/resourceGroups/Study4Dev-JE --assignee xxxx
# 對 AG 給予 Contributor 的權限
az role assignment create --role Contributor --scope /subscriptions/xxxx/resourceGroups/Study4Dev-JE/providers/Microsoft.Network/applicationGateways/AG-AKS-Study4Dev-JE --assignee xxxx
最後,透過 Ingress 的 Public IP,就可以進行簡單的測試。
關於自行定義的 Ingress
關於 AGIC 的 ingress 定義 sample,可以參考底下,底下有完整的 pod、svc 和 ingress。從這個 sample 可以看到 ingress 是讓所有 / 路徑,全部對應到 aspnetapp svc 。
apiVersion: v1
kind: Pod
metadata:
name: aspnetapp
labels:
app: aspnetapp
spec:
containers:
- image: "mcr.microsoft.com/dotnet/core/samples:aspnetapp"
name: aspnetapp-image
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: aspnetapp
spec:
selector:
app: aspnetapp
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: aspnetapp
annotations:
kubernetes.io/ingress.class: azure/application-gateway
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: aspnetapp
servicePort: 80
若要將特定路徑對應到特定 domain ,可參考底下 ingress 範例。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: go-server-ingress-timeout
namespace: test-ag
annotations:
kubernetes.io/ingress.class: azure/application-gateway
appgw.ingress.kubernetes.io/backend-hostname: "internal.example.com"
spec:
rules:
- http:
paths:
- path: /hello/
backend:
serviceName: go-server-service
servicePort: 80
更多範例請參考 AGIC GitHub 文件
後記
其實東西不難,但最近在看 Azure 的時候,越來越發現,有很多的細節要注意,所以花了很長時間,終於寫完 (泣)。另外,採用 AGIC 當然是一種作法,但如果你喜歡內建 Pod 來使用 ingress 的方式,也是可以的,這邊,就帶給大家囉。
參考資料
- https://docs.microsoft.com/zh-tw/azure/application-gateway/ingress-controller-overview
- https://docs.microsoft.com/zh-tw/azure/application-gateway/tutorial-ingress-controller-add-on-existing
- https://github.com/Azure/application-gateway-kubernetes-ingress
- https://docs.microsoft.com/en-us/cli/azure/network/public-ip?view=azure-cli-latest#aznetworkpublicipcreate
- https://docs.microsoft.com/zh-tw/azure/virtual-network/manage-public-ip-address-prefix
- https://github.com/Azure/application-gateway-kubernetes-ingress/blob/master/docs/annotations.md
- https://docs.microsoft.com/en-us/cli/azure/network/application-gateway?view=azure-cli-latest#aznetworkapplicationgatewaycreate
- https://docs.microsoft.com/zh-tw/azure/application-gateway/tutorial-ingress-controller-add-on-existing
- https://docs.microsoft.com/en-us/cli/azure/network/application-gateway?view=azure-cli-latest#aznetworkapplicationgatewaycreate
- https://docs.microsoft.com/zh-tw/azure/application-gateway/configuration-infrastructure#size-of-the-subnet