Infrastructure as Code (IaC) applies software engineering practices — version control, code review, automated testing, CI/CD — to infrastructure provisioning. Instead of clicking through a cloud console or running ad-hoc scripts, you declare your infrastructure in configuration files and let a tool provision it reproducibly.
Why IaC?
- Reproducibility: Spin up identical environments for development, staging, and production with a single command.
- Auditability: Every infrastructure change is a Git commit — who changed what, when, and why.
- Drift prevention: If someone manually changes a resource, IaC tools detect and can correct the drift.
- Disaster recovery: Rebuild an entire environment from code in minutes rather than hours.
- Collaboration: Infrastructure changes go through the same PR review process as application code.
IaC Approaches
| Approach | Tools | Description |
|---|---|---|
| Declarative | Terraform, Pulumi, CloudFormation | Describe the desired end state; the tool figures out how to get there. |
| Imperative | Ansible (ad-hoc), scripts | Describe the steps to take. Order matters; idempotency must be handled manually. |
| Mutable infra | Ansible, Chef, Puppet | Configure existing servers in-place. Faster but can accumulate configuration drift. |
| Immutable infra | Terraform + Packer, AMI baking | Never modify a running resource — replace it. More reliable, eliminates drift. |
Terraform Fundamentals
Terraform is the most widely adopted IaC tool. It uses HCL (HashiCorp Configuration Language) to declare resources across any cloud or service via providers.
A minimal AWS EC2 instance in Terraform:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "web-server"
}
}
The Terraform Workflow
terraform init— Download providers, initialise the backend, set up the working directory.terraform plan— Compare current state with desired state. Show exactly what will be created, changed, or destroyed. Always review the plan before applying.terraform apply— Execute the changes shown in the plan.terraform destroy— Tear down all resources managed by this configuration.
Remote State
Terraform tracks what it has provisioned in a state file (terraform.tfstate). For teams, local state files cause conflicts. Use a remote backend:
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "production/network/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
The S3 backend stores state remotely; DynamoDB provides state locking — preventing two users from running apply simultaneously and corrupting state.
Modules
Terraform modules are reusable, composable building blocks. A module is simply a directory of .tf files with defined input variables and output values. Organisations create internal module libraries for common patterns (VPC, ECS service, RDS instance) and consume them across many projects:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.1.2"
name = "production-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b", "us-east-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
}