はじめに
こんにちは、ACS事業部の吉川です。
Azure Kubernetes Service(AKS)でIngressを使いたいとき、皆さんはどんなIngress Controllerをお使いでしょうか?
Ingress NGINX Controller ?Application Gateway Ingress Controller?それとも、Istio?
昨年の11月に、AKSのIngressとして利用できる Application routing add-on がGAしましたので、本記事でご紹介します。
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のインストール方法は以下のドキュメントにて公開されています。
現状では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に格納した証明書を参照可能です。
以下のようにコマンドを実行することで、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の 自動ローテーション 機能を有効化しましょう。
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 によるものです。
今回は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の第一選択肢としてよさそうです。
これからは標準でApplication routing add-on、Gateway APIを含めた高度な設定が必要な場合は Application Gateway for Containers という形になっていくと想像します。Application Gateway for Containersはまだプレビュー中のサービスですが、従来のApplication Gateway Ingress Controller を置き換える有用な選択肢になるサービスです。以下記事にて紹介していますので、併せて参照ください。
【PR】
私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。
一緒に働いていただける仲間も募集中です!
まだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。
我々の事業部のCultureDeckはコチラ。