Azure Application Gatewayを複数のAKSクラスタで共有できるか?(AGIC&Helm)

少し前に「複数の AKS クラスタ(Pod)で 1 つの Application Gateway を共有できるか」検証しサンプルを書いたので文章で補足します。
なお AGIC は Helm 版を使っています。おそらく add-on 版ではできません。

https://github.com/mazgi-sandbox/202204.azure-agic-shared-by-multiple-aks-clusters

結論から言うと「できるが煩雑なので事故りそう」です。
個人的には少なくとも本番環境で使おうとは思えませんでした。

主な注意点および煩雑に感じた点は以下です。

Ingress の name が Application Gateway の Backend pool 名になる

そのため異なる AKS クラスタ間で Ingress 名が重複しないように管理する必要がありそうです。
もしかすると Ingress 名が重複した場合、いい感じに backend pool 名を変えてくれるかもしれませんが、今回は実装を追えてませんし未検証です。

AKS クラスタに紐付ける Service Principal に Application Gateway を変更する権限が必要

当然ですが Pod が Application Gateway を変更するための権限をなんらかの方法で持つ必要があります。
今回は 1 つの Service Principal(SP)を 2 つの AKS クラスタ上の Pod に紐付けました。
言い換えると、それぞれ別の AKS クラスタ上の Pod が同じ Application Gateway を変更できる状態になります。

もし共用する Application Gateway が本番環境に存在しており、開発環境の AKS クラスタや Pod からこの Application Gateway の構成を変更する場合、開発環境でのインシデンとが本番環境でのインシデントとなりかねません。

検証方法

Application Gateway, AKS クラスタ, その他リソースの構成自体は次の ARM テンプレートで行いました。

https://github.com/mazgi-sandbox/202204.azure-agic-shared-by-multiple-aks-clusters/blob/8b21ed1586e3df25dc55b5670429e89e40c278c8/azuredeploy.json

なお手順および ARM テンプレートは下記オフィシャルドキュメントおよびサンプルに沿っています。

新しい Application Gateway を使用して Application Gateway イングレス コントローラー (AGIC) をインストールする方法
https://docs.microsoft.com/ja-jp/azure/application-gateway/ingress-controller-install-new

(サンプル ARM テンプレート)
https://github.com/Azure/application-gateway-kubernetes-ingress/blob/b875ca5514f335930650db5099a4f8c74fc8cfaa/deploy/azuredeploy.json

ついでに k8s バージョンを上げています。

Update default k8s version: 1.20.9 -> 1.23.3 #1369
https://github.com/Azure/application-gateway-kubernetes-ingress/pull/1369

構成

1 つの VNet 上に主なリソースを配置しており、各 Subnet のセグメントは次の通りです。

用途 セグメント
Application Gateway 用 10.0.0.0/16
AKS クラスタ(Green)用 10.8.0.0/16
AKS クラスタ(Blue)用 10.16.0.0/16

動作確認用の Web アプリケーション代わりに nginx と httpd の Docker イメージを各 AKS クラスタに deploy しました。
Manifest は次のファイルです。

(Green 用)
https://github.com/mazgi-sandbox/202204.azure-agic-shared-by-multiple-aks-clusters/blob/8b21ed1586e3df25dc55b5670429e89e40c278c8/app.on-green.yaml

(Blue 用)
https://github.com/mazgi-sandbox/202204.azure-agic-shared-by-multiple-aks-clusters/blob/8b21ed1586e3df25dc55b5670429e89e40c278c8/app.on-blue.yaml

Ingress 設定の以下がポイントです。

  • annotations.kubernetes.io/ingress.classazure/application-gateway
  • spec.rules.host"green.example.com" のような FQDN
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: appgreen
  annotations:
    kubernetes.io/ingress.class: azure/application-gateway
spec:
  rules:
    - host: "green.example.com"
      http:
        paths:
          - path: /
            backend:
              service:
                name: appgreen
                port:
                  number: 80
            pathType: Exact

そして今回のキモである AzureIngressProhibitedTarget ですが、まずデフォルトで存在する prohibit-all-targets は次のように削除します。

​​kubectl delete AzureIngressProhibitedTargets prohibit-all-targets --context $aksGreenClusterName
kubectl delete AzureIngressProhibitedTargets prohibit-all-targets --context $aksBlueClusterName

そして別途 AzureIngressProhibitedTarget を作成し、 spec.hostname で Green では Blue の FQDN を、Blue では Green の FQDN を指定します。

(Green 用)
https://github.com/mazgi-sandbox/202204.azure-agic-shared-by-multiple-aks-clusters/blob/8b21ed1586e3df25dc55b5670429e89e40c278c8/agic-prohibit.for-green.yaml

(Blue 用)
https://github.com/mazgi-sandbox/202204.azure-agic-shared-by-multiple-aks-clusters/blob/8b21ed1586e3df25dc55b5670429e89e40c278c8/agic-prohibit.for-blue.yaml

apiVersion: "appgw.ingress.k8s.io/v1"
kind: AzureIngressProhibitedTarget
metadata:
  name: for-green-example-com
spec:
  hostname: blue.example.com

動作確認

以上で 2 つの AKS クラスタから 1 つの Application Gateway を共用した構成が作れます。
動作確認方法および結果は README をご参照ください。

https://github.com/mazgi-sandbox/202204.azure-agic-shared-by-multiple-aks-clusters/tree/8b21ed1586e3df25dc55b5670429e89e40c278c8#example-outputs