Cloudformation
Chapter 40: AWS CloudFormation
Section titled “Chapter 40: AWS CloudFormation”This chapter covers AWS CloudFormation as an alternative Infrastructure as Code solution.
What is CloudFormation?
Section titled “What is CloudFormation?”CloudFormation is AWS’s native Infrastructure as Code solution.
┌─────────────────────────────────────────────────────────────────────────────┐│ CloudFormation Overview │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌─────────────────────────────────────────────────────────────────────┐ ││ │ CloudFormation Process │ ││ │ │ ││ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ ││ │ │ Template │───▶│ Create │───▶│ Resources │ │ ││ │ │ (YAML/JSON)│ │ Stack │ │ Created │ │ ││ │ └─────────────┘ └─────────────┘ └─────────────┘ │ ││ │ │ ││ └─────────────────────────────────────────────────────────────────────┘ ││ ││ Features: ││ ✓ AWS-native - Integrated with all AWS services ││ ✓ Declarative - Define desired state ││ ✓ Idempotent - Safe to run multiple times ││ ✓ Drift detection - Identify manual changes ││ ✓ Change sets - Preview changes before applying ││ │└─────────────────────────────────────────────────────────────────────────────┘CloudFormation vs Terraform
Section titled “CloudFormation vs Terraform”┌─────────────────────────────────────────────────────────────────────────────┐│ CloudFormation vs Terraform │├─────────────────────────────────────────────────────────────────────────────┤│ ││ Feature CloudFormation Terraform ││ ────────────────────────────────────────────────────────────────────── ││ Provider AWS-only Multi-cloud ││ Language YAML or JSON HCL ││ State AWS-managed User-managed ││ Learning Curve Low Moderate ││ Drift Detection Built-in Manual ││ Modules Nested Stacks Registry Modules ││ Updates Change Sets Plan ││ ││ When to use CloudFormation: ││ ✓ AWS-only environments ││ ✓ Team already familiar with AWS ││ ✓ Need native drift detection ││ ✓ Strong AWS service support needed ││ ││ When to use Terraform: ││ ✓ Multi-cloud infrastructure ││ ✓ Complex modules needed ││ ✓ Need better state management ││ ✓ Existing Terraform expertise ││ │└─────────────────────────────────────────────────────────────────────────────┘CloudFormation Template Structure
Section titled “CloudFormation Template Structure”AWSTemplateFormatVersion: '2010-09-09'Description: 'My CloudFormation Template'
Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: 'Network Configuration' Parameters: - VPCCidr - SubnetCidr - Label: default: 'Compute Configuration' Parameters: - InstanceType
Parameters: VPCCidr: Type: String Default: '10.0.0.0/16' Description: 'CIDR block for VPC'
InstanceType: Type: String Default: 't3.micro' AllowedValues: - t3.micro - t3.small - t3.medium Description: 'EC2 instance type'
Mappings: RegionAMI: us-east-1: AMI: 'ami-0c55b159cbfafe1f0' us-west-2: AMI: 'ami-0892d3c7ee96c0bf7'
Conditions: IsProd: !Equals [!Ref Environment, 'prod']
Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VPCCidr EnableDnsHostnames: true EnableDnsSupport: true Tags: - Key: Name Value: !Sub '${AWS::StackName}-vpc'
Subnet: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: '10.0.1.0/24' AvailabilityZone: !Select [0, !GetAZs ''] MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Sub '${AWS::StackName}-subnet'
Outputs: VPCId: Description: 'VPC ID' Value: !Ref VPC Export: Name: !Sub '${AWS::StackName}-VPCID'
SubnetId: Description: 'Subnet ID' Value: !Ref SubnetIntrinsic Functions
Section titled “Intrinsic Functions”# Intrinsic Functions Examples
# Ref - Reference parameter or resourceVPCId: !Ref MyVPC
# Fn::GetAtt - Get attribute from resourceInstancePrivateIP: !GetAtt MyInstance.PrivateIp
# Fn::Sub - Substitute valuesStackName: !Sub '${AWS::StackName}-resource'
# Fn::Join - Join stringsJoinExample: !Join ['', ['arn:', !Ref AWS::Partition, ':ec2:', !Ref AWS::Region, ':', !Ref AWS::AccountId, ':instance/', !Ref MyInstance]]
# Fn::Select - Select from listAZ: !Select [0, !GetAZs '']
# Fn::Equals - Compare valuesIsProduction: !Equals [!Ref Environment, 'prod']
# Fn::If - ConditionalConditionalSG: !If [CreateProductionSG, !Ref ProductionSG, !Ref DevSG]
# Fn::Not - NegateNotDev: !Not [!Equals [!Ref Environment, 'dev']]
# Fn::And - Logical ANDBoth: !And [!Condition IsProd, !Condition HasBackup]
# Fn::Or - Logical OREither: !Or [!Condition IsProd, !Condition HasBackup]
# Fn::FindInMap - Look up in mappingAMI: !FindInMap [RegionAMI, !Ref AWS::Region, AMI]Working with Stacks
Section titled “Working with Stacks”# Create stackaws cloudformation create-stack \ --stack-name my-stack \ --template-body file://template.yaml \ --parameters ParameterKey=InstanceType,ParameterValue=t3.micro \ --capabilities CAPABILITY_IAM
# Update stackaws cloudformation update-stack \ --stack-name my-stack \ --template-body file://template.yaml \ --parameters ParameterKey=InstanceType,ParameterValue=t3.small
# Describe stackaws cloudformation describe-stacks \ --stack-name my-stack
# Delete stackaws cloudformation delete-stack \ --stack-name my-stack
# List stacksaws cloudformation list-stacks \ --stack-status-filter CREATE_COMPLETE
# Get templateaws cloudformation get-template \ --stack-name my-stack
# List stack resourcesaws cloudformation list-stack-resources \ --stack-name my-stackChange Sets
Section titled “Change Sets”# Create change setaws cloudformation create-change-set \ --stack-name my-stack \ --change-set-name my-changes \ --template-body file://template.yaml \ --parameters ParameterKey=InstanceType,ParameterValue=t3.medium
# Describe change setaws cloudformation describe-change-set \ --stack-name my-stack \ --change-set-name my-changes
# Execute change setaws cloudformation execute-change-set \ --stack-name my-stack \ --change-set-name my-changes
# Delete change setaws cloudformation delete-change-set \ --stack-name my-stack \ --change-set-name my-changesDrift Detection
Section titled “Drift Detection”┌─────────────────────────────────────────────────────────────────────────────┐│ Drift Detection │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌─────────────────────────────────────────────────────────────────────┐ ││ │ Detect Drift │ ││ │ │ ││ │ aws cloudformation detect-stack-drift \ │ ││ │ --stack-name my-stack │ ││ │ │ ││ └─────────────────────────────────────────────────────────────────────┘ ││ ││ ┌─────────────────────────────────────────────────────────────────────┐ ││ │ Check Drift Status │ ││ │ │ ││ │ aws cloudformation describe-stack-drift-detection-status \ │ ││ │ --stack-name my-stack │ ││ │ │ ││ │ Returns: │ ││ │ • DRIFTED - Stack has drifted │ ││ │ • IN_SYNC - No drift detected │ ││ │ • UNKNOWN - Detection still in progress │ ││ │ • NOT_CHECKED - Drift not detected yet │ ││ │ │ ││ └─────────────────────────────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────────────────────┘Nested Stacks
Section titled “Nested Stacks”# Parent stackResources: VPCStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://s3.amazonaws.com/my-bucket/vpc-template.yaml Parameters: VPCCidr: 10.0.0.0/16 Environment: !Ref Environment
ComputeStack: Type: AWS::CloudFormation::Stack TemplateURL: https://s3.amazonaws.com/my-bucket/compute-template.yaml Parameters: VPCId: !GetAtt VPCStack.Outputs.VPCId SubnetIds: !GetAtt VPCStack.Outputs.SubnetIdsStackSets
Section titled “StackSets”┌─────────────────────────────────────────────────────────────────────────────┐│ StackSets Overview │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌─────────────────────────────────────────────────────────────────────┐ ││ │ StackSets │ ││ │ │ ││ │ ┌──────────────────────────────────────────────────────────┐ │ ││ │ │ StackSet Template │ │ ││ │ └──────────────────────────────────────────────────────────┘ │ ││ │ │ │ ││ │ ┌──────────────────┼──────────────────┐ │ ││ │ ▼ ▼ ▼ │ ││ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ ││ │ │ Account 1 │ │ Account 2 │ │ Account 3 │ │ ││ │ │ Region A │ │ Region A │ │ Region B │ │ ││ │ └────────────┘ └────────────┘ └────────────┘ │ ││ │ │ ││ └─────────────────────────────────────────────────────────────────────┘ ││ ││ Use cases: ││ ✓ Deploy to multiple accounts ││ ✓ Deploy to multiple regions ││ ✓ Centralized compliance ││ │└─────────────────────────────────────────────────────────────────────────────┘# Create StackSetaws cloudformation create-stack-set \ --stack-set-name my-stackset \ --template-body file://template.yaml \ --capabilities CAPABILITY_IAM
# Add stack instancesaws cloudformation create-stack-instances \ --stack-set-name my-stackset \ --accounts '["123456789012", "987654321098"]' \ --regions '["us-east-1", "us-west-2"]' \ --operation-indication-bearing
# Update StackSetaws cloudformation update-stack-set \ --stack-set-name my-stackset \ --template-body file://updated-template.yamlCloudFormation Best Practices
Section titled “CloudFormation Best Practices”# Best Practices
# 1. Use Parameters for flexibilityParameters: Environment: Type: String AllowedValues: - dev - staging - prod Description: 'Deployment environment'
# 2. Use Mappings for region-specific valuesMappings: RegionMap: us-east-1: HVM64: 'ami-0c55b159cbfafe1f0' us-west-2: HVM64: 'ami-0892d3c7ee96c0bf7'
# 3. Use Outputs for cross-stack referencesOutputs: VPCId: Value: !Ref VPC Export: Name: !Sub '${AWS::StackName}-VPCID'
# 4. Enable termination protectionResources: MyStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://s3.amazonaws.com/bucket/template.yaml TerminationProtection: true
# 5. Use Stack Policiesaws cloudformation set-stack-policy \ --stack-name my-stack \ --stack-policy-body file://policy.json{ "Statement" : [ { "Effect" : "Allow", "Action" : "Update:*", "Principal": "*", "Resource" : "*" }, { "Effect" : "Deny", "Action" : "Update:*", "Principal": "*", "Resource" : "LogicalResourceId/ProductionDatabase" } ]}Summary
Section titled “Summary”In this chapter, you learned:
- CloudFormation Overview: AWS-native IaC solution
- CloudFormation vs Terraform: When to choose which
- Template Structure: YAML/JSON format, sections
- Intrinsic Functions: Ref, GetAtt, Sub, Select, If, etc.
- Stack Operations: Create, update, delete, describe
- Change Sets: Preview changes safely
- Drift Detection: Identify manual changes
- Nested Stacks: Modular templates
- StackSets: Multi-account, multi-region deployments
- Best Practices: Parameters, mappings, outputs, policies