tessl install github:giuseppe-trisciuoglio/developer-kit --skill aws-cloudformation-vpcgithub.com/giuseppe-trisciuoglio/developer-kit
AWS CloudFormation patterns for VPC infrastructure. Use when creating VPCs, Subnets, Route Tables, NAT Gateways, Internet Gateways, and implementing template structure with Parameters, Outputs, Mappings, Conditions, and cross-stack references.
Review Score
80%
Validation Score
11/16
Implementation Score
65%
Activation Score
100%
Create production-ready VPC infrastructure using AWS CloudFormation templates. This skill covers VPC components (Subnets, Route Tables, NAT Gateways, Internet Gateways), template structure best practices, parameter patterns, and cross-stack references for modular, reusable infrastructure as code.
Use this skill when:
AWSTemplateFormatVersion: 2010-09-09
Description: Simple VPC with public subnet
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-vpc
PublicSubnet:
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}-public-subnet
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-igw
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-public-rt
DefaultPublicRoute:
Type: AWS::EC2::Route
DependsOn: VPCGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet
RouteTableId: !Ref PublicRouteTableAWSTemplateFormatVersion: 2010-09-09
Description: VPC with public and private subnets across multiple AZs
Parameters:
EnvironmentName:
Type: String
Default: production
Description: Environment name for resource tagging
VpcCidr:
Type: String
Default: 10.0.0.0/16
Description: CIDR block for the VPC
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCidr
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Environment
Value: !Ref EnvironmentName
- Key: Name
Value: !Sub ${AWS::StackName}-vpc
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Environment
Value: !Ref EnvironmentName
- Key: Name
Value: !Sub ${AWS::StackName}-igw
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
# Public Subnet 1
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Environment
Value: !Ref EnvironmentName
- Key: SubnetType
Value: Public
- Key: Name
Value: !Sub ${AWS::StackName}-public-1
PublicRouteTable1:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Environment
Value: !Ref EnvironmentName
- Key: Name
Value: !Sub ${AWS::StackName}-public-rt-1
DefaultPublicRoute1:
Type: AWS::EC2::Route
DependsOn: VPCGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable1
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable1
# Private Subnet 1
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.10.0/24
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Environment
Value: !Ref EnvironmentName
- Key: SubnetType
Value: Private
- Key: Name
Value: !Sub ${AWS::StackName}-private-1
PrivateRouteTable1:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Environment
Value: !Ref EnvironmentName
- Key: Name
Value: !Sub ${AWS::StackName}-private-rt-1
PrivateSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateRouteTable1
Outputs:
VpcId:
Description: VPC ID
Value: !Ref VPC
Export:
Name: !Sub ${AWS::StackName}-VpcId
PublicSubnet1Id:
Description: Public Subnet 1 ID
Value: !Ref PublicSubnet1
Export:
Name: !Sub ${AWS::StackName}-PublicSubnet1Id
PrivateSubnet1Id:
Description: Private Subnet 1 ID
Value: !Ref PrivateSubnet1
Export:
Name: !Sub ${AWS::StackName}-PrivateSubnet1IdAWS CloudFormation templates are JSON or YAML files with specific sections. Each section serves a purpose in defining your infrastructure.
AWSTemplateFormatVersion: 2010-09-09 # Required - template version
Description: Optional description string # Optional description
# Section order matters for readability but CloudFormation accepts any order
Mappings: {} # Static configuration tables
Metadata: {} # Additional information about resources
Parameters: {} # Input values for customization
Rules: {} # Parameter validation rules
Conditions: {} # Conditional resource creation
Transform: {} # Macro processing (e.g., AWS::Serverless)
Resources: {} # AWS resources to create (REQUIRED)
Outputs: {} # Return values after stack creationThe AWSTemplateFormatVersion identifies the template version. Current version is 2010-09-09.
AWSTemplateFormatVersion: 2010-09-09
Description: My CloudFormation TemplateAdd a description to document the template's purpose. Must appear after the format version.
AWSTemplateFormatVersion: 2010-09-09
Description: >
This template creates a VPC with public and private subnets
for hosting web applications. It includes:
- Internet Gateway for public access
- NAT Gateway for private subnet outbound access
- Security groups for web and database tiersUse Metadata for additional information about resources or parameters.
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Network Configuration
Parameters:
- VpcCidr
- PublicSubnetCidr
- PrivateSubnetCidr
- Label:
default: Tags
Parameters:
- EnvironmentName
- ProjectName
ParameterLabels:
VpcCidr:
default: VPC CIDR Block
EnvironmentName:
default: Environment NameThe Resources section is the only required section. It defines AWS resources to provision.
Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-vpcUse AWS-specific parameter types for validation and easier selection in the console.
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
Description: Select an existing VPC
SubnetId:
Type: AWS::EC2::Subnet::Id
Description: Select a subnet
SecurityGroupIds:
Type: List<AWS::EC2::SecurityGroup::Id>
Description: Select existing security groups
InstanceType:
Type: AWS::EC2::InstanceType
Description: EC2 instance type
Default: t3.micro
AllowedValues:
- t3.micro
- t3.small
- t3.medium
- t3.large
AmiId:
Type: AWS::EC2::Image::Id
Description: Select an AMI
KeyName:
Type: AWS::EC2::KeyPair::KeyName
Description: Select an existing key pairAdd constraints to validate parameter values.
Parameters:
VpcCidr:
Type: String
Description: CIDR block for the VPC
Default: 10.0.0.0/16
AllowedPattern: ^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}$
ConstraintDescription: Must be a valid CIDR block (x.x.x.x/x)
InstanceCount:
Type: Number
Description: Number of instances to launch
Default: 1
MinValue: 1
MaxValue: 10
Environment:
Type: String
Description: Deployment environment
Default: development
AllowedValues:
- development
- staging
- production
ConstraintDescription: Must be development, staging, or productionReference Systems Manager parameters for dynamic values.
Parameters:
LatestAmiId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Description: Latest AMI ID from SSM
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2Use Mappings for static configuration data based on regions or other factors.
Mappings:
RegionMap:
us-east-1:
HVM64: ami-0ff8a95407f89df2f
HVMG2: ami-0a0c776d80e2a1f3c
us-west-2:
HVM64: ami-0a0c776d80e2a1f3c
HVMG2: ami-0a0c776d80e2a1f3c
eu-west-1:
HVM64: ami-0ff8a95407f89df2f
HVMG2: ami-0a0c776d80e2a1f3c
EnvironmentConfig:
development:
InstanceType: t3.micro
MinInstances: 1
MaxInstances: 2
staging:
InstanceType: t3.small
MinInstances: 1
MaxInstances: 3
production:
InstanceType: t3.medium
MinInstances: 2
MaxInstances: 10
Resources:
Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionMap, !Ref AWS::Region, HVM64]
InstanceType: !FindInMap [EnvironmentConfig, !Ref Environment, InstanceType]Use Conditions to conditionally create resources based on parameters.
Parameters:
DeployNatGateway:
Type: String
Default: true
AllowedValues:
- true
- false
Environment:
Type: String
Default: development
AllowedValues:
- development
- staging
- production
Conditions:
ShouldDeployNat: !Equals [!Ref DeployNatGateway, true]
IsProduction: !Equals [!Ref Environment, production]
Resources:
NatGateway:
Type: AWS::EC2::NatGateway
Condition: ShouldDeployNat
Properties:
AllocationId: !If
- ShouldDeployNat
- !GetAtt EIP.AllocationId
- !Ref AWS::NoValue
SubnetId: !Ref PublicSubnet
ProductionOnlyResource:
Type: AWS::EC2::VPCEndpoint
Condition: IsProduction
Properties:
ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
VpcId: !Ref VPCUse Transform for macros like AWS::Serverless for SAM templates.
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: SAM template for serverless application
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs18.x
CodeUri: function/
Events:
ApiEvent:
Type: Api
Properties:
Path: /{proxy+}
Method: ANYOutputs:
VpcId:
Description: VPC ID
Value: !Ref VPC
PublicSubnetId:
Description: Public Subnet ID
Value: !Ref PublicSubnet
VpcCidr:
Description: VPC CIDR Block
Value: !GetAtt VPC.CidrBlockExport values so other stacks can import them.
Outputs:
VpcId:
Description: VPC ID for other stacks
Value: !Ref VPC
Export:
Name: !Sub ${AWS::StackName}-VpcId
PublicSubnetIds:
Description: Comma-separated public subnet IDs
Value: !Join [",", [!Ref PublicSubnet1, !Ref PublicSubnet2]]
Export:
Name: !Sub ${AWS::StackName}-PublicSubnetIds
PrivateSubnetIds:
Description: Comma-separated private subnet IDs
Value: !Join [",", [!Ref PrivateSubnet1, !Ref PrivateSubnet2]]
Export:
Name: !Sub ${AWS::StackName}-PrivateSubnetIdsParameters:
VpcId:
Type: AWS::EC2::VPC::Id
Description: VPC ID from network stack
# User selects from exported values in console
# Or use Fn::ImportValue for programmatic access
Resources:
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !ImportValue
Fn::Sub: ${NetworkStackName}-VpcId
GroupDescription: Security group for applicationCreate a dedicated network stack that exports values:
# network-stack.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Network infrastructure stack
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-vpc
PublicSubnets:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true
Outputs:
VpcId:
Value: !Ref VPC
Export:
Name: !Sub ${AWS::StackName}-VpcId
PublicSubnetIds:
Value: !Ref PublicSubnets
Export:
Name: !Sub ${AWS::StackName}-PublicSubnetIdsApplication stack imports these values:
# application-stack.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Application stack that imports from network
Parameters:
NetworkStackName:
Type: String
Description: Name of the network stack
Default: network-stack
Resources:
Instance:
Type: AWS::EC2::Instance
Properties:
SubnetId: !ImportValue
Fn::Sub: ${NetworkStackName}-PublicSubnetIds
InstanceType: t3.microAWSTemplateFormatVersion: 2010-09-09
Description: Complete VPC with public/private subnets, NAT, and IGW
Parameters:
EnvironmentName:
Type: String
Default: production
Resources:
# VPC
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-vpc
- Key: Environment
Value: !Ref EnvironmentName
# Internet Gateway
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-igw
- Key: Environment
Value: !Ref EnvironmentName
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
# NAT Gateway (with EIP)
NatGatewayEIP:
Type: AWS::EC2::EIP
DependsOn: InternetGatewayAttachment
Properties:
Domain: vpc
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-nat-eip
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NatGatewayEIP.AllocationId
SubnetId: !Ref PublicSubnet1
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-nat-gw
- Key: Environment
Value: !Ref EnvironmentName
# Public Subnets
PublicSubnet1:
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 ${EnvironmentName}-public-1
- Key: SubnetType
Value: Public
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.2.0/24
AvailabilityZone: !Select [1, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-public-2
- Key: SubnetType
Value: Public
# Private Subnets
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.10.0/24
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-private-1
- Key: SubnetType
Value: Private
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.11.0/24
AvailabilityZone: !Select [1, !GetAZs '']
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-private-2
- Key: SubnetType
Value: Private
# Public Route Table
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-public-rt
DefaultPublicRoute:
Type: AWS::EC2::Route
DependsOn: InternetGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
PublicSubnetRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
# Private Route Table (with NAT)
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-private-rt
DefaultPrivateRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway
PrivateSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateRouteTable
PrivateSubnetRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
RouteTableId: !Ref PrivateRouteTable
Outputs:
VpcId:
Value: !Ref VPC
Export:
Name: !Sub ${EnvironmentName}-VpcId
InternetGatewayId:
Value: !Ref InternetGateway
Export:
Name: !Sub ${EnvironmentName}-InternetGatewayId
PublicSubnetIds:
Value: !Join [",", [!Ref PublicSubnet1, !Ref PublicSubnet2]]
Export:
Name: !Sub ${EnvironmentName}-PublicSubnetIds
PrivateSubnetIds:
Value: !Join [",", [!Ref PrivateSubnet1, !Ref PrivateSubnet2]]
Export:
Name: !Sub ${EnvironmentName}-PrivateSubnetIds
NatGatewayId:
Value: !Ref NatGateway
Export:
Name: !Sub ${EnvironmentName}-NatGatewayIdAlways use AWS-specific parameter types for validation and easier selection.
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
Description: Select a VPC
SubnetIds:
Type: List<AWS::EC2::Subnet::Id>
Description: Select subnets
SecurityGroupIds:
Type: List<AWS::EC2::SecurityGroup::Id>
Description: Select security groupsSeparate resources that change at different rates into different stacks.
# Network stack - rarely changes
AWSTemplateFormatVersion: 2010-09-09
Description: Network infrastructure (VPC, subnets, routes)
Resources:
VPC: AWS::EC2::VPC
Subnets: AWS::EC2::Subnet
RouteTables: AWS::EC2::RouteTable
# Application stack - changes frequently
AWSTemplateFormatVersion: 2010-09-09
Description: Application resources
Parameters:
NetworkStackName:
Type: String
Resources:
Instances: AWS::EC2::InstanceUse AWS::StackName and parameters for consistent naming.
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-vpc
- Key: Environment
Value: !Ref EnvironmentNameUse pseudo parameters for region-agnostic templates.
Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${AWS::StackName}-${AWS::AccountId}-${AWS::Region}
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Runtime: nodejs18.x
Handler: index.handler
Role: !GetAtt LambdaExecutionRole.Arn# Validate template
aws cloudformation validate-template --template-body file://template.yaml
# Check for syntax errors
aws cloudformation validate-template \
--template-body file://template.yaml \
--query 'Description'
# Use cfn-lint for advanced validation
pip install cfn-lint
cfn-lint template.yamlStack Policies prevent unintentional updates to critical resources. Use them to protect production infrastructure.
{
"Statement": [
{
"Effect": "Allow",
"Action": "Update:*",
"Principal": "*",
"Resource": "*"
},
{
"Effect": "Deny",
"Action": ["Update:Replace", "Update:Delete"],
"Principal": "*",
"Resource": "LogicalId=ProductionDatabase"
},
{
"Effect": "Deny",
"Action": "Update:Replace",
"Principal": "*",
"Resource": "LogicalId=VPC"
}
]
}Apply the stack policy:
aws cloudformation set-stack-policy \
--stack-name my-production-stack \
--stack-policy-body file://stack-policy.jsonCommon Stack Policy Use Cases:
Enable termination protection to prevent accidental stack deletion. This is critical for production environments.
Enable via AWS Console:
Enable via AWS CLI:
# Enable termination protection
aws cloudformation update-termination-protection \
--stack-name my-production-stack \
--enable-termination-protection
# Disable termination protection (requires console access)
aws cloudformation update-termination-protection \
--stack-name my-production-stack \
--no-enable-termination-protectionEnable via CloudFormation (for new stacks):
Resources:
ProductionStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/my-bucket/production.yaml
TerminationProtection: trueImportant Considerations:
Drift detection identifies differences between your CloudFormation stack and the actual infrastructure. Run regular drift checks to ensure compliance.
Detect Drift on a Stack:
# Detect drift on a stack
aws cloudformation detect-drift \
--stack-name my-vpc-stack
# Check drift status
aws cloudformation describe-stack-drift-detection-status \
--stack-drift-detection-id <detection-id>
# Get drift detection results
aws cloudformation describe-stack-resource-drifts \
--stack-name my-vpc-stackDrift Status Values:
IN_SYNC: Resource matches the templateDRIFTED: Resource has been modified outside CloudFormationNOT_CHECKED: Resource was not checkedUNKNOWN: Drift status could not be determinedAutomated Drift Detection with Events:
# Use AWS Config for continuous drift monitoring
Resources:
ConfigRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: cloudformation-drift-detection
Scope:
ComplianceResourceTypes:
- AWS::EC2::VPC
- AWS::EC2::Subnet
- AWS::EC2::SecurityGroup
Source:
Owner: CUSTOM_LAMBDA
SourceIdentifier:
Fn::GetAtt: [DriftDetectionFunction, Arn]Best Practices for Drift Detection:
Change Sets allow you to preview stack changes before applying them. This is essential for production deployments.
Create and Review a Change Set:
# Create a change set
aws cloudformation create-change-set \
--stack-name my-vpc-stack \
--template-body file://updated-template.yaml \
--change-set-name vpc-update-changeset \
--capabilities CAPABILITY_IAM
# List change sets
aws cloudformation list-change-sets \
--stack-name my-vpc-stack
# Describe change set
aws cloudformation describe-change-set \
--stack-name my-vpc-stack \
--change-set-name vpc-update-changeset
# Execute change set
aws cloudformation execute-change-set \
--stack-name my-vpc-stack \
--change-set-name vpc-update-changeset
# Delete change set (if not executing)
aws cloudformation delete-change-set \
--stack-name my-vpc-stack \
--change-set-name vpc-update-changesetChange Set Types:
| Type | Description | Use Case |
|---|---|---|
UPDATE | Standard update | Regular changes |
CREATE | Creates new stack | Initial deployment |
IMPORT | Imports existing resources | Lift-and-shift |
Change Set Output Example:
{
"ChangeSetId": "arn:aws:cloudformation:us-east-1:123456789:changeSet/...",
"Changes": [
{
"Type": "Resource",
"ResourceChange": {
"Action": "Modify",
"LogicalResourceId": "VPC",
"PhysicalResourceId": "vpc-12345678",
"Replacement": "False",
"Details": [
{
"Target": {
"Attribute": "Tags",
"RequiresRecreation": "Never"
},
"Evaluation": "Static",
"ChangeSource": "DirectModification"
}
]
}
}
],
"ExecutionStatus": "AVAILABLE",
"Status": "CREATE_COMPLETE"
}Best Practices for Change Sets:
vpc-security-update-2024-01)# GitHub Actions workflow for safe deployments
name: Deploy CloudFormation
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole
aws-region: us-east-1
- name: Create Change Set
id: changeset
run: |
aws cloudformation create-change-set \
--stack-name ${{ env.STACK_NAME }} \
--template-body file://template.yaml \
--change-set-name preview-changes \
--capabilities CAPABILITY_IAM \
--query 'Id' \
--output text
- name: Describe Change Set
run: |
aws cloudformation describe-change-set \
--stack-name ${{ env.STACK_NAME }} \
--change-set-name preview-changes
- name: Execute Change Set (Manual approval required)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
aws cloudformation execute-change-set \
--stack-name ${{ env.STACK_NAME }} \
--change-set-name preview-changes