Slide 1

Slide 1 text

俺とAzureとTerraform ~2024新春バージョン~ Toru Makabe Senior Cloud Solution Architect Microsoft

Slide 2

Slide 2 text

俺とAzureとTerraform TerraformをAzure ARMで使う時の認証 - re-imagine (torumakabe.github.io) 8年前

Slide 3

Slide 3 text

いまや Terraformなしの Azure環境構築なんて 考えられません (案件によってはBicepも使います)

Slide 4

Slide 4 text

とはいえ課題もある  AzureRMプロバイダの巨大化  コードの規模だけでなく、ユーザ数も増加  破壊的/大胆な変更には慎重な姿勢 (対応はメジャーバージョンアップ待ち、という不具合もいくつか)  Azure新サービス、機能への追従  すぐに対応されるわけではない  Issueでのリクエスト、Pull Requestをもとにメンテナが優先度づけ  「Terraformが対応するタイミングが、こなれて使い頃」という通の意見もある  「期待されている/使われているサービスや機能がわかる」という通の意見もある  テストをどうするか問題  Azure、Terraformに限らず、IaCの一般的な課題 hashicorp/azurerm | Terraform Registry (2024/1/29)

Slide 5

Slide 5 text

お伝えしたいこと • AzAPIプロバイダを活用しよう • AzureRMプロバイダを補完する、便利な懐刀 • 新サービスや機能への対応、不具合からの一時避難に使える • AzureRMプロバイダではできない、発展的な使い方も • テストを見直そう • HashiCorpもテスト機能やガイドラインの提供を本格化 • 無理せず「こういうのでいいんだよ」なテストを考えよう • 事前にいただいた質問に答えます

Slide 6

Slide 6 text

AzAPIプロバイダを活用する

Slide 7

Slide 7 text

(ご参考)Bicep/ARMテンプレート デプロイ概要 Bicep JSON (ARM Template) Azure Resource Manager API コンパイル すべてのリソース操作を1つ のAPIコールにまとめる • ARM(Azure Resource Manager) APIに対し、まとめて JSONを投げる • リソース操作の順序制御などは ARM側で行う • 新サービスや機能のAPI公開後、 すぐに使える • ARM(Azure)以外には使えない

Slide 8

Slide 8 text

Terraform & Azure概要 HCL Terraform Core Azure Resource Manager API • リソース操作の順序制御な どはTerraformが行う • 各APIの操作はそれぞれの プロバイダが行う • 新サービスや機能は、プロバ イダの対応後に使える • Azureに限らず、異なるプロ バイダを組み合わせて使える AzureRM Provider Other Provider Other API リソース操作ごとに APIをコール プラグイン

Slide 9

Slide 9 text

AzAPIプロバイダとは AzAPI プロバイダーは、 Azure ARM REST API の上にある薄いレイヤーです。 AzAPI プロバイダーを使用すると、任意の API バージョンを使用して任意の Azure リソースの種類を管理できます。 このプロバイダーは、新しい Azure リソースとプロパティ (プライベート プレビューを含 む) の管理を有効にすることで、AzureRM プロバイダーを補完します。 Terraform AzAPI プロバイダーの概要 | Microsoft Learn

Slide 10

Slide 10 text

Azure公式のIaCリファレンスでは すでに一級市民扱い Azure リソース リファレンス - Bicep, ARM template & Terraform AzAPI reference | Microsoft Learn Microsoft.Storage/storageAccounts - Bicep, ARM template & Terraform AzAPI reference | Microsoft Learn

Slide 11

Slide 11 text

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関数で変換できる) 他のリソースで参照したい属性を エクスポートする

Slide 12

Slide 12 text

発展的: 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プロバイダは、 コンテナの実行結果など推移的な 情報は取れない)

Slide 13

Slide 13 text

発展的: リソース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

Slide 14

Slide 14 text

AzureRMとAzAPIの比較 AzureRM AzAPI オーナー HashiCorp Microsoft 位置付け Azure向けの主プロバイダ AzureRMの補完 対応Azureリソース、機能 AzureRMとして対応済みのものに限る API公開されているものすべて HCLの書きやすさ 〇 VS Code拡張による補完が可能 △ • VS Code拡張による補完が可能 • APIバージョンなど、記述する属性が多い • 属性値の参照にJSONデコードが必要など、 ひと手間必要 取得できるリソース情報 〇 リソース構成に関するものは取得可能 ◎ ARM APIへのGETで取れる値すべて リソースに対するCRUD以外の 操作 × 〇 データプレーン操作やリソース固有のaction APIコールが可能

Slide 15

Slide 15 text

このふたつ 組み合わせれば アレできる HCL Terraform Core Azure Resource Manager API AzureRM Provider AzAPI Provider メイン • 書くのが楽 補完 • AzureRM未対応サービ スや機能 • バグや不具合のあるリ ソースの一時避難先 • CRUD以外の操作

Slide 16

Slide 16 text

