Azure
AzureIntermediate

Azure Infrastructure as Code: Using Terraform and ARM Templates

5 min read
azureinfrastructure-as-codeterraformarm-templatesdevops

TL;DR

Master Infrastructure as Code in Azure with this comprehensive guide covering Terraform, ARM Templates, state management, module development, and pipeline integration.

Azure Infrastructure as Code: A Complete Implementation Guide

Infrastructure as Code (IaC) is essential for managing cloud resources efficiently. This guide covers implementation details for both Terraform and ARM Templates in Azure.

$1

Key differences between IaC tools:

Feature Terraform ARM Templates
Language HCL JSON/Bicep
State Management External state Azure native
Multi-cloud Yes Azure only
Learning Curve Moderate Steep

$1

$1

``hcl

Provider configuration

provider "azurerm" {

features {}

}

Resource group

resource "azurerm_resource_group" "example" {

name = "example-resources"

location = "East US"

tags = {

environment = "Production"

department = "IT"

}

}

Virtual network

resource "azurerm_virtual_network" "example" {

name = "example-network"

resource_group_name = azurerm_resource_group.example.name

location = azurerm_resource_group.example.location

address_space = ["10.0.0.0/16"]

subnet {

name = "subnet1"

address_prefix = "10.0.1.0/24"

}

subnet {

name = "subnet2"

address_prefix = "10.0.2.0/24"

}

}

Storage account

resource "azurerm_storage_account" "example" {

name = "examplestorageacc"

resource_group_name = azurerm_resource_group.example.name

location = azurerm_resource_group.example.location

account_tier = "Standard"

account_replication_type = "LRS"

tags = {

environment = "Production"

}

}

`

$1

`hcl

modules/webapp/main.tf

variable "name" {

type = string

description = "Name of the web app"

}

variable "location" {

type = string

description = "Azure region"

}

variable "resource_group_name" {

type = string

description = "Resource group name"

}

resource "azurerm_app_service_plan" "example" {

name = "${var.name}-plan"

location = var.location

resource_group_name = var.resource_group_name

sku {

tier = "Standard"

size = "S1"

}

}

resource "azurerm_app_service" "example" {

name = var.name

location = var.location

resource_group_name = var.resource_group_name

app_service_plan_id = azurerm_app_service_plan.example.id

site_config {

dotnet_framework_version = "v4.0"

scm_type = "LocalGit"

}

app_settings = {

"WEBSITE_NODE_DEFAULT_VERSION" = "10.14.1"

}

}

output "webapp_url" {

value = azurerm_app_service.example.default_site_hostname

}

`

$1

$1

`json

{

"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",

"contentVersion": "1.0.0.0",

"parameters": {

"storageAccountName": {

"type": "string",

"metadata": {

"description": "Name of the storage account"

}

},

"location": {

"type": "string",

"defaultValue": "[resourceGroup().location]",

"metadata": {

"description": "Location for resources"

}

}

},

"variables": {

"storageAccountSku": "Standard_LRS"

},

"resources": [

{

"type": "Microsoft.Storage/storageAccounts",

"apiVersion": "2021-04-01",

"name": "[parameters('storageAccountName')]",

"location": "[parameters('location')]",

"sku": {

"name": "[variables('storageAccountSku')]"

},

"kind": "StorageV2",

"properties": {

"supportsHttpsTrafficOnly": true,

"minimumTlsVersion": "TLS1_2",

"allowBlobPublicAccess": false

}

}

],

"outputs": {

"storageAccountId": {

"type": "string",

"value": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"

}

}

}

`

$1

`json

{

"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",

"contentVersion": "1.0.0.0",

"parameters": {

"networkTemplate": {

"type": "string",

"metadata": {

"description": "URI to the network template"

}

}

},

"resources": [

{

"type": "Microsoft.Resources/deployments",

"apiVersion": "2021-04-01",

"name": "networkDeployment",

"properties": {

"mode": "Incremental",

"templateLink": {

"uri": "[parameters('networkTemplate')]",

"contentVersion": "1.0.0.0"

},

"parameters": {

"vnetName": {

"value": "myVNet"

},

"addressPrefix": {

"value": "10.0.0.0/16"

}

}

}

}

]

}

