Terraform AzAPI プロバイダーの概要

AzAPI プロバイダーは、 Azure ARM REST API の上にある薄いレイヤーです。 これにより、任意の API バージョンを使用して任意のAzure リソースの種類を管理でき、Azure内で最新の機能を使用できます。 AzAPI は、単独でも AzureRM プロバイダーとの連携でも使用できるように設計されている、優秀なプロバイダーです。

AzAPI プロバイダーを使用する利点

AzAPI プロバイダーには、次のような利点があります。

  • すべての Azure コントロール プレーン サービスをサポートします。
    • プレビュー サービスと機能
    • すべての API のバージョン
  • 完全な Terraform 状態ファイルの忠実性
    • プロパティと値はステートに保存される
  • Swagger への依存関係なし
  • 一般的で一貫性のある Azure 認証
  • 組み込みのプレフライト検証
  • インフラストラクチャ開発をきめ細かく制御する
  • Microsoft Terraform Visual Studio Code 拡張機能

リソース

更新を必要とせずにすべての Azure リソースと機能を管理できるようにするために、AzAPI プロバイダーには次の汎用リソースが含まれています。

リソース名 説明
azapi_resource 完全な CRUD を使用して Azure (コントロール プレーン) リソース (API) を完全に管理するために使用されます。
   利用事例の例
      新しいプレビュー サービス
      既存のサービスに追加された新機能
      ARM API を介してアクセスできる任意のAzure リソース
azapi_update_resource 完全な CRUD を持たないリソースまたはリソースの一部を管理するために使用される
   利用事例の例
      既存のサービスの新しいプロパティを更新する
      事前に作成された子リソース (DNS SOA レコードなど) を更新します。
azapi_resource_action リソースのライフサイクルを管理せずに、リソースに対して単一の操作を実行するために使用されます
   利用事例の例
      仮想マシンをシャットダウンする
      Key Vault にシークレットを追加する
azapi_data_plane_resource Azure データ プレーン リソースの特定のサブセットを管理するために使用されます
   利用事例の例
      KeyVault 証明書の連絡先
      Synapse ワークスペース ライブラリ

データ プレーン フレームワークのしくみと、コントロール プレーン リソースと parent_id の違いについて詳しくは、「 AzAPI データ プレーン フレームワークについて」をご覧ください。

使用階層

全体として、使用するには次の手順に従う必要があります。

  1. まず、 azapi_resource内でできるだけ多くの操作を実行します。
  2. リソース タイプが azapi_resource 内に存在せず、azapi_data_plane_resource でサポートされているタイプのいずれかに該当する場合は、代わりにそれを使用します。
  3. リソースが既に AzureRM に存在する場合、または azapi_resource 内でアクセスできないプロパティがある場合は、azapi_update_resource を使用してこれらの特定のプロパティにアクセスします。 azapi_resource または azapi_data_plane_resource でサポートされていないリソースは、このリソースを使用して更新することはできません。
  4. Azure CRUD 対応リソースに基づかないアクションを実行する場合、azapi_resource_actionazapi_update_resource ほど簡単ではありませんが、柔軟性は高くなります。

リソースの構成例

次のコード スニペットは、ARM API を介して直接Azure リソースを構成します。

resource "azapi_resource" "publicip" {
  type      = "Microsoft.Network/Customipprefixes@2021-03-01"
  name      = "exfullrange"
  parent_id = azurerm_resource_group.example.id
  location  = "westus2"

  body = {
    properties = {
      cidr          = "10.0.0.0/24"
      signedMessage = "Sample Message for WAN"
    }
  }
}

次のコード スニペットでは、AzureRM から既存のリソースのプレビュー プロパティを構成します。

resource "azapi_update_resource" "test" {
  type        = "Microsoft.ContainerRegistry/registries@2020-11-01-preview"
  resource_id = azurerm_container_registry.acr.id

  body = {
    properties = {
      anonymousPullEnabled = var.bool_anonymous_pull
    }
  }
}

次のコード スニペットでは、既存の AzureRM リソースに対するリソース アクションを構成しています。

resource "azapi_resource_action" "vm_shutdown" {
  type = "Microsoft.Compute/virtualMachines@2023-07-01"
  resource_id = azurerm_linux_virtual_machine.example.id
  action = "powerOff”
}

次のコード スニペットは、データ プレーンにプロビジョニングされているため、現在 AzureRM プロバイダーに存在しないリソースを構成しています。

