Infrastructure as Code
The IaC landscape, declarative vs imperative, and why state management is the hard part.
Overview
Infrastructure as software
Infrastructure as Code (IaC) treats provisioning as software: version-controlled, code-reviewed, deployed by automation. It has been the SRE standard since about 2015; the question now is which tool, not whether.
The major players
- Terraform / OpenTofu — Declarative HCL, state file; AWS, GCP, Azure plus 1000+ providers. OpenTofu is the 2023 community fork after Terraform's license change — The de facto multi-cloud standard
- Pulumi — Same declarative, state-driven model in real languages: Python, Go, TypeScript, C#. Smaller but fast-growing ecosystem — Teams preferring code abstractions to HCL
- AWS CDK — TypeScript, Python or Java that synthesizes to CloudFormation — AWS-only teams wanting tight integration
- Crossplane — Infrastructure as Kubernetes Custom Resources: "everything as Kubernetes objects" — K8s-heavy organizations; cleaner GitOps, less universal
The shared architecture
- 1. Declarative configuration — "I want a VPC with these subnets, an RDS instance with these specs, an EKS cluster with these node groups," not "create a VPC, then a subnet, then..."
- 2. State file — Tracks what's deployed; the diff between code and state determines changes
- 3. Plan / apply cycle — terraform plan shows what would change; terraform apply makes it so. Always plan before apply in production
- 4. Provider abstraction — AWS, GCP, Cloudflare providers expose resources your config references
Why state is the hardest problem
The state file is the tool's belief about what is deployed. When it disagrees with reality, everything breaks.
- Drift — Someone clicks in the AWS console; state thinks the resource is unchanged; the next apply may re-create or modify it unexpectedly
- State corruption — Damaged or out-of-sync state needs manual reconciliation
- Concurrent modification — Two engineers apply at once; one overwrites the other
State best practices
- Remote backend — S3, GCS, Azure Blob, Terraform Cloud; never local-only state
- Locking — DynamoDB for the S3 backend, Cloud Storage for GCS; prevents concurrent applies
- Backups — S3 versioning + lifecycle, or Terraform Cloud's automatic backups
- Workspace per environment — dev / staging / prod, to avoid cross-environment applies
- No console changes — Or detect drift with continuous terraform plan
Module design
- Reusable modules — Common patterns (VPC, RDS, EKS) invoked by environment-specific configs
- Composition over inheritance — Modules call other modules
- Versioned modules — Tagged releases, so prod can run a different module version than dev
The OpenTofu split (2023)
HashiCorp relicensed Terraform under the BUSL (not OSI-approved), and the community forked OpenTofu under the MPL. Most public usage is moving to OpenTofu; commercial users may stay on Terraform for support contracts. Compatibility holds for now; divergence is likely over 2-3 years.
Crossplane vs Terraform
- Model — Imperative-feeling apply cycle; an engineer runs commands — Continuous reconciliation in Kubernetes; submit YAML and it works toward it indefinitely
- GitOps — Usually wrapped with Atlantis or Terraform Cloud — Fits natively
Key concepts
- Declarative IaC
- Describe desired state; tool figures out how to reach it. Standard pattern across Terraform, Pulumi, CDK.
- State file
- Tool's record of what's deployed. Drift between state and reality is the leading source of IaC bugs.
- Plan / apply
- Plan shows proposed changes; apply executes them. Production-grade discipline: always plan first.
- Remote state + locking
- State stored in S3/GCS with DynamoDB/equivalent for concurrent-apply prevention. Never local-only state.
- OpenTofu fork
- Community fork (2023) after HashiCorp BUSL license change. Compatibility maintained; gradual divergence expected.
- Crossplane
- Kubernetes-native IaC. Resources are CRDs; controller reconciles continuously. Fits GitOps cleanly.
When to use it
- Greenfield infrastructure project — IaC from day 1, never click-ops
- Migration from manual to IaC — incremental import; terraform import for existing resources
- Multi-cloud or vendor-portable infrastructure — Terraform / OpenTofu (Pulumi second)
- Kubernetes-heavy, GitOps-driven shop — Crossplane is a natural fit
Interview questions
- Compare Terraform, Pulumi, and Crossplane.
- Why is state management the hardest IaC problem?
- How do you organize Terraform code at scale?
Sign up free to read the full topic
More SRE topics
Start free on Cariara · Coding problems · System design studio