Slide 1

Slide 1 text

AzureでのIaC Bicep? Terraform? それ早く言ってよ会議 真壁 徹 シニア クラウドソリューションアーキテクト 日本マイクロソフト株式会社

Slide 2

Slide 2 text

• このスライドは2026/2/6に作成しています • この資料で紹介するツールは変化し続けているため、常に最新の情報 を確認してください

Slide 3

Slide 3 text

この会議の背景  トモダッチ「AzureでIaCするなら、BicepとTerraform、どっちがいい?」  マカベッチ「これまで、それ100回くらい聞かれたんだけど(笑)」 本当に100回くらい聞かれた気がするので記念

Slide 4

Slide 4 text

100回言ったこと  試してみて、「キミにきめた!」と思えるほうを選ぶ  機能的には共通点が多い。が、コンセプトや設計思想は違う  触ってみないとわからないことも多い とはいえ、試す時間は限られる

Slide 5

Slide 5 text

Bicep? Terraform? それ早く言ってよ会議

Slide 6

Slide 6 text

概要

Slide 7

Slide 7 text

概要 Bicep Terraform 開発主体 Microsoft HashiCorp ライセンス MIT BSL 1.1 管理対象クラウドサービス Azure マルチクラウド 言語 Bicep DSL HCL(HashiCorp Configuration Language) JSON 状態管理 なし(ステートレス) 状態ファイル マネージドサービス あり(Azure標準機能) あり(HCP Terraform) 公式ドキュメントでの比較: Terraform と Bicep の比較 | Microsoft Learn

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

言語と構文

Slide 11

Slide 11 text

共通点  宣言的  コードの順序が実行順序に影響しない  リソース間の依存関係を自動解決  モジュール化による再利用性  パラメータ化による柔軟性

Slide 12

Slide 12 text

Bicep 例: ストレージアカウント resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { name: 'storageaccountname' location: resourceGroup().location sku: { name: 'Standard_LRS' } kind: 'StorageV2' tags: { environment: 'dev' } } リソースタイプと APIバージョンを明示

Slide 13

Slide 13 text

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'

Slide 14

Slide 14 text

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" } }

Slide 15

Slide 15 text

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." } }

Slide 16

Slide 16 text

APIバージョンの明示 トレードオフ Bicep Terraform APIバージョンの明示 必要 できない (AzureRMプロバイダに依存) Azure新リソース、機能への追従 APIが公開されれば、即 AzureRMプロバイダに依存 APIバージョンのメンテナンス 必要 不要 (AzureRMプロバイダに依存)

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

AzureRMとAzAPIの併用 HCL Terraform Core Azure Resource Manager API AzureRM Provider AzAPI Provider メイン • 書くのが楽 補完 • AzureRM未対応サービ スや機能 • バグや不具合のあるリ ソースの一時避難先 • CRUD以外の操作

Slide 20

Slide 20 text

モジュール化

Slide 21

Slide 21 text

共通点  インフラをモジュール(再利用可能な単位)に分割し、入力パラメータと出力で構 成できる  入力に対する型制約・バリデーション機能  Bicep: @allowed/@minLength 等のデコレータ  Terraform: validation ブロック  レジストリによるモジュール共有・バージョン管理の仕組み  ローカルパスによるモジュール参照

Slide 22

Slide 22 text

比較 Bicep Terraform モジュール定義 単一ファイル (.bicep) ディレクトリ単位 (ディレクトリ内の全 .tf ファイルが1モジュール。ファ イル分割は慣例) 入力の検証 デコレータ (@allowed, @minLength, @maxLengt h) validation ブロック (正規表現、条件式) 出力の型安全性 型指定あり (string, array, object など) 型指定あり (string, list, map など)

Slide 23

Slide 23 text

モジュールの参照方法とバージョニング 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“ (バージョン指定 非対応)

Slide 24

Slide 24 text

状態、差分管理

Slide 25

Slide 25 text

共通点  コード上の「望ましい状態」と Azure 上の「現在の状態」を比較できる  ただし、状態管理は両者の最も本質的な設計差異  Bicep は Azure 自体を真実の情報源(Source of Truth)とし、 Terraform は状態ファイル(tfstate)を中間 記録として介在させる