resource "azapi_data_plane_resource" "dataset" {
  type      = "Microsoft.Synapse/workspaces/datasets@2020-12-01"
  parent_id = trimprefix(data.azurerm_synapse_workspace.example.connectivity_endpoints.dev, "https://")
  name      = "example-dataset"
  body = {
    properties = {
      type = "AzureBlob",
      typeProperties = {
        folderPath = {
          value = "@dataset().MyFolderPath"
          type  = "Expression"
        }
        fileName = {
          value = "@dataset().MyFileName"
          type  = "Expression"
        }
        format = {
          type = "TextFormat"
        }
      }
      parameters = {
        MyFolderPath = {
          type = "String"
        }
        MyFileName = {
          type = "String"
        }
      }
    }
  }
}

プレフライトの利用例

AzAPI の組み込みのプレフライト検証により、terraform plan 中に次のコード スニペット エラーが発生します。

provider "azapi" {
  enable_preflight = true
}
resource "azapi_resource" "vnet" {
  type      = "Microsoft.Network/virtualNetworks@2024-01-01"
  parent_id = azapi_resource.resourceGroup.id
  name      = "example-vnet"
  location  = "westus"
  body = {
    properties = {
      addressSpace = {
        addressPrefixes = [
          "10.0.0.0/160", # preflight will throw an error here
        ]
      }
    }
  }
}

有効にすると、適用時ではなく、 terraform plan 中にプレフライト サーフェスの構成エラーが発生します。

データ ソース

AzAPI プロバイダーは、さまざまな便利なデータ ソースをサポートしています。

データ ソース名 説明
azapi_resource 任意の Azure (コントロール プレーン) リソース (API) から情報を読み取るために使用されます。
   利用事例の例
      新しいプレビュー サービス
      既存のサービスに追加された新機能
      ARM API を介してアクセスできる任意のAzure リソース
azapi_client_config サブスクリプション ID やテナント ID などのクライアント情報にアクセスします。
azapi_resource_action リソースのライフサイクルを管理せずに、リソースに対して単一の読み取り操作を実行するために使用されます
   利用事例の例
      キーの一覧表示
      VM の状態を読み取る
azapi_data_plane_resource Azure データ プレーン リソースの 特定のサブセット にアクセスするために使用されます
   利用事例の例
      KeyVault 証明書の連絡先
      Synapse ワークスペース ライブラリ
azapi_resource_id サブスクリプション ID、親 ID、リソース グループ名、リソース名などの情報を出力する機能を使用して、リソースのリソース ID にアクセスします。
azapi_resource_list 特定の親リソース ID の下にあるすべてのリソースを一覧表示します。
   利用事例の例
      サブスクリプション/リソース グループの下のリソース
      仮想ネットワークの下のサブネット

JMESPath フィルター処理で azapi_resource_list を使用する実践的な例については、「List Azure resources with the AzAPI Terraform provider を参照してください。

azapi_resource データ ソースを使用して既存のリソースを読み取る

azapi_resource データ ソースは、任意のAzure リソースの現在の状態を読み取り、output 属性を介してそのプロパティを公開します。 AzureRM プロバイダーが公開しないプロパティが必要な場合に使用します。

data "azapi_resource" "aks" {
  type      = "Microsoft.ContainerService/managedClusters@2024-02-01"
  resource_id = azurerm_kubernetes_cluster.example.id

  # Extract the OIDC issuer URL, not exposed by azurerm_kubernetes_cluster
  response_export_values = ["properties.oidcIssuerProfile.issuerURL"]
}

output "oidc_issuer_url" {
  value = data.azapi_resource.aks.output.properties.oidcIssuerProfile.issuerURL
}

response_export_valuesと JMESPath を使用する

response_export_values は、生の ARM API 応答から抽出され、 output 属性で使用できるプロパティを制御します。 リストまたはマップを受け入れます。

  • リスト: 抽出する JSON プロパティ パスを指定します。 ["*"]を使用して、完全な応答本文をエクスポートします。
  • マップ: JMESPath 式を使用して、応答をフィルター処理して整形します。 キーは出力フィールド名です。値は JMESPath クエリです。

マップ フォームは、リストの応答と、出力を変換する必要がある場合に適しています。

data "azapi_resource_list" "storage_accounts" {
  type      = "Microsoft.Storage/storageAccounts@2023-01-01"
  parent_id = azurerm_resource_group.example.id

  response_export_values = {
    "names"     = "value[].name"
    "locations" = "value[].location"
  }
}

完全なチュートリアルについては、「List Azure resources with the AzAPI Terraform providerを参照してください。

AzAPI プロバイダーを使用した認証

AzAPI プロバイダーは、AzureRM プロバイダーと同じ認証方法を有効にします。 認証オプションの詳細については、「Azure への Terraform の認証」を参照してください。

