CloudFormation Fundamentals
CloudFormation Fundamentals
AWS CloudFormation models and provisions AWS resources using template files (Infrastructure as Code).
Template Structure
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Simple EC2 Instance'
Parameters:
InstanceType:
Type: String
Default: t3.micro
AllowedValues:
- t3.micro
- t3.small
- t3.medium
Description: EC2 instance type
Resources:
MyInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType
ImageId: ami-0c55b159cbfafe1f0
KeyName: my-key-pair
SecurityGroups:
- !Ref MySecurityGroup
Tags:
- Key: Name
Value: MyWebServer
MySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Outputs:
InstanceId:
Value: !Ref MyInstance
PublicIP:
Value: !GetAtt MyInstance.PublicIp
Template Components
| Component | Purpose |
|---|---|
| Parameters | Input values (user-provided) |
| Resources | AWS resources to create |
| Outputs | Values to return |
| Conditions | Conditional resource creation |
| Mappings | Static lookup tables |
| Metadata | Additional information |
Intrinsic Functions
Intrinsic Functions
Common Functions
# !Ref - Reference a resource or parameter
ImageId: !Ref LatestAmiId
# !GetAtt - Get attribute from a resource
VpcId: !GetAtt MyVPC.VpcId
# !Sub - String substitution
ResourceName: !Sub '${AWS::StackName}-instance'
DNSName: !Sub 'https://${DomainName}/api'
# !Join - Concatenate values
Arn: !Sub 'arn:aws:s3:::${BucketName}/*'
# !Select - Select item from list
Subnet: !Select [0, !GetAZs '']
# !GetAZs - Get availability zones
AZs: !GetAZs Ref: 'AWS::Region'
# !If - Conditional
InstanceType: !If [IsProd, m5.large, t3.micro]
# !Not, !Equals, !And, !Or
Condition: !Not [!Equals [!Ref Env, dev]]
Conditions
Conditions:
IsProd: !Equals [!Ref Env, production]
IsDev: !Equals [!Ref Env, development]
CreateBackup: !Or [!Condition IsProd, !Equals [!Ref EnableBackup, true]]
Resources:
BackupVolume:
Type: AWS::EC2::Volume
Condition: CreateBackup
Properties:
AvailabilityZone: !Select [0, !GetAZs '']
Size: 100
VolumeType: gp3
Mappings
Mappings:
RegionMap:
us-east-1:
AMI: ami-0c55b159cbfafe1f0
InstanceType: t3.micro
eu-west-1:
AMI: ami-0d71ea30421e2c917
InstanceType: t3.micro
ap-southeast-1:
AMI: ami-0dbbe3f2db8a1c51a
InstanceType: t3.small
Resources:
Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI]
InstanceType: !FindInMap [RegionMap, !Ref 'AWS::Region', InstanceType]
Stacks and Stack Sets
Stacks and Stack Sets
Create and Manage Stacks
# Create a stack
aws cloudformation create-stack \
--stack-name my-stack \
--template-body file://template.yaml \
--parameters ParameterKey=InstanceType,ParameterValue=t3.micro \
--capabilities CAPABILITY_NAMED_IAM \
--tags Key=Environment,Value=Dev
# Wait for completion
aws cloudformation wait stack-create-complete --stack-name my-stack
# 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
# List stacks
aws cloudformation list-stacks --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE
# Get stack events
aws cloudformation describe-stack-events --stack-name my-stack
Change Sets
Preview changes before applying:
# Create change set
aws cloudformation create-change-set \
--stack-name my-stack \
--change-set-name my-changes \
--template-body file://template.yaml
# Describe change set
aws cloudformation describe-change-set \
--stack-name my-stack \
--change-set-name my-changes
# Execute change set
aws cloudformation execute-change-set \
--stack-name my-stack \
--change-set-name my-changes
# Delete change set
aws cloudformation delete-change-set \
--stack-name my-stack \
--change-set-name my-changes
Stack Sets
Deploy across multiple accounts and regions:
# Create stack set
aws cloudformation create-stack-set \
--stack-set-name my-stackset \
--template-body file://template.yaml \
--permission-model SERVICE_MANAGED
# Deploy to accounts
aws cloudformation create-stack-instances \
--stack-set-name my-stackset \
--accounts '123456789012,987654321098' \
--regions us-east-1 eu-west-1
# Check status
aws cloudformation describe-stack-set-operation \
--stack-set-name my-stackset \
--operation-id xxx
Drift Detection and Stack Policies
Drift Detection and Stack Policies
Drift Detection
# Detect drift
aws cloudformation detect-stack-drift \
--stack-name my-stack
# Describe drift status
aws cloudformation describe-stack-drift-detection-status \
--stack-drift-detection-id xxx
# List drifted resources
aws cloudformation describe-stack-resource-drifts \
--stack-name my-stack \
--stack-resource-drift-status-filters MODIFIED DELETED
Stack Policies
{
"Statement": [
{
"Effect": "Allow",
"Action": "Update:*",
"Principal": "*",
"Resource": "*",
"Condition": {
"StringNotEquals": {
"ResourceType": [
"AWS::RDS::DBInstance",
"AWS::ElasticLoadBalancerV2::LoadBalancer"
]
}
}
}
]
}
# Set stack policy
aws cloudformation set-stack-policy \
--stack-name my-stack \
--stack-policy-body file://policy.json
# Get stack policy
aws cloudformation get-stack-policy --stack-name my-stack
Nested Stacks
# Parent template
Resources:
VPCStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/my-bucket/vpc.yaml
Parameters:
VpcCIDR: 10.0.0.0/16
WebStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/my-bucket/web.yaml
Parameters:
VpcId: !GetAtt VPCStack.Outputs.VpcId
SubnetId: !GetAtt VPCStack.Outputs.PublicSubnet
CloudFormation Best Practices
CloudFormation Best Practices
Template Best Practices
# Use parameters for reusable templates
Parameters:
Environment:
Type: String
AllowedValues: [dev, staging, prod]
Default: dev
# Use mappings for region-specific values
# Use conditions for environment-specific resources
# Use outputs to export values
Outputs:
VpcId:
Value: !Ref MyVPC
Export:
Name: !Sub '${AWS::StackName}-VpcId'
SubnetId:
Value: !Ref PublicSubnet
Export:
Name: !Sub '${AWS::StackName}-SubnetId'
CLI Commands
# Validate template
aws cloudformation validate-template --template-body file://template.yaml
# Estimate costs
aws cloudformation estimate-template-cost --template-body file://template.yaml
# Package local templates
aws cloudformation package \
--template-file template.yaml \
--s3-bucket my-template-bucket \
--output-template-file packaged.yaml
# Deploy with guided prompts
aws cloudformation deploy \
--template-file packaged.yaml \
--stack-name my-stack \
--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM \
--parameter-overrides Env=prod InstanceType=m5.large
Security
- Never store secrets in templates
- Use SSM Parameter Store or Secrets Manager
- Use least-privilege IAM roles
- Enable CloudTrail for audit logging
- Use stack policies to protect critical resources