APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

AKSのIngress Controllerの新たな選択肢、Application routing add-onの紹介

はじめに

こんにちは、ACS事業部の吉川です。

Azure Kubernetes Service(AKS)でIngressを使いたいとき、皆さんはどんなIngress Controllerをお使いでしょうか?
Ingress NGINX ControllerApplication Gateway Ingress Controller?それとも、Istio

昨年の11月に、AKSのIngressとして利用できる Application routing add-on がGAしましたので、本記事でご紹介します。

azure.microsoft.com

Application routing add-onってどんなもの?

上記の更新情報ページに App routing offers a supported and managed ingress controller powered by the ingress-nginx project. とあるように、従来手動でインストールしていたIngress NGINX Controllerの代替と考えればよさそうです。Ingress Controllerの実態としてはNGINXのPodが稼働します。
また、AKSのアドオンとして提供されるということでAzureのサービスとの統合もアピールされています。具体的には

  • Key Vaultからの証明書読み込み
  • Azure DNSへの自動レコード登録

といった機能が利用できます。

インストール方法

Application routing add-onのインストール方法は以下のドキュメントにて公開されています。

learn.microsoft.com

現状ではAzureポータルからインストールすることはできず、Azure CLIでオプション指定することでインストールできます。
新規でAKSクラスターを作成する場合は、az aks create コマンドに --enable-app-routing オプションを指定することで最初からアドオンがインストールされた状態でクラスターを作成できます。
既存のAKSクラスターにインストールする際は以下のコマンドでインストールできます。

az aks approuting enable -g <リソースグループ名> -n <AKSクラスター名>

インストールするとAKSクラスター上にリソースが作成されます。
app-routing-system 名前空間上にNGINXのDeploymentやServiceといったリソースが作成され、

kubectl get all -n app-routing-system
NAME                         READY   STATUS    RESTARTS   AGE
pod/nginx-674ff56578-9zrmk   1/1     Running   0          2m14s
pod/nginx-674ff56578-kvk8j   1/1     Running   0          2m55s

NAME            TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)                                      AGE
service/nginx   LoadBalancer   10.0.83.14   20.27.4.82    80:30152/TCP,443:30936/TCP,10254:31529/TCP   3h17m

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   2/2     2            2           3h17m

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-674ff56578   2         2         2       3h17m

NAME                                        REFERENCE          TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/nginx   Deployment/nginx   0%/80%    2         100       2          3h17m

IngressClassリソースも作成されます。

kubectl get ingressclass
NAME                                 CONTROLLER                                 PARAMETERS   AGE
webapprouting.kubernetes.azure.com   webapprouting.kubernetes.azure.com/nginx   <none>       3h18m

これで、以下のようなYAMLを使ってIngressリソースをデプロイ可能です。spec.ingressClassName に webapprouting.kubernetes.azure.com を指定するのがポイントです。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: aks-helloworld
spec:
  ingressClassName: webapprouting.kubernetes.azure.com
  rules:
  - http:
      paths:
      - backend:
          service:
            name: aks-helloworld
            port:
              number: 80
        path: /
        pathType: Prefix

Key Vaultとの統合

KubernetesでIngressを利用する主な目的として、TLSの終端 があると思います。OSSのIngress NGINX Controllerであれば証明書と秘密鍵をKubernetesのSecretオブジェクトに格納して利用しますが、Application routing add-onではKey Vaultに格納した証明書を参照可能です。

learn.microsoft.com

以下のようにコマンドを実行することで、Key Vaultとの統合を有効化できます。

# Key VaultのリソースIDを取得
KEYVAULTID=$(az keyvault show --name <Key Vaultリソース名> --query "id" --output tsv)

# Application routing add-onのKey Vault統合を有効化
az aks approuting update -g <AKSリソースグループ名> -n <AKSクラスター名> --enable-kv --attach-kv ${KEYVAULTID}

--enable-kv オプションで Secrets Store CSI Driverが有効化され、

--attach-kv オプションでKey Vaultに対し必要なIAMの割り当てが行われます。

あとはIngressのマニフェストにいくつか記述を足すだけで、Key Vault内の証明書を利用できます。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: aks-helloworld
  annotations:
    kubernetes.azure.com/tls-cert-keyvault-uri: <Key Vault内の証明書のURI>
spec:
  ingressClassName: webapprouting.kubernetes.azure.com
  rules:
  - host: approute.example.com
    http:
      paths:
      - backend:
          service:
            name: aks-helloworld
            port:
              number: 80
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - approute.example.com
    secretName: keyvault-aks-helloworld    # ここで指定する secretNameの値は、"keyvault-" + Ingressリソースの名前(本例では「aks-helloworld」)とする必要がある

「Key Vault内の証明書のURI」は、Key Vaultの証明書リソースのIDから 末尾のIDを削除したもの を設定します。以下コマンドで取得可能です。

dirname `az keyvault certificate show --vault-name <Key Vault名> -n <証明書名> --query "id" --output tsv`

このマニフェストをデプロイすると、Key Vault内の証明書からKubernetesのSecretオブジェクトが生成されます。

