Azure

Terraform on Azure: Complete Guide to AzureRM/AzAPI Providers, State, Modules, and CI/CD

2026-05-24
NicheeLab Editorial Team

Terraform on Azure is the combination of HashiCorp's multi-cloud IaC tool Terraform with Azure resource management. While Bicep is an Azure-specific DSL, Terraform is multi-cloud (3,000+ Providers) with strong existing investments and an active OSS community. This article walks through Provider selection, State management, Module design, and CI/CD integration end to end.

Bicep vs Terraform: How to Choose

ItemBicepTerraform
DeveloperMicrosoftHashiCorp
Supported cloudsAzure onlyMulti-cloud (3,000+ Providers)
LanguageBicep DSLHCL
State managementNot required (handled by ARM)Required (Azure Storage / Terraform Cloud)
Latest Azure featuresImmediate supportCan lag (workaround via AzAPI)
PricingFreeOSS free / Cloud is paid
Best fitAzure-only, latest features firstMulti-cloud, existing assets

The modern rule of thumb: Bicep for greenfield Azure-only projects, Terraform for multi-cloud or existing Terraform projects.

AzureRM Provider and AzAPI Provider

ItemAzureRM ProviderAzAPI Provider (released 2022)
PositioningStandardComplementary
BehaviorDedicated functions over the Azure REST APIGeneric — calls the Azure REST API directly
Resource count3,000+ dedicated functionsA single azapi_resource covers everything
Latest feature supportCan lag by several monthsImmediate
Use caseStandard patternPreview features and newly added resources

Standard pattern: use AzureRM Provider as the base and reach for AzAPI Provider only for Preview features and newly added resources. The two can coexist inside the same Terraform project.

Managing Terraform State

Terraform State is a JSON file recording the current state of your infrastructure and is the baseline for terraform plan / apply. The default is local; in production it must be stored in a remote Backend.

Azure standard pattern

  • Use an Azure Storage Account Blob Container as the Backend
  • Implement State Lock (preventing concurrent updates) with Blob Lease
  • Encrypt State (Customer-Managed Key)
  • Use Versioning + Soft Delete to prevent accidental deletion
  • Control access to State with Microsoft Entra ID authentication

Backend configuration example

terraform {
  backend "azurerm" {
    resource_group_name  = "rg-tfstate"
    storage_account_name = "stgtfstate001"
    container_name       = "tfstate"
    key                  = "prod.terraform.tfstate"
    use_oidc             = true
  }
}

Terraform Cloud (paid SaaS) is also available as a Backend and offers more advanced State management.

Module Design

A Terraform Module is a reusable unit of Terraform code.

Recommended directory layout

infra/
├── main.tf              # エントリポイント・Provider 設定
├── variables.tf         # 入力変数
├── outputs.tf           # 出力値
├── modules/
│   ├── network/         # VNet / NSG / Subnet
│   ├── compute/         # VM / App Service / AKS
│   ├── storage/         # Storage Account / Container
│   └── identity/        # Managed Identity / Key Vault
└── environments/
    ├── dev.tfvars
    ├── stage.tfvars
    └── prod.tfvars

Module invocation example

module "network" {
  source              = "./modules/network"
  vnet_name           = var.vnet_name
  address_space       = ["10.0.0.0/16"]
  location            = var.location
  resource_group_name = azurerm_resource_group.main.name
}

module "compute" {
  source              = "./modules/compute"
  vm_name             = var.vm_name
  subnet_id           = module.network.app_subnet_id
  resource_group_name = azurerm_resource_group.main.name
  depends_on          = [module.network]
}

Azure Verified Modules (AVM)

Azure Verified Modules (AVM, GA in 2024) are a set of Microsoft-quality-assured Terraform Modules and serve as reference implementations aligned with industry best practices.

  • Officially maintained by Microsoft
  • Aligned with the Well-Architected Framework
  • Security baseline applied
  • Published on the Terraform Registry
  • A Bicep edition of AVM is also offered

