はじめに
こんにちは、ACS事業部の吉川です。
Azure Kubernetes Service(AKS)でIngressを使いたいとき、皆さんはどんなIngress Controllerをお使いでしょうか?
Ingress NGINX Controller ?Application Gateway Ingress Controller?それとも、Istio?
このたび新たな選択肢として、Application Gateway for Containers というものがプレビュー公開されましたのでご紹介したいと思います。
AGICの問題点
以前より、AzureのL7ロードバランサーサービスであるApplication GatewayをAKSのIngressとして利用する Application Gateway Ingress Controller(AGIC) が公式のアドオンとして公開されています。
しかし、AGICにはいくつか問題があり、最たるものとしては Podの状態更新がApplication Gatewayに伝達されるまでに長い時間がかかる、というものです。GitHub上の以下のIssueにて意見が交わされています。
冒頭挙げたApplication Gateway for Containersのプレビューのお知らせサイト内に、Achieve near-to-real-time convergence times to reflect add/remove of pods, routes, probes, and other load balancing configuration within Kubernetes yaml configuration.
と記載があることから、この問題を解消する新たなアーキテクチャとなったことが期待できます。
構成
公式ドキュメントに構成の簡単な概要図がありましたので引用します。
引用元: What is Application Gateway for Containers? (preview)
AKSクラスター内に ALBコントローラー というものをデプロイし、それがIngress/Gateway APIを通じてApplication Gateway for Containersの実体をコントロールする、という構成のようです。
アイコンを見て察する方もいるかもしれませんが、従来の Application Gatewayとは全くの別物 です。
試してみる
まずはAKSを作成しましょう。
Application Gateway for Containers(長いので以下AGfCと表現します)ではAzure ADワークロードIDが必須なので、それ用のオプションを追加しています。Azure ADワークロードIDについては以下を参照ください。
また、現時点ではAGfCは限られたリージョンでのみプレビュー公開されています。残念ながら日本リージョンには対応していないため、ここではEast USリージョンで作成しています。
# リソース名/リージョンの定義 RG_NAME="rg-sample" VNET_NAME="vnet-sample" AKS_SNET_NAME="snet-aks" AKS_NAME="aks-sample" LOCATION="eastus" # リソースグループ作成 az group create --location $LOCATION --name $RG_NAME # VNet/サブネットの作成 az network vnet create -n $VNET_NAME -g $RG_NAME -l $LOCATION \ --address-prefixes 192.168.0.0/16 az network vnet subnet create -n $AKS_SNET_NAME \ --vnet-name $VNET_NAME -g $RG_NAME \ --address-prefixes 192.168.0.0/24 # AKSクラスター作成 AKS_SUBNET_ID=$(az network vnet subnet show -n $AKS_SNET_NAME \ --vnet-name $VNET_NAME -g $RG_NAME --query id -o tsv) az aks create -g $RG_NAME -n $AKS_NAME -l $LOCATION \ --enable-oidc-issuer --enable-workload-identity \ --node-count 1 --network-plugin azure --vnet-subnet-id $AKS_SUBNET_ID # kubectlのインストール sudo az aks install-cli # AKSの認証情報取得 az aks get-credentials -g $RG_NAME -n $AKS_NAME
次に、ALBコントローラーが使用するマネージドIDを作成します。このマネージドIDはどこに作っても構わないと思いますが、AKSクラスターを作った際にできる MC_
で始まる名前のリソースグループ内に作成しています。
# リソース名の定義 MANAGED_ID_NAME="azure-alb-identity" # MC_リソースグループ情報の取得 AKS_RG_NAME=$(az aks show --resource-group $RG_NAME --name $AKS_NAME --query "nodeResourceGroup" -o tsv) AKS_RG_ID=$(az group show --name $AKS_RG_NAME --query id -o tsv) # マネージドID作成 az identity create --resource-group $AKS_RG_NAME --name $MANAGED_ID_NAME # マネージドIDにMC_リソースグループの閲覧者ロールを割り当て sleep 60 MANAGED_ID_PID=$(az identity show -g $AKS_RG_NAME -n $MANAGED_ID_NAME --query principalId -o tsv) az role assignment create --assignee-object-id $MANAGED_ID_PID --assignee-principal-type ServicePrincipal \ --scope $AKS_RG_ID --role "acdd72a7-3385-48ef-bd42-f606fba81ae7"
作成したマネージドIDにワークロードIDのフェデレーション設定を行います。
AKS_OIDC_ISSUER="$(az aks show -n $AKS_NAME -g $RG_NAME --query "oidcIssuerProfile.issuerUrl" -o tsv)" az identity federated-credential create --name "azure-alb-identity" \ --identity-name $MANAGED_ID_NAME \ --resource-group $AKS_RG_NAME \ --issuer $AKS_OIDC_ISSUER \ --subject "system:serviceaccount:azure-alb-system:alb-controller-sa"
Helmを使って、AKSクラスターに ALBコントローラー をデプロイします。
MANAGED_ID_CID=$(az identity show -g $AKS_RG_NAME -n $MANAGED_ID_NAME --query clientId -o tsv) helm install alb-controller oci://mcr.microsoft.com/application-lb/charts/alb-controller \ --version 0.4.023961 \ --set albController.podIdentity.clientID=$MANAGED_ID_CID
ALBコントローラーは azure-alb-system
という名前空間にデプロイされます。Podが2種類デプロイされるので、READYになったことを確認しましょう。
$ kubectl get pods -n azure-alb-system NAME READY STATUS RESTARTS AGE alb-controller-6f58b647cb-rpp7n 1/1 Running 0 7m40s alb-controller-bootstrap-5f8c757676-ctpmk 1/1 Running 0 7m40s
続いて、AGfC および フロントエンド を作成します。このフロントエンドが実際の接続を受け付けるインスタンスの定義のようです。外部からのアクセスを受け付けるためのFQDNもフロントエンドに紐づきます。
なお、このAGfCとフロントエンドの作成については、ALBコントローラーに動的に作成させるというオプションもあります。
今回は事前に作成したAGfCリソースを利用する Bring Your Ownデプロイ の手順で進めます。
# CLI拡張機能の有効化 az extension add --name alb # リソース名の定義 AGFC_NAME="alb-sample" AGFC_FRONTEND_NAME="frontend-sample" az network alb create -g $RG_NAME -n $AGFC_NAME az network alb frontend create -g $RG_NAME -n $AGFC_FRONTEND_NAME --alb-name $AGFC_NAME
作成したAGfCのフロントエンドとサブネットを紐づけます。
# リソース名の定義 AGFC_SNET_NAME="snet-agfc" ASSOCIATION_NAME="association-sample" # サブネットの作成 az network vnet subnet create -n $AGFC_SNET_NAME \ --vnet-name $VNET_NAME -g $RG_NAME \ --address-prefixes 192.168.1.0/24 # サブネットの委任 az network vnet subnet update -n $AGFC_SNET_NAME \ --vnet-name $VNET_NAME -g $RG_NAME \ --delegations 'Microsoft.ServiceNetworking/trafficControllers' AGFC_SNET_ID=$(az network vnet subnet show -n $AGFC_SNET_NAME \ --vnet-name $VNET_NAME -g $RG_NAME --query id -o tsv) # サブネットの紐づけ az network alb association create -g $RG_NAME -n $AGFC_FRONTEND_NAME \ --alb-name $AGFC_NAME --subnet $AGFC_SNET_ID
ALBコントローラーのマネージドIDに必要なロールを割り当てます。
# AGfCが存在するリソースグループの「Azure Traffic Controller Configuration Manager」ロールを割り当て RG_ID=$(az group show --name $RG_NAME --query id -o tsv) az role assignment create --assignee-object-id $MANAGED_ID_PID --assignee-principal-type ServicePrincipal \ --scope $RG_ID --role "fbc52c3f-28ad-4303-a892-8a056630b8f1" # AGfC用サブネットのネットワーク共同作成者ロールを割り当て az role assignment create --assignee-object-id $MANAGED_ID_PID --assignee-principal-type ServicePrincipal \ --scope $AGFC_SNET_ID --role "4d97b98b-1d4f-4787-a291-c67834d212e7"
これでAGfCを利用するための設定は完了です。
ポータルからリソースの状態が以下のように確認できるので参考にしてみてください。
フロントエンドの設定を見ると、hoge.fuga.alb.azure.com
というFQDNが払い出されていることが確認できます。
サブネットの接続デバイスを見ると、tcgw
というインスタンスがいくつか接続されているのが確認できます。
Ingressとして使用する
前項までの設定でAGfCをIngressとして利用できるようになりました。早速試してみましょう。
テスト用にnginxのDeploymentを起動しておきます。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 2 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-svc spec: ports: - port: 80 protocol: TCP selector: app: nginx
kubectl apply -f nginx-deployment.yaml
続いてIngressを作成します。
マニフェストのアノテーションに
- AGfC のリソースID
- AGfC のフロントエンド名 (今回の例だと
frontend-sample
)
を設定する必要があります。リソースIDは以下のコマンドで確認しておきましょう。
az network alb show -g $RG_NAME -n $AGFC_NAME --query id -o tsv
確認した値を使ってマニフェストを作成してデプロイします。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-sample annotations: alb.networking.azure.io/alb-id: <AGfCのリソースID> alb.networking.azure.io/alb-frontend: <フロントエンド名> spec: ingressClassName: azure-alb-external rules: - http: paths: - path: / pathType: Prefix backend: service: name: nginx-svc port: number: 80
kubectl apply -f ingress.yaml
これでIngressの状態を見ると、ADDRESSの欄にポータルで確認したFQDNが表示されていることが確認できます。
kubectl get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-sample azure-alb-external * hoge.fuga.azure.com 80 82s
このFQDNにアクセスすると、デプロイしたnginxのデフォルトページに繋がります。
Ingressとして使えることが確認できましたね。
手元に適当な証明書・ドメインがなかったため確認できていないですが、公式ドキュメントを見る限りTLSの終端も問題なくできそうです。
おわりに
今後が期待できそうな新サービス、Application Gateway for Containersのご紹介でした。
従来のAGICはApplication GatewayをAKSからコントロールする機構でしたが、AGfCはKubernetes用に用意された独自のリソースが作成される構成のようです。AKSから利用することだけ考えればAGfCのほうがシンプルで使いやすそうなので、今後のGAを楽しみに待ちたいと思います。
また、AGfCはIngressだけでなく、Gateway APIにも対応しているようなのですが、そちらはまた別の機会にご紹介できればと思います。
【PR】
私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。
また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。