Infrastructure as Code
Manage AWS infrastructure declaratively with CloudFormation, Terraform, and AWS CDK — version control, reproducibility, and automated provisioning.
Infrastructure as Code Principles
IaC defines infrastructure in code files rather than manual console clicks. Benefits: version control, reproducibility, peer review, automated testing, and disaster recovery. The same templates deploy identical environments.
Treat infrastructure code like application code: code review, CI/CD pipelines, testing, and documentation.
- Never modify production infrastructure manually
- Store IaC in git alongside application code
- Use separate state/stacks per environment
# IaC workflow # 1. Write infrastructure definition (YAML/HCL/TypeScript) # 2. Code review via pull request # 3. CI validates template (lint, security scan) # 4. Deploy to staging automatically # 5. Manual approval for production # 6. Deploy to production # 7. Drift detection monitors changes
AWS CloudFormation
CloudFormation is AWS native IaC service. Define resources in YAML or JSON templates. Stacks are deployed instances of templates. CloudFormation handles dependency ordering, rollback on failure, and drift detection.
Use nested stacks for modular templates. StackSets deploy across accounts and regions. Change sets preview modifications before applying.
AWSTemplateFormatVersion: '2010-09-09'
Description: Web application stack
Resources:
WebBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub '${AWS::StackName}-assets'
VersioningConfiguration:
Status: Enabled
Outputs:
BucketUrl:
Value: !GetAtt WebBucket.WebsiteURL
Export:
Name: !Sub '${AWS::StackName}-BucketUrl'Terraform
Terraform by HashiCorp is cloud-agnostic IaC using HCL syntax. The AWS provider covers all AWS services. State files track deployed resources. Plan/apply workflow previews and executes changes.
Terraform excels at multi-cloud deployments and has a larger module ecosystem. Use remote state (S3 + DynamoDB locking) for team collaboration.
resource "aws_s3_bucket" "assets" {
bucket = "${var.project}-assets"
}
resource "aws_s3_bucket_versioning" "assets" {
bucket = aws_s3_bucket.assets.id
versioning_configuration {
status = "Enabled"
}
}
output "bucket_url" {
value = aws_s3_bucket.assets.bucket_regional_domain_name
}AWS CDK
Cloud Development Kit (CDK) defines infrastructure in programming languages — TypeScript, Python, Java, C#, Go. CDK synthesizes to CloudFormation templates. Higher-level constructs simplify common patterns.
CDK appeals to developers who prefer code over YAML. L3 constructs (patterns) deploy entire architectures — a Lambda API with one construct call.
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
const app = new cdk.App();
const stack = new cdk.Stack(app, 'MyStack');
new s3.Bucket(stack, 'AssetsBucket', {
versioned: true,
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
});
app.synth();Comparing IaC Tools
CloudFormation: AWS-native, no additional tooling, deep AWS integration. Terraform: multi-cloud, large community, HCL syntax. CDK: programming languages, high-level abstractions, generates CloudFormation.
Many teams use CDK or Terraform for daily work and CloudFormation indirectly. Choose based on team skills and multi-cloud requirements.
- CDK synthesizes to CloudFormation — use cdk deploy
- Terraform state is critical — back up and lock remote state
- Use cfn-lint and tflint for template validation in CI
# Tool selection guide # CloudFormation: AWS-only, YAML/JSON, no extra tools # Terraform: multi-cloud, HCL, largest module registry # CDK: TypeScript/Python, developer-friendly, AWS-focused # SAM: serverless-focused, extends CloudFormation # Pulumi: general-purpose languages, multi-cloud
IaC Best Practices
Modularize templates by service or feature. Parameterize environment differences. Use consistent tagging strategies. Implement policy as code with cfn-guard or Sentinel. Test templates with taskcat or terratest.
Enable drift detection to catch manual console changes. Import existing resources into IaC management rather than recreating them.
# CI pipeline for IaC # 1. cfn-lint template.yaml (CloudFormation) # 2. tflint (Terraform) # 3. cdk synth && diff against deployed stack # 4. cfn-guard / checkov security scan # 5. Deploy to staging on merge # 6. Manual approval → deploy production