Terraform を使って Azure Kubernetes Service (AKS) で AGIC を動かす機会があったので、ハマりポイントを記録しておきます。
AGIC とは
Application Gateway Ingress Controller (AGIC) は、Azure ネイティブの L7 ロードバランサ Application Gateway を利用した AKS で動作する Ingress Controller です。
AGIC を使うことで、AKS で Application Gateway の機能(URL ルーティングや TLS 終端)を使うことができます。 また、AKS クラスタ外の Application Gateway がオートスケールするため、トラフィックの増減に対してクラスタでのリソース消費がありません。
この機能を使うためには、Azure に AKS と Application Gateway、そして Public IP のリソースをデプロイする必要があります。
Terraform から Application Gateway を作成する方法として 2 パターンあります。
- Application Gateway と Public IP のリソースタイプを指定する
- AKS のリソースタイプで Application Gateway を指定する
ちなみに、利用した Terraform のバージョンは以下になります(バージョン古いと怒られていますね…)。
$ terraform version
Terraform v1.2.7
on linux_amd64
Your version of Terraform is out of date! The latest version
is 1.3.3. You can update by downloading from https://www.terraform.io/downloads.html
ハマりポイント
今回は「Application Gateway と Public IP のリソースタイプを指定する」パターンで マネージド ID が Application Gateway の編集権限を持っていない という事象にハマってしまいました。
どのようにしてハマったか説明していきます。
まず、Terraform から各リソースを作成するために、以下のような tf ファイルを使用しました。 説明で不要な部分やリソースグループなどの記述は省略しています。
resource "azurerm_public_ip" "pip" {
name = local.pip_name
resource_group_name = local.rg_name
location = local.location
allocation_method = "Static"
sku = "Standard"
}
resource "azurerm_application_gateway" "agw" {
name = local.agw_name
resource_group_name = local.rg_name
location = local.location
sku {
name = "Standard_v2"
tier = "Standard_v2"
capacity = 2
}
frontend_ip_configuration {
name = "appGatewayFrontendIP"
public_ip_address_id = azurerm_public_ip.pip.id
}
}
resource "azurerm_kubernetes_cluster" "aks" {
name = local.aks_name
resource_group_name = local.rg_name
location = local.location
ingress_application_gateway {
gateway_id = azurerm_application_gateway.agw.id
}
}
この tf ファイルを見てもらったら分かる通り、AKS/Application Gateway/Puliic IP の各リソースを同じリソースグループに作成しています。
Terraform とは関係ないですが、AKS を作成すると AKS のリソースグループとは別に管理用の「ノードリソースグループ」が作られます(デフォルトのリソース名は MC_<RG 名>_<AKS 名>_<リージョン>
)。
ノードリソースグループには AKS で利用されるノードプールなどのリソースが格納されていて、Azure 側で管理されています。
上記 tf ファイルの場合、ノードリソースグループに AGIC 用のマネージド ID も作られます。 AGIC を有効にした AKS クラスタで Ingress リソースを作成/更新/削除すると、このマネージド ID が Application Gateway リソースを更新しようとします。
しかし、当該マネージド ID には Application Gateway が存在するリソースグループへの編集権限がないため、Application Gateway を更新できずにいつまで経っても Ingress へ Public IP が割り当てられません。
対処方法
前述のハマりポイントへの対処を 3 案考えました。
- マネージド ID にリソースグループへの編集権限を付与
- Terraform でマネージド ID へロール割り当てる
- Terraform の AKS のリソースタイプで Application Gateway を指定
案 1 は一番手っ取り早いですが、Terraform の管理から離れてしまっているため NG です。
案 2 も挑戦したのですが、うまくマネージド ID の情報を取得することができずに諦めました…。
案 3 が現実的な対処方法かと思うので、そちらの内容を説明します。
前述とは異なり、tf ファイルには Application Gateway と Public IP のリソースタイプは不要です。
AKS のリソースタイプのみですが、ingress_application_gateway
ブロックの内部を変更しています。
具体的には、個別に作成した Application Gateway を指定する gateway_id
を、gateway_name
と subnet_id
に変更しています。
resource "azurerm_kubernetes_cluster" "aks" {
name = local.aks_name
resource_group_name = local.rg_name
location = local.location
ingress_application_gateway {
gateway_name = local.agw_name
subnet_id = local.subnet_agw_id
}
}
これにより、AKS 作成とともに Application Gateway と Public IP が作られます。 さらに言うと、上記 2 リソースは AKS 管理用のノードリソースグループに作成されます。
AGIC 用のマネージド ID は自身のリソースグループに対する編集権限を持っているので、Application Gateway を変更できるというわけです。
おまけ
AGIC が有効になっている AKS では kube-system
Namespace で ingress-appgw-deployment
Pod が動いています。
この Pod には Application Gateway を変更するログが出力されるため、トラブルシュートの際はこちらを確認するのがよさそうです。
今回ハマった際には「以下のコマンドで権限付与してね」といった内容のエラーログが出力されていました。
az role assignment create \
--role Reader \
--scope /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg \
--assignee 00000000-0000-0000-0000-000000000000; \
az role assignment create \
--role Contributor \
--scope /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg/providers/Microsoft.Network/applicationGateways/agw \
--assignee 00000000-0000-0000-0000-000000000000