Slide 26

Slide 26 text

Bicepの差分適用 Bicepコード Azure リソース what-if Azure リソース deployment create あるべき状態 実際の状態 あるべき状態 (すべてのリソース) 差分の確認 (確認だけ)

Slide 27

Slide 27 text

Bicep: ステートレス  利点  状態ファイル管理が不要: バックエンドの構築・運用が要らない  シンプルな運用: 状態ファイルの破損、ロック残留、状態とリソースの不整合といった状態ファイル関連のトラ ブルがない  考慮点  ノイズが多い: what-if は状態ファイルなしで Azure API と直接比較するため、省略属性のデフォルト値との 差分などがノイズとして表示される  リソース削除の制御が複雑: Incremental モード(既定)ではコードから削除してもリソースは残る。Complete モードは危険。Deployment Stacks を使う場合も action-on-unmanage の挙動理解が必要

Slide 28

Slide 28 text

Terraformの差分適用 HCLコード Azure リソース plan Azure リソース apply あるべき状態 実際の状態 あるべき状態 (差分のある リソースのみ) 差分の確認 tfstate 前回の状態 apply後の状態

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

既存リソースの 取り込み

Slide 31

Slide 31 text

共通点  既存リソースからコードを自動生成する補助ツールが存在する  Bicep: Azure CLIやポータルでのテンプレートエクスポート  Terraform: aztfexport  自動生成されたコードはそのままでは利用しにくく、手動での調整が必要  エクスポートの制約  一部リソースタイプの非対応、シークレットの欠落、ハードコードされた値は共通の課題  今ならコーディングエージェントもおすすめ  Azure CLIやMCPサーバを使ってリソース情報を取得し  既存コードにスタイルを合わせてコードを書いてくれる

Slide 32

Slide 32 text

比較 Bicep Terraform アプローチ 既存リソースからコードを生成し、デプロイで 同期 既存リソースを状態ファイルに取り込み、コードと 対応付け 状態ファイルへの登録 不要(状態ファイルがない) terraform import で tfstate に追加 コード生成 ツールあり コーディングエージェントも良い ツールあり コーディングエージェントも良い ワークフロー コード作成・調整 → デプロイ terraform import → コード作成・調整 → plan で確認

Slide 33

Slide 33 text

デプロイと ライフサイクル管理

Slide 34

Slide 34 text

共通点  CLIコマンドによる宣言的デプロイ  コードで表現した「あるべき姿」にする  デプロイ前のプレビュー機能(plan / what-if)で変更内容を事前確認  リソースの作成・更新・削除を含むライフサイクル管理が可能  冪等性: 同じコードを繰り返しデプロイしても、変更がなければリソースは変更さ れない

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

Terraform コマンド # 初期化 terraform init # 変更計画 terraform plan # 適用 terraform apply # 削除 terraform destroy

Slide 37

Slide 37 text

コードからリソースを削除し、再デプロイした場合の影響 ツール / コマンド コードから消したリソース 備考 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 削除 状態ファイルとの差分で削除対象と判断される

Slide 38

Slide 38 text

差分検出と ノイズ

Slide 39

Slide 39 text

共通点  コードと実リソースの差分をプレビューするコマンドがある  terraform plan / az deployment what-if  IaC 管理外で作成されたリソースの検出は両者とも不可  Deployment Stacks も限定的  両者ともノイズ(実質的に影響のない差分表示)が発生しうる  原因は異なる

Slide 40

Slide 40 text

比較 Bicep Terraform コマンド az deployment what-if terraform plan ノイズ(false positive) 多い 少ない IaC 外リソース検出 (Deployment Stacks も限定的)

Slide 41

Slide 41 text

Bicep what-ifのノイズ原因 カテゴリ 原因 具体例 省略による差分 Bicep で省略した属性と Azure デフォルト 値との差分 VNet の privateEndpointVNetPolicies: "Disabled" が差分として表示される reference 関数 reference() で取得する値が what-if 時 点で解決できない 他リソースの出力を参照している箇所が「変更あ り」として誤検出される read-only 属性 Azure が内部管理するプロパティの表示 identity.principalId, properties.state: “Running” など 内部管理プロパティ Azure が自動設定する値 properties.defaultHostName などの計算値

