Upgrade to Pro — share decks privately, control downloads, hide ads and more …

俺とAzureとTerraform ~2024新春バージョン~

Toru Makabe
February 02, 2024
1.4k

俺とAzureとTerraform ~2024新春バージョン~

※リンクを効かせたい場合はダウンロードしてください

Toru Makabe

February 02, 2024
Tweet

Transcript

  1. とはいえ課題もある  AzureRMプロバイダの巨大化  コードの規模だけでなく、ユーザ数も増加  破壊的/大胆な変更には慎重な姿勢 (対応はメジャーバージョンアップ待ち、という不具合もいくつか)  Azure新サービス、機能への追従

     すぐに対応されるわけではない  Issueでのリクエスト、Pull Requestをもとにメンテナが優先度づけ  「Terraformが対応するタイミングが、こなれて使い頃」という通の意見もある  「期待されている/使われているサービスや機能がわかる」という通の意見もある  テストをどうするか問題  Azure、Terraformに限らず、IaCの一般的な課題 hashicorp/azurerm | Terraform Registry (2024/1/29)
  2. お伝えしたいこと • AzAPIプロバイダを活用しよう • AzureRMプロバイダを補完する、便利な懐刀 • 新サービスや機能への対応、不具合からの一時避難に使える • AzureRMプロバイダではできない、発展的な使い方も •

    テストを見直そう • HashiCorpもテスト機能やガイドラインの提供を本格化 • 無理せず「こういうのでいいんだよ」なテストを考えよう • 事前にいただいた質問に答えます
  3. (ご参考)Bicep/ARMテンプレート デプロイ概要 Bicep JSON (ARM Template) Azure Resource Manager API

    コンパイル すべてのリソース操作を1つ のAPIコールにまとめる • ARM(Azure Resource Manager) APIに対し、まとめて JSONを投げる • リソース操作の順序制御などは ARM側で行う • 新サービスや機能のAPI公開後、 すぐに使える • ARM(Azure)以外には使えない
  4. Terraform & Azure概要 HCL Terraform Core Azure Resource Manager API

    • リソース操作の順序制御な どはTerraformが行う • 各APIの操作はそれぞれの プロバイダが行う • 新サービスや機能は、プロバ イダの対応後に使える • Azureに限らず、異なるプロ バイダを組み合わせて使える AzureRM Provider Other Provider Other API リソース操作ごとに APIをコール プラグイン
  5. AzAPIプロバイダとは AzAPI プロバイダーは、 Azure ARM REST API の上にある薄いレイヤーです。 AzAPI プロバイダーを使用すると、任意の

    API バージョンを使用して任意の Azure リソースの種類を管理できます。 このプロバイダーは、新しい Azure リソースとプロパティ (プライベート プレビューを含 む) の管理を有効にすることで、AzureRM プロバイダーを補完します。 Terraform AzAPI プロバイダーの概要 | Microsoft Learn
  6. Azure公式のIaCリファレンスでは すでに一級市民扱い Azure リソース リファレンス - Bicep, ARM template &

    Terraform AzAPI reference | Microsoft Learn Microsoft.Storage/storageAccounts - Bicep, ARM template & Terraform AzAPI reference | Microsoft Learn
  7. AzAPI記述例 resource "azapi_resource" "example" { type = "Microsoft.ContainerRegistry/registries@2020-11-01-preview" name =

    "registry1" parent_id = azurerm_resource_group.example.id location = azurerm_resource_group.example.location body = jsonencode({ sku = { name = "Standard" } properties = { adminUserEnabled = true } }) response_export_values = ["properties.loginServer", "properties.policies.quarantinePolicy.status"] } APIバージョンは明示す る必要あり bodyはJSONで記述(HCLから jsonencode関数で変換できる) 他のリソースで参照したい属性を エクスポートする
  8. 発展的: AzureRMプロバイダで取れない属性値を取れる data "azapi_resource" “ci_nginx" { name = "ci-nginx" parent_id

    = azurerm_resource_group.apc_tf_meetup.id type = "Microsoft.ContainerInstance/containerGroups@2023-05-01" response_export_values = ["properties.instanceView.state"] } ARM APIでGETできる値を取れる (いっぽうでAzureRMプロバイダは、 コンテナの実行結果など推移的な 情報は取れない)
  9. 発展的: リソースCRUD関連以外のAPIもコールできる resource "azapi_resource_action" "ci_nginx" { type = "Microsoft.ContainerInstance/containerGroups@2023-05-01" resource_id

    = azurerm_container_group.ci_nginx.id action = "start" } 実行後に停止(Terminated) したコンテナを再実行するaction APIをコールできる azapi_resource_action | Resources | Azure/azapi | Terraform | Terraform Registry
  10. AzureRMとAzAPIの比較 AzureRM AzAPI オーナー HashiCorp Microsoft 位置付け Azure向けの主プロバイダ AzureRMの補完 対応Azureリソース、機能

    AzureRMとして対応済みのものに限る API公開されているものすべて HCLの書きやすさ 〇 VS Code拡張による補完が可能 △ • VS Code拡張による補完が可能 • APIバージョンなど、記述する属性が多い • 属性値の参照にJSONデコードが必要など、 ひと手間必要 取得できるリソース情報 〇 リソース構成に関するものは取得可能 ◎ ARM APIへのGETで取れる値すべて リソースに対するCRUD以外の 操作 × 〇 データプレーン操作やリソース固有のaction APIコールが可能
  11. このふたつ 組み合わせれば アレできる HCL Terraform Core Azure Resource Manager API

    AzureRM Provider AzAPI Provider メイン • 書くのが楽 補完 • AzureRM未対応サービ スや機能 • バグや不具合のあるリ ソースの一時避難先 • CRUD以外の操作
  12. AzAPI よくある質問 #2 Q: AzureRMとAzAPI間でHCLやstateを変換するツールはありますか? A: あります。AzureRM -> AzAPIではTerraformのimportブロックによるコード 生成が、AzAPI

    -> AzureRMではazapi2azurermが役に立つでしょう ただし、bodyのJSONや属性値は、エスケープシーケンス除去やTerraformの補 間(Interpolation)なくベタ書きで変換されます。ツールだけで完結しないと覚 悟しておきましょう。 resource "azurerm_application_gateway" "agw" { location = "eastus" name = "agw-default" resource_group_name = "rg-apc-tf-meetup" azapi2azurermによる変換例 一般的には保守性を考慮し、locationや resouce_group_nameなど何度も使う値はベ タ書きせず、変数やリソースの参照で補間する
  13. HashiCorpの考えるTerraformのテスト  最近テスト関連機能が拡充された  checkブロック(1.5)  testコマンド(1.6)  testコマンド mock(1.7)

     あわせて、HashiCorpがTerraform のテストをどのように考えているのか、 ドキュメントが公開された  ツールの作り手がどのように考えているのかを知る ことは、とても重要 Testing HashiCorp Terraform
  14. checkブロック check "health_check" { data "http" "terraform_io" { url =

    "https://www.terraform.io" } assert { condition = data.http.terraform_io.status_code == 200 error_message = "${data.http.terraform_io.url} returned an unhealthy status code" } }  plan、applyの最後に実行される  後述のtestコマンドでも実行される  HashiCorpはe2eテスト向けと位置 付けている  インフラはエラーなく作成できたが、ア プリケーションとしては動かなかった、 というケースは多く、非常に有用  環境全体で見るとネットワーク周りの設定が妥 当でない、というケースが典型的  網羅的なe2eテストでなくとも、左のサンプルコー ドのようにHTTPの疎通確認だけで価値はある Checks - Configuration Language | Terraform | HashiCorp Developer
  15. testコマンド variables { rg_name = "rg-apc-tf-meetup-test" } run "sets_correct_name" {

    command = plan assert { condition = azurerm_resource_group.apc_tf_meetup.name == "rg-apc-tf-meetup-test" error_message = "incorrect rg name" } }  テスト定義ファイルを別途書き実行  左のサンプルコードはリソースグループを作成する HCLに対するテストの例  テスト向けに変数を設定できる  applyしない”command = plan”指定も可能 (既定はapply)  既存リソースやstateには影響なし  テスト中はメモリ上にstateを持つ  リソース名は衝突しないように注意  テスト終了後にリソースは削除  明示的にdestroyする必要なし(継続できない エラーで終了した場合には必要) Tests - Configuration Language | Terraform | HashiCorp Developer
  16. testコマンド(mockの利用) mock_provider "azurerm" {} run "sets_correct_name" { variables { rg_name

    = "rg-apc-tf-meetup-test" } assert { condition = azurerm_resource_group.apc_tf_meetup.name == "rg-apc-tf-meetup-test" error_message = "incorrect rg name" } }  mockプロバイダの利用を明示  プロバイダがmockを使うようになる  クラウドのAPIにアクセスしない(早い)  mockの返す値に注意  値をセットしなかった属性はデフォルト値になる (0、false、ランダム文字列など)  リソースの種類ごとに既定値を設定できる  オーバーライドも可能 Tests - Provider Mocking | Terraform | HashiCorp Developer
  17. terraform test パターン整理 command = plan command = apply(既定) 実プロバイダ

    実リソース作成: なし サンプル実行時間: 21秒 実リソース作成: あり サンプル実行時間: 157秒 mockプロバイダ 実リソース作成: なし サンプル実行時間: 9秒 実リソース作成: なし サンプル実行時間: 18秒 考慮点 apply後に得られる値はconditionで チェックできない ※実行したサンプルテスト: Azureのリソースグループ1個と、その”name”のassert
  18. トール・マカベッチ いまのお気持ち  Unitテストにはグッときていない  関数の駆使など、凝ったHCLを書くならやるかも(いまはそう書かないポリシー)  テストコード作成維持の負担が、得られる価値を上回る気もする  別途、静的解析はしたい

     tflintなど  testコマンドでのインテグレーションテストは積極的に行いたい  実リソースを作らないとわからない問題は多い(Unitテストでは見つからない)  これまではシェルスクリプトやプログラムで自作していたが、標準のしくみができたのは大きい  testコマンドでテストしやすいようにHCLを書いていくムーブまである  checkブロック、これはいいものだ  test、apply時に常に簡易なe2eテストを実行できる(Continuous Validation)  テスト/環境構築時、いちいちcurlを手打ちして確認せずに済む
  19. サンプル実装を公開しました Container Apps  IaCでよくあるトラブル  リソースをエラーなく作成できても、アプリケーションを動か してから設定ミスが判明するケースがある  NSG、Private

    DNS、Application GatewayのPathベー スルーティングの設定などは典型例  checkブロックでHTTP疎通結果を確認  Terraform実行環境がアプリケーションのエンドポイントが ある仮想ネットワークにつながっていないケースがある  よってAzure Container Instance(ACI)を仮想ネット ワーク内で動かし、curlで疎通確認する  孤立したサンドボックス環境でもe2eテストが可能  いちいち手作業で確認しなくていい  AzAPIプロバイダでACIの実行ステータスをチェックしている (後述) Path Based Routing torumakabe/apc-tf-meetup (github.com) curlコンテナで 疎通チェック
  20. AzAPIでリソースの詳細情報を取得する check "nginx" { data "azapi_resource" "ci_check_nginx" { depends_on =

    [azurerm_container_group.check_nginx] name = "ci-check-nginx" parent_id = azurerm_resource_group.apc_tf_meetup.id type = "Microsoft.ContainerInstance/containerGroups@2023-05-01" response_export_values = ["properties.instanceView.state"] } assert { condition = jsondecode(data.azapi_resource.ci_check_nginx.output).properties.instanceView.state == "Succeeded" error_message = "curl check failed: to nginx. if state is Running, it is possible that the test just did not finish in time, please re-run it!" } } AzureRMプロバイダではACIコンテナの実行結 果を取得できないが、AzAPIなら可能 curlコンテナの実行が 成功したかをチェック
  21. 事前にいただいた質問 #4 Q: terraform実行時のentraとADB2Cテナントの認証方式について A: AzureRM、AzAPIともにEntra IDのセキュリティプリンシパル(ユーザやサービス プリンシパル、マネージドIDなど)で認証します。OpenID Connectでフェデレー ションも可能です。加えて、セキュリティプリンシパルへ操作対象のリソース、スコー

    プに対する権限付与(RBAC)が要ります。 実行時に環境変数に設定する値で、認証方式が決定されます。なお、システム 割り当てマネージドID、CLIの認証情報を使いたい場合は、環境変数の設定は 不要です。詳細はドキュメントを参照してください。 Docs overview | hashicorp/azurerm | Terraform | Terraform Registry