In the enterprise, customizing on top of AVM is the standard approach. Modularization dramatically improves the maintainability of large-scale IaC.

Coexisting with Bicep

The two do not compete and can be used together. Typical patterns:

  1. Bicep for Azure-only resources, Terraform for multi-cloud requirements (e.g. AWS RDS)
  2. Bicep for greenfield development while keeping existing Terraform assets
  3. Bicep / AzAPI for Microsoft's latest features (including Preview), Terraform AzureRM for stable features

CI/CD pipeline coexistence example

  • Stage 1: build the Hub VNet with Bicep
  • Stage 2: provision AWS resources + AKS with Terraform
  • Stage 3: configure Azure SaaS with Bicep

Drift Detection

Drift Detection is the operation of detecting differences between Terraform State and the actual state of Azure resources. When resources are modified manually via the Azure Portal or CLI, State drifts and unexpected changes risk being applied during the next terraform apply.

Relevant commands

  • terraform plan -refresh-only: refresh State to match current resources
  • terraform apply -refresh-only: apply the diff
  • terraform import: bring new resources into State

Embedding periodic Drift Detection in your CI/CD pipeline (for example weekly) makes it possible to catch manual changes early. Combining this with Azure Policy Deny Effect to prohibit manual changes outright is the standard enterprise pattern.

Integration with GitHub Actions / Azure Pipelines

Standard pattern

  1. Lint: terraform fmt -check + terraform validate
  2. Init: connect to the Backend
  3. Plan: terraform plan -out=tfplan — predict changes
  4. Manual Approval (for Production)
  5. Apply: terraform apply tfplan

GitHub Actions example

name: Terraform Apply
on:
  push:
    branches: [main]

jobs:
  terraform:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      - run: terraform init
      - run: terraform plan -out=tfplan
      - run: terraform apply tfplan

Use OIDC / Workload Identity Federation for AzureRM Provider authentication (no secrets needed) and for Backend authentication as well. Auto-posting Plan output as a PR comment on Pull Requests is also a standard implementation.

Operational Best Practices

  1. State must be stored in the Azure Storage Backend (local State is prohibited)
  2. Combine State Lock + Versioning + Soft Delete against accidental deletion
  3. Modularize for reusability (leverage AVM)
  4. Separate configuration per environment with tfvars
  5. OIDC / WIF for secret-less authentication
  6. Embed Plan → Approval → Apply in the CI/CD pipeline
  7. Detect manual changes with periodic Drift Detection
  8. Use Azure Policy to prohibit manual changes
  9. Auto-post Plan output as PR comments on Pull Requests
  10. Pin Provider versions (required_version + required_providers in terraform.tf)

Related Certifications

Frequently Asked Questions

What is Terraform on Azure?

Terraform on Azure is the combination of HashiCorp's multi-cloud IaC tool Terraform with Azure resource management. Azure resources are defined declaratively in HCL (HashiCorp Configuration Language) via the AzureRM Provider (officially maintained by Microsoft) and applied to Azure with the terraform plan / apply commands. While Bicep is an Azure-specific DSL with immediate support for new features, Terraform is multi-cloud (3,000+ Providers covering AWS / GCP / Azure / Kubernetes / SaaS) with strong existing investments and a vibrant OSS community. Modern selection criteria: Bicep for greenfield Azure-only projects, Terraform for multi-cloud or existing Terraform projects.

What is the difference between AzureRM Provider and AzAPI Provider?

AzureRM Provider: the standard Azure resource management Provider, officially maintained by Microsoft, built on the Azure REST API, with dedicated functions for each resource type (3,000+ resources such as azurerm_storage_account), published on the Terraform Registry. AzAPI Provider: a newer Provider released by Microsoft in 2022 that calls the Azure REST API directly via a generic resource (azapi_resource), enabling immediate use of new Azure features and Preview features that AzureRM has yet to support (AzureRM can lag by several months). Standard pattern: use AzureRM Provider as the base and rely on AzAPI Provider only for Preview features and newly added resources. The two can coexist inside the same Terraform project and be selected per resource type.

