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 パターンあります。

  1. Application Gateway と Public IP のリソースタイプを指定する
  2. 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 案考えました。

  1. マネージド ID にリソースグループへの編集権限を付与
  2. Terraform でマネージド ID へロール割り当てる
  3. Terraform の AKS のリソースタイプで Application Gateway を指定

案 1 は一番手っ取り早いですが、Terraform の管理から離れてしまっているため NG です。

案 2 も挑戦したのですが、うまくマネージド ID の情報を取得することができずに諦めました…。

案 3 が現実的な対処方法かと思うので、そちらの内容を説明します。

前述とは異なり、tf ファイルには Application Gateway と Public IP のリソースタイプは不要です。 AKS のリソースタイプのみですが、ingress_application_gateway ブロックの内部を変更しています。

具体的には、個別に作成した Application Gateway を指定する gateway_id を、gateway_namesubnet_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

参照リンク