Skip to main content

AWS CloudFormation

AWS CloudFormation is a service that helps you model and set up your Amazon Web Services resources so you can spend less time managing those resources and more time focusing on your applications that run in AWS. You create a template that describes all the AWS resources that you want, and CloudFormation takes care of provisioning and configuring those resources for you.

What is CloudFormation?

CloudFormation is AWS's native Infrastructure as Code (IaC) service that allows you to define your cloud infrastructure using JSON or YAML templates. It provides a common language for describing and provisioning all the infrastructure resources in your cloud environment.

Key Features

  • Template-Based: Define infrastructure using JSON or YAML templates
  • Declarative: Describe what you want, not how to create it
  • AWS Native: Deep integration with all AWS services
  • Stack Management: Group related resources into manageable stacks
  • Rollback Capability: Automatic rollback on deployment failures
  • Change Sets: Preview changes before applying them
  • Cross-Stack References: Share resources between stacks

Core Concepts

1. Templates

CloudFormation templates are JSON or YAML files that describe your AWS resources:

# template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "Simple EC2 instance"

Parameters:
InstanceType:
Type: String
Default: t2.micro
AllowedValues:
- t2.micro
- t2.small
- t2.medium

Resources:
MyEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0c02fb55956c7d316
InstanceType: !Ref InstanceType
Tags:
- Key: Name
Value: MyInstance

Outputs:
InstanceId:
Description: Instance ID of the EC2 instance
Value: !Ref MyEC2Instance
Export:
Name: MyInstanceId

2. Stacks

A stack is a collection of AWS resources that you can manage as a single unit:

# Create a stack
aws cloudformation create-stack \
--stack-name my-stack \
--template-body file://template.yaml

# Update a stack
aws cloudformation update-stack \
--stack-name my-stack \
--template-body file://template.yaml

# Delete a stack
aws cloudformation delete-stack \
--stack-name my-stack

3. Parameters

Make templates reusable by accepting input values:

Parameters:
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- prod
Description: Environment name

VpcCIDR:
Type: String
Default: 10.0.0.0/16
Description: CIDR block for VPC

4. Conditions

Control resource creation based on parameter values:

Conditions:
CreateProdResources: !Equals [!Ref Environment, prod]

Resources:
ProdDatabase:
Type: AWS::RDS::DBInstance
Condition: CreateProdResources
Properties:
DBInstanceClass: db.r5.large
Engine: mysql

5. Mappings

Create lookup tables for values:

Mappings:
RegionMap:
us-east-1:
AMI: ami-0c02fb55956c7d316
us-west-2:
AMI: ami-0c02fb55956c7d316
eu-west-1:
AMI: ami-0c02fb55956c7d316

Resources:
MyInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionMap, !Ref AWS::Region, AMI]

Template Structure

Basic Template Format

AWSTemplateFormatVersion: "2010-09-09"
Description: "Template description"

Parameters:
# Input parameters

Conditions:
# Conditional logic

Mappings:
# Lookup tables

Resources:
# AWS resources

Outputs:
# Stack outputs

Intrinsic Functions

CloudFormation provides built-in functions for dynamic values:

Resources:
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${AWS::StackName}-bucket-${AWS::AccountId}"
WebsiteConfiguration:
IndexDocument: index.html
ErrorDocument: error.html

MyInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref LatestAmi
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd

Common Intrinsic Functions

1. Ref

References parameters, resources, or pseudo parameters:

!Ref MyParameter
!Ref AWS::Region
!Ref MyEC2Instance

2. GetAtt

Gets attributes from resources:

!GetAtt MyEC2Instance.PublicIp
!GetAtt MyLoadBalancer.DNSName

3. Sub

Substitutes variables in strings:

!Sub 'https://${MyBucket}.s3.amazonaws.com'
!Sub
- 'Hello ${Name}'
- Name: !Ref UserName

4. Join

Joins strings with a delimiter:

!Join [",", [!Ref Param1, !Ref Param2, !Ref Param3]]

5. Select

Selects an element from a list:

!Select [0, !GetAZs !Ref AWS::Region]

Advanced Features

1. Nested Stacks

Break complex templates into smaller, manageable pieces:

Resources:
NetworkStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/bucket/network.yaml
Parameters:
VpcCIDR: 10.0.0.0/16

2. Cross-Stack References

Share resources between stacks:

# Stack A - Export
Outputs:
VpcId:
Value: !Ref MyVPC
Export:
Name: !Sub "${AWS::StackName}-VPC-ID"