kubectl get secret
NAME                      TYPE                DATA   AGE
keyvault-aks-helloworld   kubernetes.io/tls   2      26m

Secretと同名のDeploymentが作られていることも確認できます。

kubectl get deployment,pod
NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/aks-helloworld            1/1     1            1           3h44m
deployment.apps/keyvault-aks-helloworld   1/1     1            1           42m

NAME                                         READY   STATUS    RESTARTS   AGE
pod/aks-helloworld-688dbc9b4f-6hqzr          1/1     Running   0          3h44m
pod/keyvault-aks-helloworld-6ff9dd66-ht4cx   1/1     Running   0          42m

これはSecret Store CSI Driverの「PodからVolumeとしてKey Vaultをマウントした際にSecretオブジェクトを作成する」という仕様のため、Secretオブジェクトを作成するためだけのPodが起動するようです。 コンテナイメージは以下のPause用のイメージが使われており、消費されるリソース量としては無視できるレベルでしょう。

kubectl get pod keyvault-aks-helloworld-6ff9dd66-ht4cx -o jsonpath="{.spec.containers[*].image}"
mcr.microsoft.com/oss/kubernetes/pause:3.6-hotfix.20220114

Secret Store CSI Driverを利用する際の複雑な設定が簡略化されており、シンプルな設定でとても使いやすいです!

証明書の更新を自動的に反映する

Secret Store CSI Driverのデフォルトの挙動としては、Key Vault内の証明書が更新されたとしてもIngressには反映されません。
Key Vault内の証明書更新をトリガーとして自動で更新させたい場合は、Secret Store CSI Driverの 自動ローテーション 機能を有効化しましょう。

learn.microsoft.com

az aks addon update -g <AKSリソースグループ名> -n <AKSクラスター名> -a azure-keyvault-secrets-provider --enable-secret-rotation

Ingressリソースを作った後に上記の --enable-secret-rotation を実行した場合は、Ingressリソースを一度削除し再作成しないと有効にならないかもしれません。自動反映を利用する場合はIngressリソースを作成する前に上記コマンドを実行しておくとよいでしょう。
デフォルト設定では2分ごとにKey Vault内の証明書の更新をチェックし、更新されていればKubernetesのSecretの中身を更新してくれます。

Azure DNSの自動登録

もう1つの目玉機能がAzure DNSの自動登録です。パブリックなAzure DNS、プライベートなAzure Private DNSの両方に対応しています。この登録機能は、OSSの external-dns によるものです。

learn.microsoft.com

今回はAzure Private DNSで試してみます。

プライベートDNSゾーンを、以下のコマンドでApplication routing add-onとリンクさせます。

# プライベートDNSゾーンのリソースIDを取得
ZONEID=$(az network private-dns zone show -g <DNSゾーンリソースグループ名> -n <DNSゾーン名> --query "id" --output tsv)

# Application routing add-onにDNSゾーンをリンクさせる
az aks approuting zone add -g <AKSリソースグループ名> -n <AKSクラスター名> --ids=${ZONEID} --attach-zones

完了すると、DNSゾーンのIAMにAKSが利用するマネージドIDが追加されます。

が、プライベートDNSの場合はこのままだと機能しません。。。
AzureのDNSサービスはパブリックとプライベートで別扱いになっているようで、必要なIAMロールも別です。Application routing add-onによって自動で追加されるIAMロールはパブリック用のもので、これをプライベート用のものに変更してあげる必要があります。バグっぽい気がするのでそのうち修正されるとは思いますが、現状は手でIAMロールを修正してあげましょう。プライベート DNS ゾーンの共同作成者 が必要です。

設定が完了して暫く待つと、DNSレコードが登録されたことが確認できるはずです。デフォルトの設定では3分おきに変更をチェックしてDNSゾーンに反映してくれます。

うまく動いていないときは、app-routing-system 名前空間内に external-dns のPodが作られているので、このPodのログを見るといいでしょう。

おわりに

Ingressの導入が簡単にできる Application routing add-on の紹介でした。
これまでもOSSを組み合わせて同様のことは実現できましたが、Microsoftからコマンドひとつで導入できる形で提供されている のがポイントだと思います。以下のドキュメントでも、AKS でのイングレスには、アプリケーション ルーティング アドオンをお勧めします。 と記載されており、AKSでのIngressの第一選択肢としてよさそうです。

learn.microsoft.com

これからは標準でApplication routing add-on、Gateway APIを含めた高度な設定が必要な場合は Application Gateway for Containers という形になっていくと想像します。Application Gateway for Containersはまだプレビュー中のサービスですが、従来のApplication Gateway Ingress Controller を置き換える有用な選択肢になるサービスです。以下記事にて紹介していますので、併せて参照ください。

techblog.ap-com.co.jp

techblog.ap-com.co.jp

【PR】
私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。

www.ap-com.co.jp

一緒に働いていただける仲間も募集中です!
まだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。
我々の事業部のCultureDeckはコチラ。

www.ap-com.co.jp

本記事の投稿者: 吉川 俊甫
2024年もコンテナ中心でがんばります。 Microsoft MVP (Microsoft Azure)
Shunsuke Yoshikawa - Credly