Welcome to our introduction to best practices for using AWS CloudFormation! In this text, we will be covering guidelines for utilizing CloudFormation effectively in order to manage your infrastructure resources on AWS. We will discuss the use of JSON and YAML for writing CloudFormation templates, as well as the benefits of using CloudFormation parameters, conditionals, mappings, and functions. We will also cover the concept of nested stacks and how they can be used to organize and reuse common templates. Additionally, we will delve into the importance of stack policies and change sets in controlling and testing changes to your stack, and we will discuss the usefulness of stack events and drift detection in tracking and maintaining the configurations of your resources. By the end of this text, you should have a solid understanding of how to effectively use CloudFormation to manage your infrastructure on AWS.
Use JSON or YAML for writing CloudFormation templates. These formats are easier to read and maintain than XML, and they have built-in support for comments.
--- AWSTemplateFormatVersion: '2010-09-09' Description: Creates an Amazon S3 bucket Resources: MyBucket: Type: AWS::S3::Bucket Outputs: BucketName: Value: !Ref MyBucket
In this example, the AWSTemplateFormatVersion
indicates the version of the CloudFormation template format being used. The Description
provides a brief summary of what the template does. The Resources
section defines the resources that will be created, in this case an S3 bucket. The Outputs
section specifies values that will be output when the stack is created, such as the name of the S3 bucket.
In YAML, comments are indicated by a #
symbol and can be added anywhere on a line. For example, you could add a comment to the template like this:
# This is a comment
Use CloudFormation parameters to make your templates more flexible and easier to reuse. Parameters allow you to specify values that can be customized when you create or update a stack.
--- AWSTemplateFormatVersion: '2010-09-09' Description: Creates an Amazon S3 bucket with a customizable bucket name Parameters: BucketName: Type: String Description: The name of the S3 bucket to create Resources: MyBucket: Type: AWS::S3::Bucket Properties: BucketName: !Ref BucketName Outputs: BucketName: Value: !Ref MyBucket
In this example, the Parameters
section defines a parameter called BucketName
of type String
. When you create or update the stack, you can specify the value for the BucketName
parameter. This value will be used to set the BucketName
property of the S3 bucket resource when the stack is created.
Using parameters in your CloudFormation templates allows you to customize the values of your resources at stack creation or update time, making your templates more flexible and easier to reuse.
This page provides detailed information about using parameters in CloudFormation templates, including how to define and use parameters, the available parameter types, and best practices for using parameters.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html
Use CloudFormation conditionals to customize your templates based on input parameters or other runtime values. Conditionals allow you to specify different resources or property values depending on the value of an input or the result of an evaluation.
--- AWSTemplateFormatVersion: '2010-09-09' Description: Creates an Amazon EC2 instance with a customizable instance type Parameters: InstanceType: Type: String Description: The type of the EC2 instance to create Default: t2.micro Resources: MyInstance: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType # Use a conditional to customize the AMI based on the instance type ImageId: !If - IsT2Micro - ami-123456 - !If - IsT2Small - ami-234567 - ami-345678 Conditions: IsT2Micro: !Equals [!Ref InstanceType, t2.micro] IsT2Small: !Equals [!Ref InstanceType, t2.small]
In this example, the Parameters section defines a parameter called InstanceType of type String. The Resources section defines an EC2 instance with a Properties block that includes an InstanceType property set to the value of the InstanceType parameter. The ImageId property is set using a conditional that checks the value of the InstanceType parameter and sets the ImageId property to a different AMI ID depending on the value.
The Conditions section defines two conditions, IsT2Micro and IsT2Small, that are used in the conditional expression to check the value of the InstanceType parameter.
Using conditionals in your CloudFormation templates allows you to customize the properties of your resources based on input parameters or other runtime values, which can make your templates more flexible and powerful.
This page provides detailed information about using conditionals in CloudFormation templates, including how to define and use conditions, the available comparison and logical operators, and examples of using conditionals.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html
Use CloudFormation mappings to specify values that depend on the region or availability zone in which the stack is being created. Mappings allow you to specify different values for different regions or availability zones.
Example uses a mapping to specify the Amazon Linux AMI ID for different regions:
--- AWSTemplateFormatVersion: '2010-09-09' Description: Creates an Amazon EC2 instance using the Amazon Linux AMI for the current region Resources: MyInstance: Type: AWS::EC2::Instance Properties: ImageId: !FindInMap - RegionMap - !Ref 'AWS::Region' - AMI Mappings: RegionMap: us-east-1: AMI: ami-123456 us-west-2: AMI: ami-234567 eu-west-1: AMI: ami-345678
In this example, the Mappings
section defines a mapping called RegionMap
that includes the AMI ID for the Amazon Linux AMI in different regions. The Resources
section defines an EC2 instance with an ImageId
property set using the FindInMap
function. The FindInMap
function takes the mapping name, the current region, and the key for the desired value, and returns the corresponding value from the mapping.
Using mappings in your CloudFormation templates allows you to specify values that depend on the region or availability zone in which the stack is being created, making your templates more flexible and adaptable to different environments.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html
Use CloudFormation functions to simplify your templates and make them more powerful. Functions allow you to perform operations on template variables, such as calculating the size of an Amazon Elastic Block Store (EBS) volume or generating a unique identifier.
Example that uses functions to calculate the size of an Amazon EBS volume and generate a unique identifier:
--- AWSTemplateFormatVersion: '2010-09-09' Description: Creates an Amazon EBS volume with a customizable size and a unique identifier Parameters: VolumeSize: Type: Number Description: The size of the EBS volume in GB Default: 100 Resources: MyVolume: Type: AWS::EC2::Volume Properties: Size: !Sub ${VolumeSize} # Use the UniqueId function to generate a unique identifier VolumeId: !Sub ${AWS::Region}-${AWS::StackName}-${AWS::AccountId}-${AWS::StackId}-${AWS::ResourceName}-${AWS::UniqueId} Outputs: VolumeId: Value: !Ref MyVolume
In this example, the Parameters section defines a parameter called VolumeSize of type Number. The Resources section defines an EBS volume with a Size property set to the value of the VolumeSize parameter using the Sub function. The Sub function allows you to substitute variables in a string with their corresponding values.
The VolumeId property is set using the Sub function and several CloudFormation intrinsic functions, such as AWS::Region, AWS::StackName, and AWS::UniqueId. These functions provide information about the current stack and resources, such as the region the stack is in, the name of the stack, and a unique identifier.
Using functions in your CloudFormation templates allows you to perform operations on template variables and make your templates more powerful and flexible.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html
Use CloudFormation nested stacks to organize and reuse common templates. Nested stacks allow you to use a stack as a resource in another stack, which can be useful for creating reusable templates or dividing a large stack into smaller, more manageable pieces.
Example that uses a nested stack to create an Amazon VPC and subnets:
--- AWSTemplateFormatVersion: '2010-09-09' Description: Creates an Amazon VPC with customizable CIDR range and number of subnets Parameters: VpcCidr: Type: String Description: The CIDR range of the VPC Default: 10.0.0.0/16 NumSubnets: Type: Number Description: The number of subnets to create Default: 2 Resources: MyVpc: Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://s3.amazonaws.com/my-bucket/vpc.yml Parameters: VpcCidr: !Ref VpcCidr NumSubnets: !Ref NumSubnets Outputs: VpcId: Value: !GetAtt [MyVpc, Outputs.VpcId]
In this example, the Resources
section defines a nested stack called MyVpc
using the AWS::CloudFormation::Stack
resource type. The TemplateURL
property specifies the URL of the template for the nested stack, and the Parameters
property passes the values of the VpcCidr
and NumSubnets
parameters to the nested stack.
The Outputs
section includes an output value for the VpcId
of the nested stack, which is retrieved using the GetAtt
function and the Outputs.VpcId
output of the nested stack.
Using nested stacks in your CloudFormation templates allows you to organize and reuse common templates, and divide large stacks into smaller, more manageable pieces.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/working-with-stacks-nested.html
Use CloudFormation stack policies to control who can make changes to your stack and what types of changes are allowed. Stack policies allow you to specify which actions are allowed or denied for specific users or IAM groups.
Example that uses a stack policy to control who can make changes to the stack:
--- AWSTemplateFormatVersion: '2010-09-09' Description: Creates an Amazon VPC with customizable CIDR range and number of subnets Resources: MyVpc: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 # Use the StackPolicy property to specify a stack policy StackPolicy: # Allow updates to resources in the MyVpc resource Allow: - Update: '*' # Deny updates to the MyVpc resource Deny: - Update: - !Ref MyVpc
In this example, the StackPolicy property is used to specify a stack policy for the stack. The Allow and Deny properties specify which actions are allowed or denied for specific resources or resource types.
In this case, the policy allows updates to all resources in the stack except for the MyVpc resource, which is denied updates. This policy would prevent users from accidentally updating the MyVpc resource, which could cause disruptions to any resources or services that depend on it.
Using stack policies in your CloudFormation templates allows you to control who can make changes to your stack and what types of changes are allowed, helping to ensure the stability and security of your stack.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html
Use CloudFormation change sets to preview and test changes to your stack before applying them. Change sets allow you to see what changes will be made to your stack and whether they will succeed or fail before actually making the changes.
Example that uses a change set to preview and test changes to a stack:
--- AWSTemplateFormatVersion: '2010-09-09' Description: Creates an Amazon VPC with customizable CIDR range and number of subnets Resources: MyVpc: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 # Use the AWS::CloudFormation::ChangeSet resource to create a change set Resources: MyChangeSet: Type: AWS::CloudFormation::ChangeSet Properties: # Specify the stack to which the change set will be applied StackName: !Ref AWS::StackName # Specify the template that will be used to create the change set TemplateURL: https://s3.amazonaws.com/my-bucket/vpc.yml # Specify the changes that will be made by the change set ChangeSetName: MyChangeSet ChangeSetType: UPDATE Parameters: - ParameterKey: VpcCidr ParameterValue: 10.0.0.0/16 # Use the AWS::CloudFormation::WaitCondition resource to wait for the change set to be created Resources: MyWaitCondition: Type: AWS::CloudFormation::WaitCondition Properties: Handle: !GetAtt [MyChangeSet, Outputs.ChangeSetId] Timeout: PT5M
In this example, the AWS::CloudFormation::ChangeSet
resource is used to create a change set for the stack. The StackName
property specifies the stack to which the change set will be applied, and the TemplateURL
property specifies the template that will be used to create the change set.
The ChangeSetName
property specifies the name of the change set, and the ChangeSetType
property specifies the type of changes that will be made by the change set. In this case, the change set will update the stack using the specified template.
The AWS::CloudFormation::WaitCondition
resource is used to wait for the change set to be created before continuing with the stack creation process. The Handle
property specifies the output value of the ChangeSetId
from the MyChangeSet
resource, and the Timeout
property specifies the time to wait for the change set to be created before timing out.
Using change sets in your CloudFormation templates allows you to preview and test changes to your stack before actually applying them. This can help you to avoid unintended consequences and ensure that your stack updates are successful.
For more information on using change sets in CloudFormation templates, you can refer to the AWS documentation:
Use CloudFormation stack events to track changes to your stack and understand what happened during stack updates. Stack events provide a record of all changes made to the stack, including resource creations, updates, and deletions.
Example that uses stack events to track changes to a stack:
--- AWSTemplateFormatVersion: '2010-09-09' Description: Creates an Amazon VPC with customizable CIDR range and number of subnets Resources: MyVpc: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 # Use the AWS::CloudFormation::WaitCondition resource to wait for stack events Resources: MyWaitCondition: Type: AWS::CloudFormation::WaitCondition Properties: # Specify the stack for which to wait for events StackName: !Ref AWS::StackName # Wait for the CREATE_IN_PROGRESS and CREATE_FAILED stack events LogicalResourceIds: - !Ref MyWaitCondition # Wait for stack events for up to 10 minutes Timeout: PT10M
In this example, the AWS::CloudFormation::WaitCondition
resource is used to wait for stack events to occur before continuing with the stack creation process. The StackName
property specifies the stack for which to wait for events, and the LogicalResourceIds
property specifies the resource IDs for which to wait for events.
The Timeout
property specifies the time to wait for stack events before timing out. In this case, the template will wait for the CREATE_IN_PROGRESS
and CREATE_FAILED
stack events to occur before continuing.
Using stack events in your CloudFormation templates allows you to track changes to your stack and understand what happened during stack updates. This can help you to troubleshoot issues and ensure that your stack updates are successful.
For more information on using stack events in CloudFormation templates, you can refer to the AWS documentation:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-wait-condition.html
Use CloudFormation drift detection to identify resources in your stack that have drifted from their expected configuration. Drift detection allows you to detect and fix differences between the expected and actual stack resource configurations.
Example that uses drift detection to identify resources that have drifted from their expected configuration:
--- AWSTemplateFormatVersion: '2010-09-09' Description: Creates an Amazon VPC with customizable CIDR range and number of subnets Resources: MyVpc: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsHostnames: true EnableDnsSupport: true InstanceTenancy: default # Use the AWS::CloudFormation::Stack resource to enable drift detection Resources: MyStack: Type: AWS::CloudFormation::Stack Properties: # Enable drift detection for the MyVpc resource DriftDetection: EnableDriftDetection: true StackResourceDriftStatus: MODIFIED # Specify the stack for which to enable drift detection StackName: !Ref AWS::StackName
In this example, the AWS::CloudFormation::Stack
resource is used to enable drift detection for a stack. The DriftDetection
property includes the EnableDriftDetection
property, which is set to true
to enable drift detection for the stack, and the StackResourceDriftStatus
property, which specifies the drift status for stack resources.
In this case, drift detection is enabled for the MyVpc
resource, and the drift status is set to MODIFIED
, indicating that the resource has drifted from its expected configuration.
Using drift detection in your CloudFormation templates allows you to identify resources that have drifted from their expected configuration and take corrective action to fix any differences. This can help you to ensure that your stack resources are always in the desired state.
For more information on using drift detection in CloudFormation templates, you can refer to the AWS documentation:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/drift-detection.html