AWS CloudFormation
AWS CloudFormation is a service provided by Amazon Web Services (AWS) that allows you to define and manage your infrastructure as code.
Key Terms
CloudFormation templates
A CloudFormation template is used to define your AWS resources in a structured text format, either YAML or JSON.
CloudFormation stack
A "stack" is a collection of AWS resources that may be managed as a single unit in AWS CloudFormation.
StackSet
A named collection of stacks that have the same template but are applied to distinct accounts and regions.
Change Set
A Change Set is a list of proposed changes that will be applied to a stack when you run an update. It serves as a preview method, allowing you to review and validate potential modifications before they are implemented in your infrastructure.
You are only charged for the resources you create and the API calls that CloudFormation performs on your behalf.
The Template Study
Let's dive into the structure of an AWS CloudFormation template
The following example shows an AWS CloudFormation YAML template structure and its top-level objects:
AWSTemplateFormatVersion: 'version date' (optional) # version of the CloudFormation template. Only accepted value is '2010-09-09'
Description: 'String' (optional) # a text description of the Cloudformation template
Metadata: 'template metadata' (optional) # objects that provide additional information about the template
Parameters: 'set of parameters' (optional) # a set of inputs used to customize the template
Rules: 'set of rules' (optional) # a set of rules to validate the parameters provided at deployment/update
Mappings: 'set of mappings' (optional) # a mapping of keys and associated values
Conditions: 'set of conditions' (optional) # conditions that control whether certain resources are created
Transform: 'set of transforms' (optional) # for serverless applications
Resources: 'set of resources' (required) # a components of your infrastructure
Hooks: 'set of hooks' (optional) # Used for ECS Blue/Green Deployments
Outputs: 'set of outputs' (optional) # values that are returned whenever you view your stack's properties
Now, Its time for building some CloudFormation Templates and explore various features.
Lets begin the game now
Building Cloud Formation Templates
Simple Templates
Template 1
A Simple CloudFormation Template that creates an S3 Bucket
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyS3Bucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: templateonebucket
- Replace templateonebucket with a unique name for your S3 bucket. S3 bucket names are globally unique across all of AWS, so you may need to come up with a creative and unique name.
- Save this template in a .yaml file and then use the AWS CloudFormation service to deploy it.
Lets Understand the above snippet
Certainly! Let me explain each part of the CloudFormation template:
AWSTemplateFormatVersion: '2010-09-09'
:
This specifies the version of the CloudFormation template format being used. In this case, it's set to the earliest version '2010-09-09'. This version indicates the overall structure and syntax of the template.Resources
:
TheResources
section is where you define the AWS resources you want to create or manage using this CloudFormation template. Resources can include things like EC2 instances, S3 buckets, DynamoDB tables and more.MyS3Bucket
:
This is the logical name of the resource being defined. In this case, it's an S3 bucket, and the logical name isMyS3Bucket
. You'll use this logical name later to refer to this resource in other parts of the template or when interacting with AWS services.Type: 'AWS::S3::Bucket'
:
This line specifies the type of AWS resource you want to create. In this case, you're creating an S3 bucket, so theType
is set toAWS::S3::Bucket
. This tells CloudFormation that you want to create an S3 bucket resource.Properties
:
TheProperties
section is where you provide the specific configuration for the resource you're creating. For an S3 bucket, there are various properties you can set, such asBucketName
,AccessControl
,VersioningConfiguration
etcBucketName: templateonebucket:
This is where you set the properties for the S3 bucket. In this example, you're setting theBucketName
property to templateonebucket.
Replace templateonebucket with a unique name for your S3 bucket. As mentioned before, S3 bucket names must be globally unique across AWS, so make sure to choose a unique name.
Once you have this CloudFormation template ready, you can use the AWS CloudFormation service to deploy it. This will create an S3 bucket with the bucket name specified
Template 2
Create another s3 bucket with versioning enabled
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyS3Bucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: mybucketname
VersioningConfiguration:
Status: Enabled
- Replace mybucketname with a unique name for your S3 bucket. S3 bucket names are globally unique across all of AWS, so you may need to come up with a creative and unique name.
- Save this template in a .yaml file and then use the AWS CloudFormation service to deploy it.
VersioningConfiguration
is a property that sets the versioning configuration for the bucket.
Status
is set to Enabled to enable versioning for the bucket.
Intrinsic functions
Intrinsic functions are AWS CloudFormation built-in functions that you may use within CloudFormation templates to dynamically produce values, apply conditionals, and control resource characteristics.
You can use intrinsic functions in resource properties, outputs, metadata attributes, and update policy attributes.
Lets dive into some commonly used intrinsic functions in CloudFormation
Ref
This function is used to reference a resource declared within the same CloudFormation stack. It returns the value of the specified resource's logical name.
Template 3
A simple S3 bucket with the name of the bucket getting displayed in output tab using Ref
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyS3Bucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: my-unique-bucket-name
Outputs:
BucketNameOutput:
Description: "Name of the S3 bucket"
Value: !Ref MyS3Bucket
- Replace my-unique-bucket-name with a unique name for your S3 bucket. S3 bucket names are globally unique across all of AWS, so you may need to come up with a creative and unique name.
- Save this template in a .yaml file and then use the AWS CloudFormation service to deploy it.
- We define an output named
BucketNameOutput
to display the name of the created S3 bucket. - We use the !Ref function to reference the
MyS3Bucket
resource, which returns the logical name of the resource, in this case,MyS3Bucket
Outputs in CloudFormation provide a way to make important information available after your infrastructure has been deployed. This can include resource identifiers, endpoints, URLs, and more. By defining outputs, you can make your CloudFormation stacks more flexible and interconnected, enabling you to build complex and dynamic infrastructures.
- In Summary, When you deploy this CloudFormation template, it will create an S3 bucket with the specified name, and the output
BucketNameOutput
will display the logical name of the bucket resource (MyS3Bucket).
You can View the output value on the AWS CloudFormation console , in the Outputs tab.
Fn::Join
This function joins values together using a delimiter to create a single string. It's often used to construct resource names or ARNs
Every Fn::Join object requires two parameters,
- a string delimiter
- a list of strings to be joined or a function that returns a list of strings to be joined.
Template 4
A simple S3 bucket with bucket name getting generated using Fn:Join
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyS3Bucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName:
Fn::Join:
- '-'
- - 'my-bucket-prefix'
- Ref: 'AWS::Region'
- 'unique-id'
- Save this template in a .yaml file and then use the AWS CloudFormation service to deploy it.
- Under the Resources section, we define an S3 bucket resource named MyS3Bucket.
We use the
Fn::Join
intrinsic function to dynamically generate the bucket name.As the
Fn::Join
function takes two arguments:
The delimiter to use to join the elements (in this case, a hyphen -)
A list of elements to join together
Inside the list of elements, we include:
- A static string 'my-bucket-prefix'.
- The Ref intrinsic function referencing the AWS region. This will be replaced with the actual AWS region where the stack is being created.
-
Another static string 'unique-id'.
- The resulting bucket name will be something like:
my-bucket-prefix-us-east-2-unique-id
, where us-east-2 being the actual AWS region I use the CloudFormation service
- The resulting bucket name will be something like:
Fn::Sub
The Fn::Sub
intrinsic function in AWS CloudFormation is used for variable substitution in strings. It allows you to create dynamic strings by substituting variables with their corresponding values from resources, parameters, or intrinsic functions
Syntax:
Fn::Sub:
- "string to substitute ${variable}"
- { "variable": value }
Template 5
A simple S3 bucket with a bucket name derived by the value of the Environment variable using Fn::Sub
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyBucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName:
Fn::Sub:
- "my-awesome-bucket-${Environment}"
- { "Environment": "production" }
- Save this template in a .yaml file and then use the AWS CloudFormation service to deploy it.
Under the Resources section, we define an S3 bucket resource named MyBucket.
The BucketName property of the S3 bucket resource uses the
Fn::Sub
intrinsic function to create a dynamic bucket name.The first argument is the string template with a variable ${Environment} that needs to be replaced.
The second argument to
Fn::Sub
is a JSON object that specifies the values of the variables used in the string template.In this case,
{"Environment": "production"}
means that${Environment}
will be replaced with the value "production".After deployment, the bucket name will be
my-awesome-bucket-production
.
Fn::GetAtt
The Fn::GetAtt
intrinsic function returns the value of an attribute from a resource in the template.
Syntax
!GetAtt logicalNameOfResource.attributeName
Template 6
Create an S3 bucket resource, along with a few outputs being generated using Fn::GetAtt
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: my-unique-bucket-name
Outputs:
BucketName:
Value: !Ref MyS3Bucket
BucketArn:
Value: !GetAtt MyS3Bucket.Arn
BucketDomainName:
Value: !GetAtt MyS3Bucket.DomainName
- Replace my-unique-bucket-name with a unique name for your S3 bucket. S3 bucket names are globally unique across all of AWS, so you may need to come up with a creative and unique name.
- Save this template in a .yaml file and then use the AWS CloudFormation service to deploy it.
-
MyS3Bucket
is defined as an S3 bucket resource with a specified unique bucket name. - The BucketName output uses
!Ref
to reference the bucket resource, effectively providing the name of the bucket. - The BucketArn output uses
!GetAtt
to retrieve the Amazon Resource Name (ARN) of the bucket resource. - The BucketDomainName output uses
!GetAtt
to retrieve the domain name of the bucket.
You can View the output values on the AWS CloudFormation console , in the Outputs tab.
Fn::Select
The
Fn::Select
intrinsic function in AWS CloudFormation is used to select an element from a list based on its index. It's commonly used when you have a list of items and you want to retrieve a specific item from that list.
Syntax:
Fn::Select: [ index, listOfItems ]
-
index
: The zero-based index of the item you want to select from the list. -
listOfItems
: The list of items from which you want to select an item.
The
!Select
function allows you to dynamically select values based on their indices, enabling you to parameterize and customize your resource properties within the template.
Template 7
Creates an AWS S3 bucket resource named MyBucket with a specific bucket name generated using Fn::Select
function
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Select [1, ["my-bucket-1", "my-bucket-2", "my-bucket-3"]]
- Replace my-bucket-1,my-bucket-2,my-bucket-3 with a unique name for your S3 bucket. S3 bucket names are globally unique across all of AWS, so you may need to come up with a creative and unique name.
- Save this template in a .yaml file and then use the AWS CloudFormation service to deploy it.
AWSTemplateFormatVersion: '2010-09-09'
: This indicates the version of the CloudFormation template format being used. In this case, the template is using the 2010-09-09 version.Resources
: This section defines the AWS resources that you want to create or manage using the CloudFormation template.MyBucket:
This is the logical ID of the AWS S3 bucket resource being created.Type: AWS::S3::Bucket:
This specifies the resource type as an S3 bucket. It indicates that CloudFormation should create an S3 bucket resource.
Properties
: This section contains the properties specific to the resource being created. In this case, it's the properties of the S3 bucket resource.
BucketName
: This property specifies the name of the S3 bucket. The value is retrieved using the !Select intrinsic function.
-!Select [1, ["my-bucket-1", "my-bucket-2", "my-bucket-3"]]
: This uses the !Select
function to select an element from a list.
- The arguments are as follows:
-
1
: This is the index of the element to be selected. Since indices are zero-based, 1 corresponds to the second element in the list. -
["my-bucket-1", "my-bucket-2", "my-bucket-3"
]: This is the list of bucket names. The second element in this list is "my-bucket-2
".
-
When this CloudFormation template is executed, it will create an S3 bucket resource named MyBucket with the bucket name "my-bucket-2".
Fn::Split
The Fn::Split
intrinsic function in AWS CloudFormation is used to split a string into a list of substrings based on a specified delimiter.
Syntax:
Fn::Split: [ delimiter, sourceString ]
Template 8
Add a tag for the S3 bucket resource MyBucket
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyS3Bucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: my-bucket-name
Tags:
- Key: Name
Value:
'Fn::Select':
- 1
- 'Fn::Split':
- '-'
- my-bucket-name
- Replace my-bucket-name with a unique name for your S3 bucket. S3 bucket names are globally unique across all of AWS, so you may need to come up with a creative and unique name.
- Save this template in a .yaml file and then use the AWS CloudFormation service to deploy it.
AWSTemplateFormatVersion: '2010-09-09
': This line specifies the version of the CloudFormation template format being used. In this case, it's the 2010-09-09 version.Resources:
This section defines the AWS resources that you want to create or manage using the CloudFormation template.MyBucket:
This is the logical ID of the AWS S3 bucket resource being created.Type: AWS::S3::Bucket:
This line indicates that the resource type being created is an S3 bucket. The CloudFormation template will create an S3 bucket resource.Properties
: This section contains the properties specific to the S3 bucket resource.BucketName: my-bucket-name:
This sets the name of the S3 bucket to "my-bucket-name".Tags
: This property allows you to assign tags to the S3 bucket.
Tags are key-value pairs used to label and categorize resources for better organization and management.
-Key: Name:
This defines a tag with the key "Name" The key represents the label or category of the tag.
Value:
The value of the tag is determined using theFn::Select
andFn::Split
intrinsic functions.Fn::Split
: This function is used to split the string "my-bucket-name
" into a list of substrings using the "-
" delimiter. The result is a list of substrings:["my", "bucket", "name"]
.Fn::Select:
This function is used to select an element from the list of substrings. In this case, the second element ("bucket") is selected using an index of 1.
As a result, the S3 bucket resource MyBucket will have a tag with the key "Name" and the value "bucket."
You can view the tags on the properties tab of your bucket in S3 Console
The dynamic tagging is achieved by using
Fn::Split
to manipulate the string "my-bucket-name" andFn::Select
to select the desired substring for the tag value.
Fn::ForEach
The Fn::ForEach
intrinsic function takes a collection and a fragment, and applies the items in the collection to the identifier in the provided fragment
Syntax:
Fn::ForEach::UniqueLoopName:
- Identifier
- - Value1 # Collection
- Value2
- OutputKey:
OutputValue
-
UniqueLoopName
A name for this loop. -
Identifier
The identifier you want to replace in the OutputKey and OutputValue parameters that represent the template fragment that is replicated Collection
The collection of values to iterate over. This can be an array in this parameter, or it can be a Ref to a CommaDelimitedList.OutputKey
The key in the transformed template. ${Identifier} must be included within the OutputKey parameter.OutputValue
The value that is replicated in the transformed template for each item in the Collection parameter
You must use the
AWS::LanguageExtensions
transform to use the Fn::ForEach intrinsic function.
Template 9
Using the Fn::ForEach
intrinsic function, create S3 buckets with versioning enabled, by looping through a list of bucket names and building S3 buckets with those names
AWSTemplateFormatVersion: 2010-09-09
Transform: 'AWS::LanguageExtensions'
Resources:
Fn::ForEach::Buckets:
- BucketName
- - my-unique-bucket-name-one
- my-unique-bucket-name-two
- ${BucketName}:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
VersioningConfiguration:
Status: Enabled
- Replace my-unique-bucket-name-one and my-unique-bucket-name-two with a unique names for your S3 buckets. S3 bucket names are globally unique across all of AWS, so you may need to come up with a creative and unique name.
- Save this template in a .yaml file and then use the AWS CloudFormation service to deploy it.
Transform:
AWS::LanguageExtensions:
This indicates that you're using a custom CloudFormation transform namedAWS::LanguageExtensions
. This transform extends the template syntax with additional capabilities, and in this case, it's used to enable the Fn::ForEach functionality.Resources
: This is where you define your CloudFormation resources.-
Fn::ForEach::Buckets:
This is the resource defined with theFn::ForEach
intrinsic function. It iterates over the list of bucket names and creates S3 bucket resources for each name.-
BucketName:
This is the logical ID for the iteration. This is the parameter for the iteration, representing the list of bucket names that you want to iterate over.
-
my-unique-bucket-name-one
and my-unique-bucket-name-two
: These are the actual bucket names specified in the list. Each name represents an iteration.
${BucketName}
: This is the dynamic reference to the iteration variable. It's used to create the logical IDs for the S3 buckets.
Type: AWS::S3::Bucket:
This specifies that the resource type is an S3 bucket.
BucketName: !Ref BucketName:
This sets the name of the S3 bucket based on the value of the BucketName parameter.
VersioningConfiguration:
This defines the bucket's versioning configuration.
Status: Enabled:
This enables versioning for the S3 bucket.
- With
Fn::ForEach
, you can replicate parts of your templates with minimal lines of code. - You can use
Fn::ForEach
to simplify your template layout and make it easier and faster for you and your peers to review your code. -
Fn::ForEach
helps reduce human errors such as updating wrong properties or missing out on updating multiple target properties in your template.
Fn::FindInMap
The Fn::FindInMap intrinsic function is used in AWS CloudFormation templates to retrieve a value from a predefined mapping. This function is particularly useful when you want to parameterize or customize resources based on certain conditions, such as regions or environments.
A Mappings section is a top level section of a CloudFormation template. It is used to define maps, their keys and values which can be then referenced in your template.
When you include the AWS::LanguageExtensions
transform in an AWS CloudFormation template, you can define the fields of Fn::FindInMap
using intrinsic functions. so that, If no mapping is detected, you can utilize a new optional field to return a default value.
Template 10
Create S3 buckets with names based on AWS regions, while also providing a default bucket name in case a specific region mapping is not defined. using !FindInMap
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::LanguageExtensions'
Mappings:
S3BucketNames:
us-east-1:
BucketName: my-bucket-us-east-1
us-west-1:
BucketName: my-bucket-us-west-1
Resources:
MyS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName:
Fn::FindInMap:
- S3BucketNames
- !Ref AWS::Region
- BucketName
- DefaultValue: my-default-bucket
Replace my-default-bucket, my-bucket-us-east-1 and my-bucket-us-west-1 with a unique names for your S3 buckets.
S3 bucket names are globally unique across all of AWS
so you may need to come up with a creative and unique name.Save this template in a .yaml file and then use the AWS CloudFormation service to deploy it.
Try deploying the template in
us-east-1,
us-west-
1 andus-west-2
regions.
The above CloudFormation template showcases the usage of the AWS::LanguageExtensions
transform along with the Fn::FindInMap
function and a default value extension.
Transform:
'AWS::LanguageExtensions'
: This line indicates that the CloudFormation template is using the AWS::LanguageExtensions transform, which allows the use of language extensions like default values for intrinsic functions.Mappings
: Defines a mapping named S3BucketNames, which associates different S3 bucket names with different AWS regions.S3BucketNames
: This key under the Mappings section contains the mapping for S3 bucket names based on regions.us-east-1
andus-west-1
: These region keys under the S3BucketNames mapping correspond to different AWS regions. For each region, there's a sub-keyBucketName
that holds the corresponding bucket name.Resources:
Specifies the AWS resources created as part of this CloudFormation stack.MyS3Bucket:
Defines an S3 bucket resource.Type: AWS::S3::Bucket:
Indicates that this resource represents an S3 bucket.Properties: Sets the properties for the
MyS3Bucket
resource.
BucketName
: This property designates the bucket name of the S3 bucket.
- The
Fn::FindInMap
function is used to dynamically retrieve the bucket name based on the AWS region of the stack (!Ref AWS::Region)
.
There is a twist here,
DefaultValue: my-default-bucket:
This extension, facilitated by theAWS::LanguageExtensions
transform, allows specification of a fallback value if the specific mapping key isn't found.
In this scenario, if the stack is deployed in a region not included in the S3BucketNames
mapping, such as a region other than us-east-1
or us-west-1
, the bucket name will default to
my-default-bucket
.
If you try to deploy the CloudFormation Template in regions say
US West (Oregon), us-west-2 (which is not mentioned in mapping-S3BucketNames) The name of the bucket would be my-default-bucket
If you try to deploy the cloudformation Template in regions say
US East (N. Virginia) us-east-1 The name of the bucket would be my-bucket-us-east-1
If you try to deploy the cloudformation Template in regions say
US West (N. California) us-west-1 The name of the bucket would be my-bucket-us-west-1
Create CloudFormation stacks using the AWS Management Console
The following YouTube video illustrate how you can create a CloudFormation stack using the console.
Deleting a CloudFormation stack will remove all resources created by that stack. So once you have finished learning, You can delete the stacks
Top comments (0)