AzAPI プロバイダーのエクスペリエンスとライフサイクル

このセクションでは、AzAPI プロバイダーの使用に役立ついくつかのツールについて説明します。

VS Code 拡張機能と言語サーバー

Microsoft Terraform VS Code 拡張機能 は、AzureRM プロバイダーと AzAPI プロバイダーの両方に次のような豊富な作成エクスペリエンスを提供します。

  • 使用可能なすべてのリソースの種類と API バージョンを一覧表示します。 使用可能なすべてのリソースの種類の一覧表示
  • 任意のリソースで許可されるプロパティと値のオートコンプリート。 許可されるプロパティの一覧表示
  • プロパティの上にマウス ポインターを置くと、ヒントが表示されます。 プロパティの上にマウス ポインターを置くと、ヒントが表示される
  • 構文検証 構文検証
  • コード サンプルを含むオートコンプリート。 コード サンプルを使用したオートコンプリート

拡張機能では、ARM JSON を azapi_resource ブロックに変換する AzAPI として貼り付け、aztfexport を使用した Azure リソースのエクスポート、AzureRM から AzAPI への移行、およびプレフライト検証もサポートされます。 完全なガイドについては、「 Microsoft Terraform VS Code 拡張機能を使用するを参照してください。

aztfmigrate 移行ツール

aztfmigrate ツール は、AzAPI プロバイダーと AzureRM プロバイダー間で既存のリソースを移行できるように設計されています。

aztfmigrate には、計画と移行の 2 つのモードがあります。

  • プランでは、移行できる AzAPI リソースが表示されます。
  • 移行では、HCL ファイルと状態の両方でAzAPI リソースを AzureRM リソースに移行します。

aztfmigrate、移行後に Terraform の構成と状態が実際の状態と一致することを保証します。 移行の完了後に terraform plan を実行して、変更が発生しなかった場合は、状態への更新を検証できます。

詳細なチュートリアルについては、「 AzAPI から AzureRM へのリソースの移行」を参照してください。

既存のAzure リソースをインポートする

既存のAzure リソースを再作成せずに AzAPI 管理の下に移動するには、import ブロック (Terraform 1.5 以降) または terraform import コマンドを使用します。 リソース ID には、クエリ パラメーターとして API バージョンを含める必要があります。

import {
  to = azapi_resource.example
  id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg/providers/Microsoft.Network/virtualNetworks/example-vnet?api-version=2023-11-01"
}

resource "azapi_resource" "example" {
  type      = "Microsoft.Network/virtualNetworks@2023-11-01"
  name      = "example-vnet"
  parent_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg"
  location  = "westus"
  body = {
    properties = {
      addressSpace = {
        addressPrefixes = ["10.0.0.0/16"]
      }
    }
  }
}

既存のAzure インフラストラクチャから複数のリソースを一度にインポートするには、Azure Export for Terraform (aztfexport) を使用します。これによって、HCL 構成とインポート ブロックの両方が自動的に生成されます。

インフラストラクチャに対するきめ細かい制御

AzAPI の主な利点の 1 つは、適切な設計パターンに合わせて構成を微調整できることです。 これにはいくつかの方法があります。

プロバイダー構成オプション

AzAPI プロバイダー ブロックは、構成内のすべてのリソースにグローバルに適用されるいくつかの設定を受け入れます。

オプション 説明
enable_preflight プラン時にプレフライト検証を有効にします。 既定値は false です。 詳細については、「 AzAPI Terraform プロバイダーでプレフライト検証を有効にする 」を参照してください。
ignore_no_op_changes 構成と正規化された API 応答の no-op の違いから、計画時のノイズを抑制します。 既定値は true です。
disable_default_output trueに設定すると、response_export_valuesが指定されていない場合、読み取り専用プロパティの自動出力が無効になります。 既定値は false です。
default_location 明示的に指定されていないすべてのリソースの既定の location を設定します。
default_tags すべてのリソースに適用される既定のタグを設定します。 リソース レベルの tags は、これらの既定値をオーバーライドします。
skip_provider_registration リソース プロバイダーの自動登録をスキップします。 制限された環境で true に設定します。

プロバイダー構成オプションの完全な一覧については、AzAPI プロバイダー スキーマを参照してください。

プレフライトを有効にするチュートリアルについては、「 AzAPI Terraform プロバイダーでプレフライト検証を有効にする」を参照してください。

プロバイダー関数

AzAPI v2.0 以降には、いくつかの プロバイダー関数が含まれています。

