Post

Terraform CI/CD Pipeline Best Practices for Azure

Terraform CI/CD Pipeline Best Practices for Azure

When managing cloud infrastructure at scale, a well‑structured CI/CD pipeline for Terraform is essential.
This guide walks through best practices for building safe, maintainable, and automated workflows — with examples geared toward Azure.


🗂 1. Structure Your Repository for Clarity

A clean repo layout ensures modularity and reusability:

1
2
3
4
5
6
7
8
9
├── modules/
│   ├── networking/
│   ├── compute/
│   └── monitoring/
├── environments/
│   ├── dev/
│   ├── staging/
│   └── prod/
└── .github/workflows/
  • Modules → Encapsulate repeatable resources (networking, compute, alerts)
  • Environments → Hold environment‑specific variables and backend configs

🔐 2. Secure Your State

Store your Terraform state remotely with locking and encryption. For Azure:

1
2
3
4
5
6
7
8
terraform {
  backend "azurerm" {
    resource_group_name  = "rg-terraform-state"
    storage_account_name = "tfstateprod"
    container_name       = "statefiles"
    key                  = "prod.terraform.tfstate"
  }
}
  • Enable state locking to prevent race conditions
  • Encrypt state files at rest and in transit

🚦 3. Introduce Manual Approval Gates

In GitHub Actions, approvals can block unintended production changes:

1
2
3
4
5
6
7
jobs:
  deploy-prod:
    needs: plan-prod
    if: github.ref == 'refs/heads/main'
    environment:
      name: production
      url: https://portal.azure.com
  • Pair this with terraform plan artifacts so reviewers can verify before applying

🧠 4. Detect Changes Before Running Apply

Avoid unnecessary runs by filtering workflow triggers:

1
2
3
4
5
on:
  push:
    paths:
      - 'environments/prod/**'
      - 'modules/**'

This ensures terraform apply runs only when relevant code changes.


📊 5. Monitor Infrastructure with Reusable Modules

Example: Azure Monitor Metric Alerts module:

1
2
3
4
5
6
7
module "cpu_alert" {
  source              = "../../modules/monitoring/metric_alert"
  alert_name          = "HighCPUUsage"
  target_resource_id  = azurerm_linux_virtual_machine.vm.id
  metric_name         = "Percentage CPU"
  threshold           = 80
}
  • Makes alert creation consistent across environments
  • Reduces duplication in your codebase

📝 Final Thoughts

A great Terraform CI/CD pipeline balances:

  • Speed → Fast feedback on changes
  • Safety → Approvals and controlled rollouts
  • Maintainability → Modular, reusable components

💡 Pro Tip: Test locally with the same backend config as your CI system to catch issues before merge.


This post is licensed under CC BY 4.0 by the author.