`

$1

$1

`hcl

Backend configuration

terraform {

backend "azurerm" {

resource_group_name = "terraform-state-rg"

storage_account_name = "terraformstate"

container_name = "tfstate"

key = "prod.terraform.tfstate"

}

}

State locking

resource "azurerm_storage_account" "state" {

name = "terraformstate"

resource_group_name = "terraform-state-rg"

location = "East US"

account_tier = "Standard"

account_replication_type = "LRS"

blob_properties {

versioning_enabled = true

}

}

resource "azurerm_storage_container" "state" {

name = "tfstate"

storage_account_name = azurerm_storage_account.state.name

container_access_type = "private"

}

`

$1

$1

`yaml

trigger:

branches:

include:

- main

paths:

include:

- terraform/*

variables:

- group: terraform-vars

stages:

  • stage: Validate
  • jobs:

    - job: ValidateAndPlan

    pool:

    vmImage: 'ubuntu-latest'

    steps:

    - task: TerraformInstaller@0

    inputs:

    terraformVersion: '1.0.0'

    - task: TerraformTaskV3@3

    inputs:

    provider: 'azurerm'

    command: 'init'

    backendServiceArm: '$(AZURE_SUBSCRIPTION)'

    backendAzureRmResourceGroupName: '$(BACKEND_RG)'

    backendAzureRmStorageAccountName: '$(BACKEND_SA)'

    backendAzureRmContainerName: '$(BACKEND_CONTAINER)'

    backendAzureRmKey: '$(BACKEND_KEY)'

    - task: TerraformTaskV3@3

    inputs:

    provider: 'azurerm'

    command: 'plan'

    environmentServiceNameAzureRM: '$(AZURE_SUBSCRIPTION)'

  • stage: Apply
  • dependsOn: Validate

    condition: succeeded()

    jobs:

    - deployment: ApplyTerraform

    environment: 'Production'

    strategy:

    runOnce:

    deploy:

    steps:

    - task: TerraformTaskV3@3

    inputs:

    provider: 'azurerm'

    command: 'apply'

    environmentServiceNameAzureRM: '$(AZURE_SUBSCRIPTION)'

    commandOptions: '-auto-approve'

    ``

    $1

    $1

    Test Type Tool Purpose
    Static Analysis tflint Syntax validation
    Security Scanning tfsec Security checks
    Policy Compliance Checkov Policy validation
    Integration Tests Terratest Resource testing

    $1

    1. Code Organization

    - Use modules

    - Implement state management

    - Version control

    - Documentation

    2. Security

    - Secure state storage

    - Use service principals

    - Implement least privilege

    - Regular security scans

    3. Deployment

    - Use pipelines

    - Implement validation

    - Stage deployments

    - Regular testing

    4. Maintenance

    - Version tracking

    - State backups

    - Regular updates

    - Monitoring

    $1

    Common IaC issues and solutions:

    1. State Issues

    - Check backend configuration

    - Verify access permissions

    - Review state locks

    - Backup state files

    2. Deployment Failures

    - Check dependencies

    - Verify credentials

    - Review logs

    - Test locally

    3. Module Problems

    - Check versions

    - Verify inputs

    - Review outputs

    - Test modules

    $1

    After implementing IaC:

    1. Set up monitoring

    2. Implement compliance checks

    3. Automate testing

    4. Train team members

    5. Document processes

    Remember to regularly review and update your IaC implementation to maintain optimal infrastructure management.

    Why This Matters

    Understanding the business and technical context helps you make informed decisions rather than blindly following patterns.

    Trade-offs to Consider

    Every architectural decision involves trade-offs. Consider your specific requirements, team expertise, and scale when evaluating options.

    When NOT to Use This

    Knowing when a solution doesn't apply is as valuable as knowing when it does. Consider alternatives for your specific situation.

    Decision Framework

    Use this framework to evaluate whether this approach is right for your use case based on your specific constraints and requirements.