Infrastructure as Code#

Infrastructure-as-Code (IaC) treats infrastructure the same way as application code: defined in version-controlled files, reviewed in pull requests, and applied by automation rather than clicked into a console.

        flowchart LR
  Dev[Engineer] -->|edit + PR| Git[(Git Repo)]
  Git -->|plan in CI| CI[CI Pipeline]
  CI -->|terraform plan| Plan[Plan Artifact]
  Plan -->|review| Reviewer
  Reviewer -->|approve + merge| Git
  Git -->|apply| Apply[terraform apply]
  Apply -->|update| State[(Remote State<br/>+ Lock)]
  Apply -->|provision| Cloud[Cloud APIs]
  Cloud --> Resources[VPCs / VMs / Buckets / IAM]
  Resources -.->|drift detection| Plan
    

Provisioning Tools#

The IaC tools an operator picks among. Terraform leads on broad cloud coverage with HCL; OpenTofu is the open-source fork; Pulumi authors infrastructure in real programming languages; CloudFormation, CDK, Bicep are cloud-specific; Crossplane brings provisioning into Kubernetes itself.

A Tiny Terraform Example#

terraform {
  required_providers {
    aws = { source = "hashicorp/aws", version = "~> 5.0" }
  }
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "logs" {
  bucket = "myorg-logs-${var.env}"
}

variable "env" {
  type    = string
  default = "dev"
}

output "bucket_name" {
  value = aws_s3_bucket.logs.id
}
$ terraform init
$ terraform fmt
$ terraform validate
$ terraform plan -out tfplan
$ terraform apply tfplan
$ terraform destroy

State#

Terraform records what it created in a state file. Treat state with care:

  • Store remotely (S3 + DynamoDB lock, Terraform Cloud, GCS, Azure storage).

  • Lock during applies to prevent concurrent runs.

  • Never edit by hand in production.

  • Use terraform import to bring existing resources under management.

Configuration Management#

The other half of IaC, describing what runs on a server, not just which servers exist. Ansible’s agentless YAML playbooks dominate today; Chef, Puppet, and Salt cover the mature alternatives. Increasingly, configuration moves into container images, leaving CM for traditional VM fleets.

For per-server configuration (packages, files, services), the classic tools are:

  • Ansible, agentless, YAML playbooks over SSH.

  • Chef, Ruby DSL, agent-based.

  • Puppet , declarative DSL, agent-based.

  • Salt , ZeroMQ pub-sub, fast at fleet scale.

A minimal Ansible playbook:

- hosts: web
  become: true
  tasks:
    - name: install nginx
      apt: { name: nginx, state: latest, update_cache: true }
    - name: ensure nginx is running
      service: { name: nginx, state: started, enabled: true }

Patterns#

The patterns that turn IaC from a folder of files into a production discipline. Modules for reuse, separate state per environment, plan-in-CI / apply-on-merge for review, periodic drift detection, and consistent resource tagging all show up in mature setups.

  • Modules / charts, bundle a reusable piece of infrastructure with inputs and outputs.

  • Environments via workspaces or directories, separate state per env (dev/staging/prod).

  • Plan in CI, apply on merge, review changes before they land.

  • Drift detection, run terraform plan periodically; alert on unexpected diffs.

  • Tagging strategy, consistent tags (env, owner, cost-center) on every resource.