関数名 説明
build_resource_id 親 ID、リソースの種類、およびリソース名を指定して、Azure リソース ID を構築します。
特定のスコープ内で最上位レベルおよび入れ子になったリソースのリソース ID を作成する場合に便利です。
extension_resource_id 基本リソース ID、リソースの種類、その他のリソース名を指定して、Azure拡張機能リソース ID を構築します。
management_group_resource_id 管理グループ名、リソースの種類、およびリソース名を指定して、Azure 管理グループ スコープ リソース ID を構築します。
parse_resource_id この関数は、Azure リソース ID とリソースの種類を受け取り、その ID をサブスクリプション ID、リソース グループ名、プロバイダー名前空間、その他の部分などの個々のコンポーネントに解析します。
resource_group_resource_id サブスクリプション ID、リソース グループ名、リソースの種類、およびリソース名を指定して、Azure リソース グループ スコープリソース ID を構築します。
subscription_resource_id サブスクリプション ID、リソースの種類、およびリソース名を指定して、Azure サブスクリプション スコープのリソース ID を構築します。
tenant_resource_id リソースの種類とリソース名を指定して、Azure テナント スコープのリソース ID を構築します。

retry ブロックを使用したユーザー定義の再試行可能エラー

AzAPI プロバイダーは、 retry ブロックを介して予期されるエラーを処理します。 たとえば、リソースで作成タイムアウトが発生したときに再試行するには、次の構成を使用します。

resource "azapi_resource" "example" {
    # usual properties
    retry {
        interval_seconds     = 5
        randomization_factor = 0.5 # adds randomization to retry pattern
        multiplier           = 2 # if try fails, multiplies time between next try by this much
        error_message_regex  = ["ResourceNotFound"]
    }
    timeouts {
        create = "10m"
}

retry ブロックは、次の属性を受け入れます。

Attribute 説明
error_message_regex 必須。 エラー メッセージと一致する正規表現の一覧。 任意の式が一致すると、要求が再試行されます。
interval_seconds 再試行間の基本待機時間。 既定値は 10 です。
max_interval_seconds 再試行間の最大待機時間。 既定値は 180 です。
multiplier 試行が失敗するたびに間隔に適用される乗数。 既定値は 1.5 です。
randomization_factor 雷が鳴るパターンを回避するために、再試行間隔にジッターを追加します。 既定値は 0.5 です。

retrytimeouts ブロックと組み合わせて、合計再試行時間の上限を設定します。

timeouts {
  create = "10m"
}

エフェメラル リソースと書き込み専用プロパティ

AzAPI v2.x では、sensitive_bodyazapi_resource 属性を使用した書き込み専用引数 (Terraform 1.11 以降) がサポートされています。 書き込み専用プロパティは ARM API に送信されますが、Terraform 状態には格納されません。これはシークレットと資格情報に役立ちます。

resource "azapi_resource" "example" {
  type      = "Microsoft.SomeService/resources@2024-01-01"
  name      = "example"
  parent_id = azurerm_resource_group.example.id

  body = {
    properties = {
      name = "example"
    }
  }

  # Write-only — not stored in state
  sensitive_body = {
    properties = {
      adminPassword = var.admin_password
    }
  }
}

sensitive_body_versionを使用して、書き込み専用プロパティを API に再送信するタイミングを制御します (資格情報のローテーション時など)。

リソース置換のトリガー

AzAPI プロバイダーを使用すると、リソース置換のパラメーターを構成できます。

replace_triggers_external_values

値が変更された場合にリソースを置き換えます。 たとえば、SKU またはゾーンの変数を変更する場合、このリソースは再作成されます。

resource "azapi_resource" "example" {
  name      = var.name
  type      = "Microsoft.Network/publicIPAddresses@2023-11-01"
  parent_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example"
  body      = properties = {
    sku   = var.sku
    zones = var.zones
  }
  replace_triggers_external_values = [
    var.sku,
    var.zones,
  ]
}

このトリガーは、定義のプロパティが変更されたときのポリシー割り当てなど、広範なリソース セットで機能します。

replace_triggers_refs

参照される値が変更された場合に、リソースを置き換えます。 たとえば、SKU 名または層が変更された場合、このリソースは再作成されます。

resource "azapi_resource" "example" {
  type      = "Microsoft.Relay/namespaces@2021-11-01"
  parent_id = azurerm_resource_group.example.id
  name      = "xxx"
  location  = "westus"
  body = {
    properties = {
    }
    sku = {
      name = "Standard"
      tier = "Standard"
    }
  }

  replace_triggers_refs = ["sku"]
}

これにより、別のリソースの SKU が変更されても、置換はトリガーされません。

次のステップ