AzAPI よくある質問 #1 Q: Plan時に正しく差分はとれますか? HCLを変えていないのに、常に”change” と表示されます A: はい、とれます。ただしシークレットなどセンシティブな属性、大文字/小文字が 影響して差分ありと認識される場合があります。これを避けるには `ignore_missing_property`、`ignore_casing`属性を`true`に設定してください AzAPI Provider: Frequently asked questions | Guides | Azure/azapi | Terraform | Terraform Registry

Slide 17

Slide 17 text

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など何度も使う値はベ タ書きせず、変数やリソースの参照で補間する

Slide 18

Slide 18 text

テストを見直そう

Slide 19

Slide 19 text

HashiCorpの考えるTerraformのテスト  最近テスト関連機能が拡充された  checkブロック(1.5)  testコマンド(1.6)  testコマンド mock(1.7)  あわせて、HashiCorpがTerraform のテストをどのように考えているのか、 ドキュメントが公開された  ツールの作り手がどのように考えているのかを知る ことは、とても重要 Testing HashiCorp Terraform

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

terraform test パターン整理 command = plan command = apply(既定) 実プロバイダ 実リソース作成: なし サンプル実行時間: 21秒 実リソース作成: あり サンプル実行時間: 157秒 mockプロバイダ 実リソース作成: なし サンプル実行時間: 9秒 実リソース作成: なし サンプル実行時間: 18秒 考慮点 apply後に得られる値はconditionで チェックできない ※実行したサンプルテスト: Azureのリソースグループ1個と、その”name”のassert

Slide 24

Slide 24 text

トール・マカベッチ いまのお気持ち  Unitテストにはグッときていない  関数の駆使など、凝ったHCLを書くならやるかも(いまはそう書かないポリシー)  テストコード作成維持の負担が、得られる価値を上回る気もする  別途、静的解析はしたい  tflintなど  testコマンドでのインテグレーションテストは積極的に行いたい  実リソースを作らないとわからない問題は多い(Unitテストでは見つからない)  これまではシェルスクリプトやプログラムで自作していたが、標準のしくみができたのは大きい  testコマンドでテストしやすいようにHCLを書いていくムーブまである  checkブロック、これはいいものだ  test、apply時に常に簡易なe2eテストを実行できる(Continuous Validation)  テスト/環境構築時、いちいちcurlを手打ちして確認せずに済む

Slide 25

Slide 25 text

サンプル実装を公開しました 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コンテナで 疎通チェック

Slide 26

Slide 26 text

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コンテナの実行が 成功したかをチェック

Slide 27

Slide 27 text

事前にいただいた 質問への回答

Slide 28

Slide 28 text

事前にいただいた質問 #1 Q: 標準的なガイドラインを作りたいのですが、参考になる資料はありますか? A: IaCツールに限らない、はじめの一歩として、Microsoft Azure Well- Architected Frameworkの「コードとしてのインフラストラクチャの使用に関する推 奨事項」がおすすめです

Slide 29

Slide 29 text

事前にいただいた質問 #2 Q: Terraformで環境構築をしたのですが、その後ポータルでの運用中心になって しまい、Terraformのコードは更新できていません。今後を考えると現状を Terraformのコードに反映しておきたいのですが、いい方法はありますか? A: まずplanして、現状との差分をみてください。差分が少量であれば、手作業で 現状を反映してもいいでしょう。importするという手もあります。なお、使っている AzureRMプロバイダのバージョンによっては、バージョンアップ対応が必要です。 ただし、これまで更新できていなかったということは、チームの習熟度に不安がある のではないでしょうか。少し苦労しても、手作業での変換やテスト環境の整備を 通じ、スキルアップしたほうがいいかもしれません。

Slide 30

Slide 30 text

事前にいただいた質問 #3 Q: バージョンに追従する方法はありますか? A: Terraform Core、プロバイダともに、新サービスや機能の利用、不具合対応 などの必要がなければ、頑張って最新を追いかけなくてもよいと思います。 が、突然新バージョンがリリースされて利用中のバージョンがコードfix対象から外れ ることはよくあります。また、新バージョンの影響はリリース内容を見ないとわかりま せん。よって、「3か月バージョンアップの機会がなければ、実施する」などバージョン アップのリズムを決めておき、チームとしてバージョンアップ能力を維持し続けること をおすすめします。

Slide 31

Slide 31 text

事前にいただいた質問 #4 Q: terraform実行時のentraとADB2Cテナントの認証方式について A: AzureRM、AzAPIともにEntra IDのセキュリティプリンシパル(ユーザやサービス プリンシパル、マネージドIDなど)で認証します。OpenID Connectでフェデレー ションも可能です。加えて、セキュリティプリンシパルへ操作対象のリソース、スコー プに対する権限付与(RBAC)が要ります。 実行時に環境変数に設定する値で、認証方式が決定されます。なお、システム 割り当てマネージドID、CLIの認証情報を使いたい場合は、環境変数の設定は 不要です。詳細はドキュメントを参照してください。 Docs overview | hashicorp/azurerm | Terraform | Terraform Registry

Slide 32

Slide 32 text

Thank you