Working with CloudFormation Templates

Before provisioning and configuring any AWS cloud resources, we must first understand and learn to work with CloudFormation templates. A CloudFomration template contains all the key instructions to deploy an AWS infrastructure’s resources using CloudFormation.

In this lesson, we’ll explore the basic aspects of a CloudFormation template and how to create a new one or reuse and adapt an existing one according to our needs.

Anatomy of a CloudFormation template

CloudFormation uses templates to define the AWS resources that we want to create and configure. Templates are written in a declarative language, with supported JSON and YAML. All resources that we want to provision and the order in which we want to provision them are essentially declared in a CloudFormation template.

Templates can be version-controlled, just like any other code, making it easier to roll back any changes in case of deployment failure without compromising the entire infrastructure.

Press + to interact

The CloudFormation template has several aspects, and each supported AWS resource has its own syntax and parameters that we need to follow. To keep things simple, we’ll only explore the basic anatomy of a CloudFormation template, which is enough to start working with templates for the commonly used general CloudFormation stacks. The following illustration provides a breakdown of the different sections in a CloudFormation template:

Press + to interact
Breakdown of the CloudFormation template
Breakdown of the CloudFormation template

Here’s the basic skeleton code format for a CloudFormation template in JSON and YAML that covers the first basic layer of the template:

AWSTemplateFormatVersion: "2010-09-09"
# Adding a Comment in a YAML template
Description: >
This is a sample description
in a YAML template that has multiline value
support.
Metadata:
<Template Metadata Formatted as List of YAML Objects>
Parameters:
<Set of Parameters Formatted as List of YAML Objects>
Rules:
<Set of Rules Formatted as List of YAML Objects>
Mappings:
<Set of Mappings Formatted as List of YAML Objects>
Conditions:
<Set of Conditions Formatted as List of YAML Objects>
Transform:
<Set of Transform Formatted as List of YAML Objects>
Resources:
<Set of Resources Formatted as List of YAML Objects>
Outputs:
<Set of Outputs Formatted as List of YAML Objects>
CloudFormation template skeleton code

Note: You can choose either JSON or YAML formats when working with CloudFormation templates. However, due to different syntaxes, the YAML format offers a few more features than the JSON format. For example, in the YAML format, you can have comments and multiline support in some sections, whereas in the JSON format, such actions are not supported.

Here’s a brief explanation of the most common sections that we can see in both the JSON and YAML CloudFormation templates:

AWSTemplateFormatVersion

In this section, we specify the version of the template format we want to use, which is a date in the YYYY-MM-DD format. We can only provide a string literal as the template format and version.

Warning: As of this writing, the latest template format version is “2010-09-09,” which is the only one accepted as a valid value by CloudFormation, and using any other version value will result in an error from CloudFormation in reading the stack template.

Description

In this section, we can add information and comments to describe the CloudFormation template and the stack it will provision. We can only provide a string literal as the description, which must be 1024 bytes in length at most.

Metadata

In this section, we specify a single or list of YAML/JSON objects that provide the metadata-based information about the template. We can also use it to define configuration settings here, which are then retrieved using CloudFormation features, like CloudFormation scripts.

Parameters

In this section, we specify a single or list of YAML/JSON objects representing parameters that allow us to input custom values into the CloudFormation template when creating or updating a stack.

It can be beneficial to have parameters within our template, especially when updating a stack, as we only need to input a new parameter value once that can be referenced in the Resources and Outputs sections and avoid changing the value at multiple instances in the template.

Here’s an example template code snippet for a parameter defining the type of an EC2 instance:

Parameters:
EC2InstanceType:
Description: "EC2 instance type"
Type: String
Default: 't2.micro'

Note: There are some constraints with using CloudFormation template parameters in that we must declare and reference parameters within the CloudFormation template. We can also have a maximum of 200 parameters in a CloudFormation template.

Resources

In this section, we specify a single or list of YAML/JSON objects representing resources that we want to provision in the CloudFormation stack. This section supports the following fields:

  • Logical ID: This field is a unique alphanumeric ID that references the corresponding AWS resource in a CloudFormation stack and within other sections in the template itself. The logical ID is different from the physical ID of an AWS resource, which is the actual ID of the resource.

  • Type: This field represents the type of AWS resource that we want to create. The resource type field has the following format: service-provider::service-name::resource-type. For example, if we want to create a Lambda function, we’ll write AWS::Lambda::Function as the resource type.

  • Properties: This field is where we can specify any additional properties for the AWS resource.

Here’s an example template code snippet for provisioning the EC2 instance and security group resources. Note that we also utilized the EC2InstanceType parameter from the parameter example.

Resources:
SecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: "Internal Security group for EC2 instance"
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0e731c8a588258d0d
InstanceType: { "Ref" : "EC2InstanceType" }
SecurityGroupIds:
- !GetAtt SecurityGroup.GroupId

Note: The Resources section is a required section in a CloudFormation template and must be provided. All other template sections are optional and can be omitted from the template.

Outputs

In this section, we specify a single or list of YAML/JSON objects representing outputs related to the stack that we can return via API-based stack calls or the AWS CloudFormation management console.

Here’s an example template code snippet for the output defining the public DNS link of the EC2 instance:

Outputs:
InstanceEndpoint:
Description: The DNS name of Instance
Value: !Sub "http://${Instance.PublicDnsName}"
Export:
Name: InstanceEndpoint

Now that we’ve explored the basic anatomy of a CloudFormation template, we can proceed to understand some of the basic features that CloudFormation offers to work with templates.

Intrinsic functions

Intrinsic functions are built-in functions provided by CloudFormation, and we can use these in our template to assign resource attributes with unavailable values until runtime. Here’s a brief description of some of the commonly used intrinsic functions in CloudFormation templates:

  • !Base64 | Fn::Base64: This intrinsic function returns the Base64 representation of the input string.

  • !FindInMap | Fn::FindInMap: This intrinsic function returns the values corresponding to the keys defined in the Mappings section.

  • !GetAtt | Fn::GetAtt: This intrinsic function returns the value of an attribute from a resource in the template.

  • !Ref|Ref: This intrinsic function returns the value of the specified parameter or resource.

  • !Sub | Fn::Sub: This intrinsic function is used to substitute variables in an input string with values that you specify.

Pseudo parameters

Pseudo parameters are pre-defined parameters provided by CloudFormation that we don’t essentially need to declare in the template. We can retrieve the pseudo parameter using the Ref Intrinsic function. Here’s a brief description of some of the commonly used pseudo parameters in CloudFormation templates:

  • AWS::AccountId: This pseudo parameter returns the ID of the AWS account in which the stack is currently being built.

  • AWS::Region: This pseudo parameter returns the region value in which the stack is currently being built.

  • AWS::StackId: This pseudo parameter returns the ID of the stack that is currently being built.

  • AWS::StackName: This pseudo parameter returns the name of the stack that is currently being built.


This lesson taught us about the AWS CloudFormation templates and understand the core structure and functions of a CloudFormation template.

Get hands-on with 1300+ tech skills courses.