CloudFormation
AWS CloudFormation
Model and provision AWS infrastructure with templates
AWS CloudFormation enables you to model, provision, and manage AWS resources using infrastructure as code (IaC).
Why CloudFormation?
| Benefit | Description |
|---|---|
| Automation | Provision resources automatically |
| Consistency | Same template = same infrastructure |
| Version Control | Track infrastructure changes in Git |
| Rollback | Automatic rollback on failure |
| Cost Tracking | Tag resources for billing |
Stack Lifecycle
Template Structure
YAML Format (Recommended)
AWSTemplateFormatVersion: '2010-09-09'
Description: My CloudFormation Template
Parameters:
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- prod
Mappings:
RegionMap:
us-east-1:
AMI: ami-12345678
Conditions:
IsProduction: !Equals [!Ref Environment, prod]
Resources:
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub my-bucket-${Environment}
Outputs:
BucketName:
Value: !Ref MyBucket
Export:
Name: MyBucketNameTemplate Sections
Parameters
Accept input values at runtime:
Parameters:
InstanceType:
Type: String
Default: t3.micro
AllowedValues:
- t3.micro
- t3.small
- t3.medium
Description: EC2 instance type
DatabasePassword:
Type: String
NoEcho: true
MinLength: 8
Description: Database passwordParameter Types:
StringNumberList<Number>CommaDelimitedListAWS::SSM::Parameter::Value<String>- AWS-specific types (VPC ID, Subnet ID, etc.)
Mappings
Static lookup tables:
Mappings:
EnvironmentConfig:
dev:
InstanceType: t3.micro
MinSize: 1
prod:
InstanceType: t3.large
MinSize: 3
Resources:
Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !FindInMap [EnvironmentConfig, !Ref Environment, InstanceType]Conditions
Conditional resource creation:
Conditions:
CreateProdResources: !Equals [!Ref Environment, prod]
UseMultiAZ: !Or
- !Equals [!Ref Environment, prod]
- !Equals [!Ref Environment, staging]
Resources:
ProdOnlyBucket:
Type: AWS::S3::Bucket
Condition: CreateProdResourcesResources
Define AWS resources:
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Tags:
- Key: Name
Value: MyVPC
Subnet:
Type: AWS::EC2::Subnet
DependsOn: VPC
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24Outputs
Export values for cross-stack references:
Outputs:
VPCId:
Description: VPC ID
Value: !Ref VPC
Export:
Name: !Sub ${AWS::StackName}-VPCId
# Import in another stack
# !ImportValue stack-name-VPCIdIntrinsic Functions
| Function | Description | Example |
|---|---|---|
!Ref | Reference parameter or resource | !Ref MyBucket |
!GetAtt | Get resource attribute | !GetAtt MyBucket.Arn |
!Sub | String substitution | !Sub arn:aws:s3:::${BucketName} |
!Join | Join strings | !Join ['-', [a, b, c]] |
!Split | Split string | !Split [',', 'a,b,c'] |
!Select | Select from list | !Select [0, !Ref MyList] |
!If | Conditional value | !If [IsProd, t3.large, t3.micro] |
!Equals | Compare values | !Equals [!Ref Env, prod] |
!And / !Or | Logical operators | !And [Cond1, Cond2] |
!Not | Logical not | !Not [!Equals [!Ref Env, dev]] |
!FindInMap | Look up in mappings | !FindInMap [Map, Key1, Key2] |
!ImportValue | Import from other stack | !ImportValue VPCId |
!Base64 | Encode to Base64 | !Base64 !Ref Script |
Pseudo Parameters
Built-in parameters available in all templates:
| Parameter | Description |
|---|---|
AWS::AccountId | Current account ID |
AWS::Region | Current region |
AWS::StackName | Stack name |
AWS::StackId | Stack ID |
AWS::NoValue | Remove property |
AWS::URLSuffix | Domain suffix (amazonaws.com) |
Resources:
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub my-bucket-${AWS::AccountId}-${AWS::Region}Resource Attributes
DependsOn
Explicit dependency:
Resources:
Database:
Type: AWS::RDS::DBInstance
DependsOn: VPCGatewayAttachmentDeletionPolicy
Control what happens when resource is deleted:
Resources:
Database:
Type: AWS::RDS::DBInstance
DeletionPolicy: Snapshot # Retain, Delete, SnapshotUpdateReplacePolicy
Control updates that require replacement:
Resources:
Database:
Type: AWS::RDS::DBInstance
UpdateReplacePolicy: SnapshotCreationPolicy
Wait for resource to be ready:
Resources:
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
CreationPolicy:
ResourceSignal:
Count: 2
Timeout: PT15MUpdatePolicy
Control rolling updates:
Resources:
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
UpdatePolicy:
AutoScalingRollingUpdate:
MaxBatchSize: 1
MinInstancesInService: 1Nested Stacks
Modularize templates:
Resources:
NetworkStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/bucket/network.yaml
Parameters:
Environment: !Ref Environment
AppStack:
Type: AWS::CloudFormation::Stack
DependsOn: NetworkStack
Properties:
TemplateURL: https://s3.amazonaws.com/bucket/app.yaml
Parameters:
VPCId: !GetAtt NetworkStack.Outputs.VPCIdChange Sets
Preview changes before applying:
# Create change set
aws cloudformation create-change-set \
--stack-name my-stack \
--change-set-name my-change-set \
--template-body file://template.yaml
# View changes
aws cloudformation describe-change-set \
--stack-name my-stack \
--change-set-name my-change-set
# Execute if approved
aws cloudformation execute-change-set \
--stack-name my-stack \
--change-set-name my-change-setStack Policies
Protect resources from updates:
{
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "Update:Replace",
"Resource": "LogicalResourceId/Database"
},
{
"Effect": "Allow",
"Principal": "*",
"Action": "Update:*",
"Resource": "*"
}
]
}CloudFormation StackSets
Deploy to multiple accounts/regions:
aws cloudformation create-stack-set \
--stack-set-name my-stack-set \
--template-body file://template.yaml \
--permission-model SERVICE_MANAGED \
--auto-deployment Enabled=true,RetainStacksOnAccountRemoval=false
aws cloudformation create-stack-instances \
--stack-set-name my-stack-set \
--deployment-targets OrganizationalUnitIds=ou-123abc \
--regions us-east-1 us-west-2Best Practices
Template Organization
- Use nested stacks for modularity
- Separate network, security, and application resources
- Use consistent naming conventions
- Add meaningful descriptions
Security
- Never hardcode secrets
- Use NoEcho for sensitive parameters
- Reference Secrets Manager / SSM Parameter Store
- Use least privilege IAM roles
Reliability
- Use DeletionPolicy for stateful resources
- Implement proper rollback strategies
- Test templates in non-production first
- Use change sets for production updates
Maintenance
- Version control templates
- Use CloudFormation Drift Detection
- Tag resources for cost tracking
- Document dependencies