20. Infrastructure as Code
Infrastructure as Code
TL;DR
- CloudFormation is AWS-native IaC; CDK compiles to CloudFormation but adds programming constructs (loops, conditionals).
- Terraform is multi-cloud IaC with separate state file management; choose based on actual multi-cloud requirement, not just preference.
- StackSets deploy stacks consistently across many accounts/Regions; pairs well with Terraform for application infrastructure.
- Drift detection reports divergence between IaC and live infrastructure; it does not prevent manual changes.
- GitOps enforces Git as the deployment trigger and source of truth; infrastructure changes only through reviewed Git merges.
- The real risk is not the tool choice; it’s whether IaC is the enforced deployment path or just a description that manual changes bypass.
Core Concepts
CloudFormation: AWS-Native Declarative IaC
CloudFormation is AWS’s native service for declaring infrastructure as templates (YAML or JSON). AWS tracks stack state internally; no separate state file to manage.
Advantages:
- Deep AWS service integration.
- No separate state file; AWS is the source of truth.
- CloudFormation Change Sets preview changes before applying.
Disadvantages:
- Declarative YAML/JSON gets verbose with complex logic.
- Conditional logic and loops in raw YAML are awkward.
AWS CDK: Programming-Based IaC
AWS CDK lets you define infrastructure in TypeScript, Python, Java, or other languages, compiling to CloudFormation templates underneath.
Advantages:
- Loops, conditionals, and functions for complex infrastructure.
- Reusable constructs (Construct Hub has pre-built patterns).
- Type-safe infrastructure definitions.
Critical caveat: CDK is an abstraction over CloudFormation. Teams that treat CDK as a black box struggle to debug deployment failures because they don’t understand the generated CloudFormation. Understanding the underlying CloudFormation is essential for troubleshooting.
Example: A CDK variable name typo results in a CloudFormation error referencing an undefined property. Debugging requires reading the generated template.
Terraform: Multi-Cloud IaC
Terraform uses HCL (HashiCorp Configuration Language) as a declarative IaC language. Unlike CloudFormation, Terraform maintains a separate state file (typically in S3 with DynamoDB locking for multi-user concurrency).
When to choose Terraform:
- Genuine multi-cloud requirement (AWS, Azure, GCP).
- Organization already has deep Terraform investment and tooling.
When not to: Single-cloud AWS deployments; CloudFormation or CDK is usually simpler.
Trade-off: Terraform state file management is an operational burden. Losing or corrupting the state file can be catastrophic. Remote state (S3 + DynamoDB locking) is the standard pattern.
StackSets: Multi-Account, Multi-Region Rollout
StackSets deploy CloudFormation stacks consistently across many AWS accounts and Regions from a single place. The canonical use case: roll out organizational guardrails (a mandatory CloudTrail configuration, a baseline IAM policy) to every account in an AWS Organization.
Important: Choosing Terraform for application infrastructure doesn’t eliminate StackSets’ value for AWS-native, foundational, org-wide rollout. They are not mutually exclusive. StackSets handles org-wide governance; Terraform handles application infrastructure.
Drift Detection: Reporting, Not Prevention
Drift detection compares live infrastructure with the IaC definition and reports discrepancies. Example: A security group rule was manually added via the console; drift detection finds it and reports it.
What drift detection does: Reports the discrepancy.
What it doesn’t do:
- Prevent the manual change from happening.
- Automatically resolve which side is correct (the IaC definition or the live infrastructure).
- Delete the manual change automatically.
Real-world example: Drift detection shows a manually-added inbound security group rule. Is the rule correct and should IaC be updated? Or is the rule a mistake and should be removed? Drift detection doesn’t answer; a human must investigate.
Operational requirement: Drift detection is only effective if findings are reviewed. A configured-but-unreviewed drift detection dashboard is equivalent to not having it.
GitOps: Git as Deployment Trigger and Source of Truth
GitOps goes beyond “IaC files live in Git.” It enforces Git as the actual deployment trigger:
- IaC changes are proposed as pull requests.
- PR review happens before merge.
- Merge to the main branch triggers an automated deployment.
- Continuous reconciliation: if live infrastructure drifts from Git, a reconciliation operator reverts it.
Enforcement mechanism: If the only path to changing infrastructure is a reviewed Git merge, there is no manual console change to drift from.
Example anti-pattern: A GitOps pipeline that auto-applies infrastructure changes without PR review. This just moves the unreviewed-change risk from the console to unreviewed commits.
Comparison Table
| Aspect | CloudFormation | AWS CDK | Terraform |
|---|---|---|---|
| Language | YAML/JSON | TypeScript/Python/etc. | HCL |
| State management | AWS-managed | AWS-managed (CloudFormation) | Separate state file |
| Multi-cloud | AWS only | AWS only | Multi-cloud |
| Abstraction level | Low | High (compiles to CloudFormation) | Medium |
| Best for | AWS-native, strict templates | Complex AWS patterns, reusable constructs | Multi-cloud, orgs with existing Terraform investment |
Command/Configuration Reference
CloudFormation Drift Detection
Detect drift:
aws cloudformation detect-stack-drift \
--stack-name my-stack
Check results:
aws cloudformation describe-stack-drift-detection-status \
--stack-drift-detection-id <detection-id>
CDK Deployment with Context
Synthesize CloudFormation template:
cdk synth --context @aws-cdk/core:newStyleStackSynthesis=true
Deploy with change set review:
cdk deploy --require-approval never # Auto-approve (use carefully)
cdk deploy # Prompts for approval (recommended)
Terraform State Management
Initialize and lock state in S3:
terraform init \
-backend-config="bucket=my-state-bucket" \
-backend-config="key=prod/terraform.tfstate" \
-backend-config="dynamodb_table=terraform-locks"
Plan changes:
terraform plan -out=tfplan
terraform apply tfplan
Common Pitfalls
| Pitfall | Why | Fix |
|---|---|---|
| IaC describes infrastructure on day one, then manual changes accumulate | Console fixes under incident pressure aren’t reflected in IaC. Drift grows over time. | Enforce console/CLI access restrictions via IAM or SCPs. IaC must be the only deployment path. |
| CDK treated as a black box | Team doesn’t understand the generated CloudFormation. Deployment failures become mysteries. | Require the team to read and understand generated CloudFormation templates, especially during troubleshooting. |
| Drift detection configured but never reviewed | Findings accumulate; drift is ignored until a security review surfaces it. | Schedule drift detection reviews. Route findings to alerting. Assign someone to investigate. |
| No access controls on IaC-managed resources | Manual console changes can happen at any time, making drift a permanent condition. | Restrict console/CLI write access to IaC-managed resources via IAM roles or SCPs. |
| GitOps pipeline auto-applies without PR review | Unreviewed changes in Git are as risky as unreviewed console changes. | Require PR review before merge. Merge triggers deployment automatically. |
| Terraform state file managed locally | Losing the state file is catastrophic. Multi-user concurrency is unmanaged. | Use remote state in S3 with DynamoDB locking. Never commit state files to Git. |
Interview Questions
-
A CDK deployment fails with a cryptic CloudFormation error. Walk me through your debugging approach. — Tests whether the candidate can drop down to the underlying CloudFormation template to troubleshoot, not just re-run the CDK command.
-
Your drift detection dashboard shows 20 stacks with drift. Walk me through your actual remediation process. — Tests understanding of drift as a signal requiring investigation and architectural prevention, not just a dashboard metric.
-
Explain the difference between “our Terraform is in Git” and a real GitOps workflow. — Tests understanding of enforcement mechanisms: Git as the sole deployment trigger, with automated reconciliation if infrastructure drifts.
-
When would you choose Terraform over CloudFormation and CDK for an AWS-only organization? — Tests understanding of actual trade-offs: Terraform is multi-cloud IaC, not AWS-specific. The choice should be based on genuine multi-cloud requirement, not preference.