How should Terraform State be managed?

Terraform State is a JSON file recording the current state of your infrastructure and is the baseline for terraform plan / apply. The default location is local (terraform.tfstate), but production must use a remote Backend. Azure standard pattern: 1) use an Azure Storage Account Blob Container as the Backend, 2) implement State Lock (preventing concurrent updates) via Blob Lease, 3) encrypt State (Customer-Managed Key), 4) prevent accidental deletion with Versioning + Soft Delete, 5) control access to State with Microsoft Entra ID authentication. Backend config example: terraform { backend 'azurerm' { resource_group_name = '...' storage_account_name = '...' container_name = '...' key = 'prod.terraform.tfstate' } }. Terraform Cloud (paid SaaS) is also available as a Backend and offers more advanced State management.

How should Modules be designed?

A Terraform Module is a reusable unit of Terraform code. Standard directory structure: 1) main.tf (entry point and Provider config), 2) variables.tf (input variables), 3) outputs.tf (output values), 4) modules/ (functional modules: network, compute, storage), 5) environments/ (per-environment tfvars). Publish Modules to the Terraform Registry or internal Git for reuse across projects. Microsoft's official Azure Verified Modules (AVM, GA in 2024) are a set of Microsoft-quality-assured Terraform Modules and serve as reference implementations aligned with industry best practices. In the enterprise it is standard to customize on top of AVM. Modularization dramatically improves maintainability of large-scale IaC and provides the same kind of benefits as Bicep's Module feature.

Can Bicep and Terraform be used together?

Yes — the two do not compete and can be used together. Typical patterns: 1) Bicep for Azure-only resources, Terraform for multi-cloud requirements (e.g. AWS RDS), 2) Bicep for greenfield while keeping existing Terraform assets, 3) Bicep / AzAPI for Microsoft's latest (including Preview) features and Terraform AzureRM for stable features. The two can run sequentially inside the same Azure DevOps / GitHub Actions pipeline. CI/CD pipeline example: Stage 1 (build Hub VNet with Bicep) → Stage 2 (provision AWS resources + AKS with Terraform) → Stage 3 (configure Azure SaaS with Bicep). A realistic strategy is to mix them flexibly based on your team's skill set, existing assets, and requirements.

How does State Drift Detection work?

Drift Detection is the operation of detecting differences between Terraform State and the actual state of Azure resources. When resources are modified manually via the Azure Portal or CLI (changes outside Terraform), State drifts and unexpected changes risk being applied during the next terraform apply. Relevant commands: terraform plan -refresh-only (refresh State to match current resources), terraform apply -refresh-only (apply the diff), and terraform import (bring new resources into State). Embedding periodic Drift Detection into the CI/CD pipeline (for example weekly) makes it possible to catch manual changes early. Combining this with Azure Policy DenyEffect to prohibit manual changes outright is the standard enterprise pattern.

How does it integrate with GitHub Actions / Azure Pipelines?

Standard pattern: 1) Lint (terraform fmt -check + terraform validate), 2) Init (Backend connection), 3) Plan (terraform plan -out=tfplan, predicting changes), 4) Manual Approval (for Production), 5) Apply (terraform apply tfplan). On GitHub Actions, use the hashicorp/setup-terraform Action; on Azure Pipelines, combine the TerraformInstaller Task with the TerraformTaskV4 Task. Use OIDC / Workload Identity Federation for AzureRM Provider authentication (no secrets needed) and for Backend authentication as well. Auto-posting Plan output as a PR comment on Pull Requests is also a standard implementation. The CI/CD patterns covered in the Bicep tutorial article apply to Terraform with very few changes.

Which certifications are related?