Slide 42

Slide 42 text

Bicep what-ifのノイズ判定を楽にするアイデア  コーディングエージェント向けスキルを 作る  what-ifの出力を分析し、ノイズかどうかを判定 する aks-chaos-lab/.github/skills/bicep-what-if- analysis/SKILL.md at main · torumakabe/aks- chaos-lab

Slide 43

Slide 43 text

Terraform planのノイズ原因 カテゴリ 原因 具体例 Set のインデックス変更 内部でSetを使っている要素の追加/削除 で他の要素のインデックスがずれ、実際には 行われない削除/作成が出力される NSG ルールをインラインで定義した場合、ルール 追加で既存ルールが再作成、と出力される。 Setが多く使われているApplication Gatewayで も起きやすい

Slide 44

Slide 44 text

 コーディングエージェント向けスキルを 作る  Terraform planの出力を分析し、ノイズかどうか を判定する Terraform planのノイズ判定を楽にするアイデア awesome-copilot/skills/terraform-azurerm-set-diff- analyzer/SKILL.md at main · github/awesome-copilot

Slide 45

Slide 45 text

テスト

Slide 46

Slide 46 text

共通点  ネイティブのテストフレームワークを提供  考慮点: Bicepテストフレームワークは実験的機能扱い  アサーションベースの検証  期待する値と実際の値を比較し、テスト結果を判定  テストファイルをモジュールコードと同じリポジトリに配置する設計

Slide 47

Slide 47 text

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 に相当する「無効入力のテスト」機能は未サ ポート

Slide 48

Slide 48 text

Terraform テストフレームワーク  GA段階  mock_provider によるプロバイダモック  実際の Azure API を呼び出さずにテスト実行可能  command = plan で実リソース作成なしの単体テスト  デフォルト値やバリデーションルールを高速に検証  command = apply で実リソースを作成・検証する結合テスト  テスト完了後に自動クリーンアップ(tearing down)される  expect_failures で無効な入力に対するバリデーションエラーをテスト可能

Slide 49

Slide 49 text

比較 Bicep Terraform 成熟度 Experimental GA モック 不可 ファイル内で定義可能 アサーション モジュール内 テストファイル内 単体テスト 対応 (クライアントサイド評価) command = plan 結合テスト 非対応 (Azure CLI スクリプト等で別途実施) command = apply テストフレームワークではTerraformが圧勝

Slide 50

Slide 50 text

Terraformの テストフレームワーク

Slide 51

Slide 51 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 52

Slide 52 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 53

Slide 53 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 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

静的解析と セキュリティスキャン

Slide 57

Slide 57 text

共通点  組み込みLinterまたはLint ツールによるコード品質チェック  Trivy による共通の Azure セキュリティルール(Rego)でのスキャン

Slide 58

Slide 58 text

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 などが必要

Slide 59

Slide 59 text

セキュリティスキャンツール ツール Bicep Terraform 備考 Trivy △ARMテンプレートJSONへ の変換要 ◎ マルチクラウド対応 • Trivy の Azure ルールはBicep/Terraformで共通(Regoで1セット定義)だが、Terraform パーサーと ARMテンプレート パーサー の実装差異により検出結果が異なるケースがある

Slide 60

Slide 60 text

選定ガイドライン

Slide 61

Slide 61 text

Bicepが適するケース  Azure にフォーカスする  Azure CLI と統合されている  追加ツールの導入が少なく済む  Azureの新機能をすぐに使いたい  新しいAPIバージョンを指定すればいい  生成AIやコンテナ系サービスなど、進化が激しいサービスで特に嬉しい  状態ファイルの管理が嫌だ  状態ファイルの管理が不要  Microsoftのサポートが欲しい  Azureの標準機能としてサポートされる

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

まとめ

Slide 64

Slide 64 text

101回目の  試してみて、「キミにきめた!」と思えるほうを選ぶ  機能的には共通点が多い。が、コンセプトや設計思想は違う  触ってみないとわからないことも多い

Slide 65

Slide 65 text

No content