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
`` provider "azurerm" {
features {}
} resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "East US"
tags = {
environment = "Production"
department = "IT"
}
} 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"
}
} 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"
}
}
hcl
`Provider configuration
Resource group
Virtual network
Storage account
$1
` 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
}
hcl
`modules/webapp/main.tf
$1
$1
` {
"$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'))]"
}
}
}
json
`
$1
` {
"$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"
}
}
}
}
]
}
json
`
$1
$1
` terraform {
backend "azurerm" {
resource_group_name = "terraform-state-rg"
storage_account_name = "terraformstate"
container_name = "tfstate"
key = "prod.terraform.tfstate"
}
} 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"
}
hcl
`Backend configuration
State locking
$1
$1
` trigger:
branches:
include:
- main
paths:
include:
- terraform/* variables:
- group: terraform-vars stages:
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)' 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'
yaml
``
$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.