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

AzureでのIaC - Bicep? Terraform? それ早く言ってよ会議

Avatar for Toru Makabe Toru Makabe
February 06, 2026

AzureでのIaC - Bicep? Terraform? それ早く言ってよ会議

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

Avatar for Toru Makabe

Toru Makabe

February 06, 2026
Tweet

More Decks by Toru Makabe

Other Decks in Technology

Transcript

  1. 概要 Bicep Terraform 開発主体 Microsoft HashiCorp ライセンス MIT BSL 1.1

    管理対象クラウドサービス Azure マルチクラウド 言語 Bicep DSL HCL(HashiCorp Configuration Language) JSON 状態管理 なし(ステートレス) 状態ファイル マネージドサービス あり(Azure標準機能) あり(HCP Terraform) 公式ドキュメントでの比較: Terraform と Bicep の比較 | Microsoft Learn
  2. Bicep 構成要素 Bicep JSON (ARM Template) Azure Resource Manager API

    コンパイル (トランスパイル) すべてのリソース操作を1つ のDeployment APIコール にまとめる • ARM(Azure Resource Manager) APIに対し、 まとめてJSONを投げる • リソース操作の順序制御などはARM側で行う • 新サービスや機能のAPI公開後、すぐに使える • 原則、ARMが管理するリソースのみを対象とする • 例外: Microsoft Graph Bicep拡張 Azure CLI /Bicep CLI
  3. Terraform & Azure 構成要素 HCL Terraform Core Azure Resource Manager

    API • リソース操作の順序制御などは Terraformが行う • 各APIの操作はそれぞれのプロバイ ダが行う • 新サービスや機能は、プロバイダの 対応後に使える • Azureに限らず、異なるプロバイダを 組み合わせて使える • Azure向けプロバイダ • AzureRM • AzureAD • AzAPI AzureRM Provider Other Provider Other API リソース操作ごとに APIをコール プラグイン State (JSON) Terraform
  4. Bicep 例: ストレージアカウント resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { name: 'storageaccountname'

    location: resourceGroup().location sku: { name: 'Standard_LRS' } kind: 'StorageV2' tags: { environment: 'dev' } } リソースタイプと APIバージョンを明示
  5. Bicepの特徴  Azure リソースタイプと API バージョンを明示  VS Code +

    Bicep 拡張による強力な型推論と IntelliSense  リソースプロパティの自動補完、API バージョンの候補表示、リアルタイムの誤り検出  デコレータによるメタデータ・制約定義 @description('Name of the storage account (must be globally unique, 3-24 lowercase alphanumeric)') @minLength(3) @maxLength(24) param name string @allowed(['Standard_LRS', 'Standard_GRS', 'Standard_RAGRS', 'Standard_ZRS', 'Premium_LRS']) param sku string = 'Standard_LRS'
  6. Terraform 例: ストレージアカウント resource "azurerm_storage_account" "example" { name = "storageaccountname"

    resource_group_name = azurerm_resource_group.example.name location = azurerm_resource_group.example.location account_tier = "Standard" account_replication_type = "LRS" tags = { environment = "dev" } }
  7. Terraformの特徴  豊富な組み込み関数  文字列操作: format, replace, regex  コレクション操作:

    merge, flatten, lookup  数値・暗号: max, md5  for_each、count による動的リソース生成  型システムによる変数検証 variable "name" { type = string validation { condition = can(regex("^[a-z0-9]{3,24}$", var.name)) error_message = "Storage account name must be 3-24 lowercase alphanumeric characters." } }
  8. BicepのAPIバージョンのメンテナンスを楽にするアイデア  年に1、2回程度のメンテナンスのた めに凝った仕組み作りは避けたい  APIバージョンの廃止は多くない  GitHub Copilotなどコーディングエー ジェント向けのスキルを作る

     自然言語でAPIバージョンの更新要否基準やポ リシーを表現する  ツールでAPIバージョンに関する情報を取得する aks-chaos-lab/.github/skills/bicep-api-version- updater/SKILL.md at main · torumakabe/aks- chaos-lab
  9. TerraformでAPIバージョンを明示したい場合のアイデア 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" } } }  AzAPIプロバイダを使う  ARM APIのラッパープロバイダで、自由度が高い  リソースのCRUDに限らずデータプレーン操作など、 AzureRMプロバイダにできないことが可能  AzureRMプロバイダと併用できる  AzureRMプロバイダのほうがコード量が少なく済 むため、主はAzureRM、補完的にAzAPIという 使い分けが一般的 Terraform AzAPI プロバイダーの概要 | Microsoft Learn
  10. AzureRMとAzAPIの併用 HCL Terraform Core Azure Resource Manager API AzureRM Provider

    AzAPI Provider メイン • 書くのが楽 補完 • AzureRM未対応サービ スや機能 • バグや不具合のあるリ ソースの一時避難先 • CRUD以外の操作
  11. 共通点  インフラをモジュール(再利用可能な単位)に分割し、入力パラメータと出力で構 成できる  入力に対する型制約・バリデーション機能  Bicep: @allowed/@minLength 等のデコレータ

     Terraform: validation ブロック  レジストリによるモジュール共有・バージョン管理の仕組み  ローカルパスによるモジュール参照
  12. 比較 Bicep Terraform モジュール定義 単一ファイル (.bicep) ディレクトリ単位 (ディレクトリ内の全 .tf ファイルが1モジュール。ファ

    イル分割は慣例) 入力の検証 デコレータ (@allowed, @minLength, @maxLengt h) validation ブロック (正規表現、条件式) 出力の型安全性 型指定あり (string, array, object など) 型指定あり (string, list, map など)
  13. モジュールの参照方法とバージョニング Bicep Terraform 公開レジストリ Azure Verified Modules(AVM): Microsoftが公開するレジストリ。OCI タグ でバージョン指定。例:

    br/public:avm/res/storage/storage- account:0.9.0。Terraform 版もある Terraform Registry: Official / Partner / Community の品質層があり、コンテンツの品質 にばらつきがある。セマンティックバージョニングで 範囲制約が可能 例: version = "~> 3.0" プライベートレジストリ Azure Container Registry: OCI アーティ ファクトとして格納。バージョニングは公開レ ジストリと同様。 例: br:myacr.azurecr.io/bicep/modules /storage:v1.0.0 HCP Terraform: Terraform Registry プロトコ ルを利用。バージョニングは公開レジストリと同様 Git リポジトリ 非対応 GitHub / Azure DevOps Repos: Git タグ・ブ ランチで固定指定。 例: git::https://github.com/org/modules.gi t//network?ref=v1.2.0 ローカルパス ‘../../modules/storage-account.bicep’ (バージョン指定 非対応) "../../modules/storage-account“ (バージョン指定 非対応)
  14. 共通点  コード上の「望ましい状態」と Azure 上の「現在の状態」を比較できる  ただし、状態管理は両者の最も本質的な設計差異  Bicep は

    Azure 自体を真実の情報源(Source of Truth)とし、 Terraform は状態ファイル(tfstate)を中間 記録として介在させる
  15. Bicepの差分適用 Bicepコード Azure リソース what-if Azure リソース deployment create あるべき状態

    実際の状態 あるべき状態 (すべてのリソース) 差分の確認 (確認だけ)
  16. Bicep: ステートレス  利点  状態ファイル管理が不要: バックエンドの構築・運用が要らない  シンプルな運用: 状態ファイルの破損、ロック残留、状態とリソースの不整合といった状態ファイル関連のトラ

    ブルがない  考慮点  ノイズが多い: what-if は状態ファイルなしで Azure API と直接比較するため、省略属性のデフォルト値との 差分などがノイズとして表示される  リソース削除の制御が複雑: Incremental モード(既定)ではコードから削除してもリソースは残る。Complete モードは危険。Deployment Stacks を使う場合も action-on-unmanage の挙動理解が必要
  17. Terraformの差分適用 HCLコード Azure リソース plan Azure リソース apply あるべき状態 実際の状態

    あるべき状態 (差分のある リソースのみ) 差分の確認 tfstate 前回の状態 apply後の状態
  18. Terraform: 状態ファイルを活用  利点  変更計画(plan)の明確さ: コード、状態ファイル、実リソースの3者間差分を計算し、変更対象のリソースを特 定できる  Bicep

    の what-if と比較してノイズが少ない: 状態ファイルを介した3者間比較により、省略属性のデフォルト 値との差分など Bicep 特有のノイズが発生しない  ただし Terraform にも固有のノイズ原因があり、完全ではない  考慮点  状態ファイルの管理が必要: バックアップ、排他ロック、シークレット保護の仕組みが必須。状態ファイルにはリ ソース ID やアクセスキー等の機密情報が含まれる  複数人での作業時にリモートバックエンド必須: Azure Storage 等のリモートバックエンドとロック機構(lease) が必要  Out-of-band 変更への対処が必要: Azure Portal などで行われたリソースレベルの作成や削除は状態ファ イルに反映されず、terraform state import や terraform rm での対処が必要
  19. 共通点  既存リソースからコードを自動生成する補助ツールが存在する  Bicep: Azure CLIやポータルでのテンプレートエクスポート  Terraform: aztfexport

     自動生成されたコードはそのままでは利用しにくく、手動での調整が必要  エクスポートの制約  一部リソースタイプの非対応、シークレットの欠落、ハードコードされた値は共通の課題  今ならコーディングエージェントもおすすめ  Azure CLIやMCPサーバを使ってリソース情報を取得し  既存コードにスタイルを合わせてコードを書いてくれる
  20. 比較 Bicep Terraform アプローチ 既存リソースからコードを生成し、デプロイで 同期 既存リソースを状態ファイルに取り込み、コードと 対応付け 状態ファイルへの登録 不要(状態ファイルがない)

    terraform import で tfstate に追加 コード生成 ツールあり コーディングエージェントも良い ツールあり コーディングエージェントも良い ワークフロー コード作成・調整 → デプロイ terraform import → コード作成・調整 → plan で確認
  21. 共通点  CLIコマンドによる宣言的デプロイ  コードで表現した「あるべき姿」にする  デプロイ前のプレビュー機能(plan / what-if)で変更内容を事前確認 

    リソースの作成・更新・削除を含むライフサイクル管理が可能  冪等性: 同じコードを繰り返しデプロイしても、変更がなければリソースは変更さ れない
  22. Bicep コマンド # 変更プレビュー az deployment sub what-if --location japaneast

    --template-file main.bicep # デプロイ(Incremental モード - 既定) az deployment sub create --location japaneast --template-file main.bicep # Deployment Stacks デプロイ az stack sub create --name mystack --location japaneast --template-file main.bicep ¥ --action-on-unmanage deleteResources --deny-settings-mode none # Deployment Stacks 削除 az stack sub delete --name mystack --action-on-unmanage deleteAll
  23. Terraform コマンド # 初期化 terraform init # 変更計画 terraform plan

    # 適用 terraform apply # 削除 terraform destroy
  24. コードからリソースを削除し、再デプロイした場合の影響 ツール / コマンド コードから消したリソース 備考 az deployment sub create

    (既定: Incremental) 残る コードからリソースを消しても影響がない az deployment sub create --mode Complete 削除 破壊的であり、非推奨 az stack sub create 選択可能 --action-on-unmanage で削除/デタッチを選択。 action-on-unmanage は「スタック管理下にあったリ ソースがコードから削除された場合」にのみ適用される。 ポータルやCLIなどbicepコードの外で作成されたリソー スは検出も削除もしない terraform apply 削除 状態ファイルとの差分で削除対象と判断される
  25. 共通点  コードと実リソースの差分をプレビューするコマンドがある  terraform plan / az deployment what-if

     IaC 管理外で作成されたリソースの検出は両者とも不可  Deployment Stacks も限定的  両者ともノイズ(実質的に影響のない差分表示)が発生しうる  原因は異なる
  26. 比較 Bicep Terraform コマンド az deployment what-if terraform plan ノイズ(false

    positive) 多い 少ない IaC 外リソース検出 (Deployment Stacks も限定的)
  27. Bicep what-ifのノイズ原因 カテゴリ 原因 具体例 省略による差分 Bicep で省略した属性と Azure デフォルト

    値との差分 VNet の privateEndpointVNetPolicies: "Disabled" が差分として表示される reference 関数 reference() で取得する値が what-if 時 点で解決できない 他リソースの出力を参照している箇所が「変更あ り」として誤検出される read-only 属性 Azure が内部管理するプロパティの表示 identity.principalId, properties.state: “Running” など 内部管理プロパティ Azure が自動設定する値 properties.defaultHostName などの計算値
  28. Terraform planのノイズ原因 カテゴリ 原因 具体例 Set のインデックス変更 内部でSetを使っている要素の追加/削除 で他の要素のインデックスがずれ、実際には 行われない削除/作成が出力される

    NSG ルールをインラインで定義した場合、ルール 追加で既存ルールが再作成、と出力される。 Setが多く使われているApplication Gatewayで も起きやすい
  29. Bicep テストフレームワーク  Experimental段階  実験的機能で、サポート対象外  2026 年現在も Experimental

    のまま開発継続中(GA 時期は未定)。有効化には bicepconfig.json で "testFramework": true と "assertions": true の明示的設定が必要  assert 文はモジュール本体に記述が必要  テストファイルからアサーションを指定不可。そのため本番コードとテストコードが分離できない  bicep test コマンドはスタンドアロン Bicep CLI でのみ利用可能  az bicep testコマンドは存在しない  test 宣言はコンパイル検証が主目的: パラメータの型チェック、 @allowed/@minLength/@maxLength 等の制約検証を行う  Terraform の expect_failures に相当する「無効入力のテスト」機能は未サ ポート
  30. Terraform テストフレームワーク  GA段階  mock_provider によるプロバイダモック  実際の Azure

    API を呼び出さずにテスト実行可能  command = plan で実リソース作成なしの単体テスト  デフォルト値やバリデーションルールを高速に検証  command = apply で実リソースを作成・検証する結合テスト  テスト完了後に自動クリーンアップ(tearing down)される  expect_failures で無効な入力に対するバリデーションエラーをテスト可能
  31. 比較 Bicep Terraform 成熟度 Experimental GA モック 不可 ファイル内で定義可能 アサーション

    モジュール内 テストファイル内 単体テスト 対応 (クライアントサイド評価) command = plan 結合テスト 非対応 (Azure CLI スクリプト等で別途実施) command = apply テストフレームワークではTerraformが圧勝
  32. 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
  33. 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
  34. 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
  35. terraform test パターン整理 command = plan command = apply(既定) 実プロバイダ

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

    tflintなど  testコマンドでのインテグレーションテストは積極的に行いたい  実リソースを作らないとわからない問題は多い(Unitテストでは見つからない)  これまではシェルスクリプトやプログラムで自作していたが、標準のしくみができたのは大きい  testコマンドでテストしやすいようにHCLを書いていくムーブまである  checkブロック、これはいいものだ  test、apply時に常に簡易なe2eテストを実行できる(Continuous Validation)  テスト/環境構築時、いちいちcurlを手打ちして確認せずに済む
  37. Lintツール ツール 対象 ルール数 特徴 Bicep linter Bicep 40+ 構文・ベストプラクティス(汎用)

    PSRule for Azure Bicep/ARM 500+ Well-Architected Framework 準拠 tflint + azurerm plugin Terraform 200+ Azure リソース固有の検証 • Bicep linter は組み込みのアドバンテージ(追加インストール不要、VS Code でリアルタイム検出)があるが、カバー範囲は汎用 的なベストプラクティスに限定される • たとえば no-unused-params(未使用パラメータ)、outputs-should-not-contain-secrets(出力へのシークレット漏洩防止)、use- recent-api-versions(古い API バージョンの警告)といった構文品質ルールが中心で、Azure リソース固有の検証(SKU の有効性、 リージョン制限、命名規則準拠など)は含まれない • tflint の azurerm プラグインは azurerm_storage_account_invalid_account_tier(無効な SKU)のようなリソース固有のバ リデーションルールを提供する • 深いセキュリティ検証は、両者とも Trivy などが必要
  38. セキュリティスキャンツール ツール Bicep Terraform 備考 Trivy △ARMテンプレートJSONへ の変換要 ◎ マルチクラウド対応

    • Trivy の Azure ルールはBicep/Terraformで共通(Regoで1セット定義)だが、Terraform パーサーと ARMテンプレート パーサー の実装差異により検出結果が異なるケースがある
  39. Bicepが適するケース  Azure にフォーカスする  Azure CLI と統合されている  追加ツールの導入が少なく済む

     Azureの新機能をすぐに使いたい  新しいAPIバージョンを指定すればいい  生成AIやコンテナ系サービスなど、進化が激しいサービスで特に嬉しい  状態ファイルの管理が嫌だ  状態ファイルの管理が不要  Microsoftのサポートが欲しい  Azureの標準機能としてサポートされる
  40. Terraformが適するケース  マルチクラウド指向である  テストフレームワークを重視する  Bicep TestFramework は 2026

    年現在も Experimental  ノイズは少ないほうがいい  豊富なエコシステムに魅力を感じる  Infracost(コスト見積もり)、terraform-docs(ドキュメント自動生成)など、Bicep にはないツールが利用可能  使いこなし情報は多いほうがいい  マルチクラウド対応ツールゆえ、情報量が多い