AZ-400 (DevOps Engineer Expert) is the flagship certification for this area — Domain 3 covers Terraform alongside Bicep / ARM as IaC. AZ-104 (Administrator) covers IaC fundamentals, and AZ-305 (Solutions Architect Expert) covers IaC strategy selection from an architect's viewpoint (Bicep vs Terraform). Outside Microsoft: HashiCorp Certified: Terraform Associate (vendor-neutral, the standard Terraform certification, renewed annually) is recognized in the job market as proof of Terraform expertise. The combo of AZ-400 + Terraform Associate is a powerful asset for DevOps engineers and is especially valued at multi-cloud companies.

Related Articles and Technical Deep Dives

Azure Bicep チュートリアル|ARM 後継 IaC の基本構文・モジュール化・What-If・CI/CD 統合【2026 年版】

Azure 純正 IaC ツール Bicep の完全チュートリアル。ARM JSON との違い・基本構文 (param/var/resource/module/output)・モジュール化ベストプラクティス・What-If デプロイ・GitHub Actions / Azure Pipelines 統合・ARM からの移行手順・関連認定試験 (AZ-104 / AZ-204 / AZ-400 / AZ-305) を日本語で網羅。

GitHub Actions vs Azure Pipelines 完全比較|CI/CD 選定・Self-hosted Runner・OIDC 認証【2026 年版】

GitHub Actions と Azure Pipelines を完全比較。機能差・Marketplace エコシステム・Self-hosted Runner / Agent・OIDC (Workload Identity Federation) 認証・Matrix Build・Composite Action / Reusable Workflow・DevSecOps 統合・関連認定試験 (AZ-400 / AZ-204) を日本語で網羅。

Azure DevOps エンジニア キャリアロードマップ|AZ-104 → AZ-400 → SC-100 シニア DevOps への道【2026 年版】

Azure DevOps Engineer になるための認定取得ロードマップ完全版。AZ-900 → AZ-104 → AZ-400 の王道ルート、GitHub と Azure DevOps の両方を扱う AZ-400 の構成、Kubernetes 認定 (CKA / CKAD / CKS) との二刀流、IaC (Bicep / Terraform) 戦略、年収レンジまで日本語で網羅。

AZ-400 完全ガイド|Microsoft Azure DevOps Engineer Expert 出題範囲・学習リソース・合格戦略【2026 年版】

Microsoft Certified: DevOps Engineer Expert (AZ-400) の完全ガイド。5 ドメインの出題範囲、Azure DevOps と GitHub の両方を網羅、IaC (Bicep / ARM / Terraform)、CI/CD パイプライン設計、DevSecOps、SRE プラクティス、3-4 ヶ月の合格ロードマップ、AZ-305 / SC-100 との二刀流戦略を日本語で網羅。

The technical content in this article is based on the AzureRM Provider Documentation and the Microsoft Terraform on Azure Documentation. This article is not an official Microsoft Corporation product and has no affiliation or sponsorship relationship with Microsoft. Microsoft and Azure are trademarks of the Microsoft group of companies. Terraform is a trademark of HashiCorp. Information reflects official public materials as of May 24, 2026. Always check the official pages for the latest information.

Check what you learned with practice questions

Practice with certification-focused question sets

Visit the Azure exam prep page
Author

NicheeLab Editorial Team

NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.


Related articles
Azure

AZ-900 Azure Fundamentals: Complete Exam Guide (2026)

Pass AZ-900 — cloud concepts, Azure architecture, management...

Azure

Azure Certification Roadmap: Which Cert to Take Next (2026)

Choose your Azure certification path — Fundamentals, Associa...

Azure

AI-901 Azure AI Fundamentals (Beta): Complete Guide (2026)

Pass AI-901 — Microsoft Foundry, generative AI, responsible ...

Azure

Microsoft Entra ID Fundamentals for Azure Certs (2026)

Entra ID basics every cert candidate needs — tenants, identi...

Azure

DP-900 Azure Data Fundamentals: Complete Guide (2026)

Pass DP-900 — relational, non-relational, analytics, Power B...

Browse all Azure articles (104)
© 2026 NicheeLab All rights reserved.