# Stack B - Import
Resources:
MySubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !ImportValue "NetworkStack-VPC-ID"

3. Custom Resources

Extend CloudFormation with custom logic:

Resources:
CustomResource:
Type: Custom::MyCustomResource
Properties:
ServiceToken: !GetAtt CustomResourceFunction.Arn
Parameter1: value1
Parameter2: value2

4. Stack Sets

Deploy stacks across multiple accounts and regions:

aws cloudformation create-stack-set \
--stack-set-name my-stack-set \
--template-body file://template.yaml \
--capabilities CAPABILITY_IAM

Best Practices

1. Template Design

  • Use parameters for configurable values
  • Implement proper validation for parameters
  • Use conditions for optional resources
  • Organize resources logically
  • Use meaningful resource names

2. Security

  • Use IAM roles and policies properly
  • Implement least privilege access
  • Use AWS Secrets Manager for sensitive data
  • Enable CloudTrail for audit logging
  • Use parameter constraints

3. Error Handling

  • Implement proper rollback triggers
  • Use change sets for preview
  • Test templates in dev environment first
  • Use stack policies for protection
  • Monitor stack events

4. Performance

  • Use nested stacks for large templates
  • Implement proper dependencies
  • Use cross-stack references efficiently
  • Optimize template size
  • Use stack sets for multi-account deployments

Common Use Cases

1. Web Application Stack

Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16

PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs !Ref AWS::Region]

InternetGateway:
Type: AWS::EC2::InternetGateway

AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway

PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC

DefaultPublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway

WebServer:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0c02fb55956c7d316
InstanceType: t2.micro
SubnetId: !Ref PublicSubnet
SecurityGroupIds:
- !Ref WebServerSecurityGroup

2. Database Stack

Resources:
DatabaseSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Subnet group for RDS
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2

Database:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceIdentifier: my-database
DBName: myapp
DBInstanceClass: db.t3.micro
Engine: mysql
EngineVersion: "8.0"
MasterUsername: admin
MasterUserPassword: !Ref DatabasePassword
DBSubnetGroupName: !Ref DatabaseSubnetGroup
VPCSecurityGroups:
- !Ref DatabaseSecurityGroup

CloudFormation vs Other Tools

FeatureCloudFormationTerraformOpenTofuPulumi
LanguageJSON/YAMLHCLHCLPython/TypeScript/Go
ProviderAWS OnlyMulti-CloudMulti-CloudMulti-Cloud
State ManagementAWS ManagedLocal/RemoteLocal/RemoteCloud/File
CostFreeFreeFreeFree/Paid
Learning CurveMediumMediumMediumHard
AWS IntegrationNativeGoodGoodGood

When to Use CloudFormation

Choose CloudFormation when:

  • You're working exclusively with AWS
  • You need deep AWS service integration
  • You want AWS-managed state and operations
  • You prefer JSON/YAML over other languages
  • You need AWS support and documentation
  • You're using AWS Organizations and Stack Sets

Consider alternatives when:

  • You need multi-cloud support
  • You want more flexible programming languages
  • You need advanced state management features
  • You want to avoid vendor lock-in
  • You need more sophisticated templating

CLI Commands

Basic Operations

# Create stack
aws cloudformation create-stack \
--stack-name my-stack \
--template-body file://template.yaml \
--parameters ParameterKey=KeyPairName,ParameterValue=MyKeyPair

# Update stack
aws cloudformation update-stack \
--stack-name my-stack \
--template-body file://template.yaml

# Delete stack
aws cloudformation delete-stack --stack-name my-stack

# Describe stack
aws cloudformation describe-stacks --stack-name my-stack

# List stacks
aws cloudformation list-stacks

Change Sets

# Create change set
aws cloudformation create-change-set \
--stack-name my-stack \
--change-set-name my-change-set \
--template-body file://template.yaml

# Execute change set
aws cloudformation execute-change-set \
--change-set-name my-change-set

Monitoring and Troubleshooting

1. Stack Events

# View stack events
aws cloudformation describe-stack-events --stack-name my-stack

2. Stack Drift Detection

# Detect drift
aws cloudformation detect-stack-drift --stack-name my-stack

# Get drift results
aws cloudformation describe-stack-drift-detection-status \
--stack-drift-detection-id drift-detection-id

3. CloudWatch Integration

  • Stack events are automatically sent to CloudWatch
  • Set up alarms for stack failures
  • Monitor stack resource metrics
  • Use CloudWatch Logs for custom resource debugging