Skip to content
Pipelines and Pizza 🍕
Go back

Infrastructure as Code: What, Why, and How

5 min read

Building on the Git and Ansible foundations, this week we explore Infrastructure as Code (IaC) — the philosophy, the benefits, and the tools to make infrastructure repeatable, reliable, and version-controlled.

What Is Infrastructure as Code?

Infrastructure as Code (IaC) is the practice of managing and provisioning your IT infrastructure—everything from servers and networks to databases and firewalls—using code and automation, rather than manual setup. Think of it as treating your infrastructure like software: you write scripts to spin up your environments, version control your changes, and let tools do the heavy lifting. This means faster deployments, fewer errors, and the power to recreate entire systems on demand.

Key idea: Treat your infrastructure the same way you treat application code.

Example from AzureRM Terraform provider:

resource "azurerm_resource_group" "example" {
  name     = "example-resources"
  location = "West Europe"
}

resource "azurerm_virtual_network" "example" {
  name                = "example-network"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_subnet" "example" {
  name                 = "internal"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefixes     = ["10.0.2.0/24"]
}

resource "azurerm_linux_virtual_machine" "example" {
  name                = "example-machine"
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  size                = "Standard_F2"
  admin_username      = "adminuser"
  # ... additional config
}

This snippet creates a basic linux vm in azure — without clicking inside the portal.


Why IaC Matters

Benefits:

  • Repeatability: Run the same config in dev, staging, and prod.
  • Versioning: Track changes over time in Git history.
  • Speed: Deploy infrastructure in minutes, not hours.
  • Collaboration: Share config like any other code.
  • Disaster Recovery: Rebuild environments from scratch.

Without IaC, teams rely on manual steps and tribal knowledge — a recipe for drift and outages.


Declarative vs. Imperative Approaches

When managing cloud resources, you have two main philosophies: declarative and imperative.

  • Declarative (What): You describe your desired end state—what you want to exist—and let a tool figure out how to make it reality. Tools like Terraform and AWS CloudFormation excel here.

    resource "azurerm_resource_group" "rg" {
      name     = "my-rg"
      location = "East US"
    }

    After you’ve written your configuration:

    terraform apply

    And when it’s time to clean up:

    terraform destroy
  • Imperative (How): You write out a series of step-by-step commands telling the system how to reach your goal.

    az group create --name my-rg --location "East US"
    # ... later ...
    az group delete --name my-rg --yes --no-wait

Bottom line: Declarative IaC tools like Terraform are like handing the chef your pizza order and letting them handle the details, while imperative scripting is you in the kitchen—kneading the dough, adding the toppings, and hoping you don’t forget a step.


Core Principles of IaC

  1. Idempotence: Your infrastructure code should be safe to run again and again, always bringing the system to the same expected state.

  2. Version Control: Treat your infrastructure scripts just like application code—store them in Git.

  3. Automation: Remove humans from the critical path. Infrastructure changes should be automated from start to finish.

  4. Testing: Never just “hope it works.” Use tools and processes to validate your IaC before pushing it to production.

  5. Modularity: Break your infrastructure into reusable building blocks, such as Terraform modules or Ansible roles.


ToolLanguageMulti-cloudConfig MgmtEase
TerraformHCLYesNoHigh
AnsibleYAMLYesYesHigh
PulumiJS/Py/GoYesNoMedium
CloudFormationJSON/YAMLNoNoMedium
ARM TemplatesJSONNoNoLow

IaC in DevOps Pipelines

Infrastructure as Code integrates seamlessly into your CI/CD workflows:

  1. Commit IaC changes to Git.
  2. Trigger automated validation and testing in your pipeline.
  3. Apply infrastructure changes in staging, then production.

Example: Using GitHub Actions to Deploy with Terraform

jobs:
  deploy_infrastructure:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@v3
      - name: Set up Terraform
        uses: hashicorp/setup-terraform@v2
      - name: Initialize Terraform
        run: terraform init
      - name: Apply Terraform configuration
        run: terraform apply -auto-approve

Common Pitfalls

  • Manual Changes in Production: Making changes directly on live infrastructure causes “configuration drift.”
  • Not Using Modules: Skipping modules leads to repeated code and maintenance headaches.
  • Ignoring State Files: Tools like Terraform rely on state files. Always secure and back them up.
  • Skipping Reviews: Infrastructure code deserves peer review—always use pull requests.

Hands-On Lab

Goal: Create an Azure Resource Group with Terraform.

  1. Install Terraform.
  2. Create main.tf:
provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "my-rg"
  location = "East US"
}
  1. Run:
terraform init
terraform apply -auto-approve
  1. Verify in Azure Portal.

Q&A

Q: Should I store secrets in IaC code? A: No — use a secrets manager.

Q: Can IaC replace all manual ops? A: Not always — but aim for 100% automation where possible.