Demystifying AWS CloudFormation: Understanding Key Template Sections

Introduction
Welcome to this beginner's guide to AWS CloudFormation! In this article, we'll explore what CloudFormation is, why it's useful, and how to create your first template to deploy an EC2 instance with a security group. By the end, you'll understand the different sections of a CloudFormation template and how they work together to define your infrastructure as code—all with a simple, working example you can try yourself.
What is AWS CloudFormation?
AWS CloudFormation is a service that lets you define and manage AWS infrastructure using code. Instead of manually setting up resources like EC2 instances or S3 buckets through the AWS Management Console, you write a template that describes what you want. CloudFormation then creates, updates, or deletes those resources for you in a predictable way. This approach, called "Infrastructure as Code" (IaC), helps you automate, replicate, and version your infrastructure easily.
Template Formats: JSON vs. YAML
CloudFormation templates can be written in two formats: JSON or YAML. While both work, YAML is more beginner-friendly because it's easier to read and supports comments (unlike JSON). For this tutorial, we'll use YAML to keep things clear and simple.
Sections of a CloudFormation Template
A CloudFormation template can have up to 10 sections, each with a specific role in defining your infrastructure. Only one section is required: Resources. The others are optional but add flexibility and functionality. Let's break them down.
1. Format Version
- Purpose: Specifies the version of the CloudFormation template format.
- Details: Optional but recommended. The value is always
'2010-09-09'
.
Example:
AWSTemplateFormatVersion: '2010-09-09'
2. Description
- Purpose: Provides a short summary of what the template does.
- Details: Optional but useful for clarity.
Example:
Description: A simple template to create an EC2 instance with a security group.
3. Metadata
- Purpose: Adds extra details about the template (e.g., UI hints).
- Details: Optional and advanced, so we'll cover it in a future article.
4. Parameters
- Purpose: Allows users to input custom values, making the template reusable.
- Details: We'll use three parameters: InstanceType, KeyName, and SSHLocation.
Example:
Parameters:
InstanceType:
Type: String
Default: t2.micro
AllowedValues:
- t2.micro
- t2.small
- t2.medium
Description: Enter t2.micro, t2.small, or t2.medium. Default is t2.micro.
KeyName:
Type: AWS::EC2::KeyPair::KeyName
Description: Name of an existing EC2 KeyPair for SSH access.
SSHLocation:
Type: String
Default: 0.0.0.0/0
Description: The IP range that can SSH to the instance (e.g., 203.0.113.0/24).
MinLength: 9
MaxLength: 18
AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
ConstraintDescription: Must be a valid IP CIDR range (x.x.x.x/x).
5. Rules
- Purpose: Validates parameters with conditions.
- Details: Optional and complex, so we'll cover it in a future article.
6. Mappings
- Purpose: Maps keys to values for dynamic selections (e.g., AMI IDs by region).
- Details: We'll map AMI IDs for two regions.
Example:
Mappings:
RegionMap:
us-east-1:
AMI: ami-0c55b159cbfafe1f0
us-west-2:
AMI: ami-0c94855ba95c71c99
7. Conditions
- Purpose: Controls resource creation based on conditions.
- Details: Optional and skipped for simplicity. We'll cover it in a future article.
8. Transform
- Purpose: Used for serverless applications with SAM.
- Details: We'll cover it in a future article.
9. Resources
- Purpose: Defines the AWS resources to create (required).
- Details: We'll create a security group and an EC2 instance.
Example:
Resources:
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH access
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref SSHLocation
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType
KeyName: !Ref KeyName
ImageId: !FindInMap [RegionMap, !Ref AWS::Region, AMI]
SecurityGroupIds:
- !Ref InstanceSecurityGroup
10. Outputs
- Purpose: Exports values from the stack.
- Details: We'll output the instance ID and public IP.
Example:
Outputs:
InstanceId:
Description: The Instance ID
Value: !Ref EC2Instance
PublicIP:
Description: Public IP address of the instance
Value: !GetAtt EC2Instance.PublicIp
Complete Working Template
Here's the full YAML template:
AWSTemplateFormatVersion: '2010-09-09'
Description: A simple template to create an EC2 instance with a security group.
Parameters:
InstanceType:
Type: String
Default: t2.micro
AllowedValues:
- t2.micro
- t2.small
- t2.medium
Description: Enter t2.micro, t2.small, or t2.medium. Default is t2.micro.
KeyName:
Type: AWS::EC2::KeyPair::KeyName
Description: Name of an existing EC2 KeyPair for SSH access.
SSHLocation:
Type: String
Default: 0.0.0.0/0
Description: The IP range that can SSH to the instance (e.g., 203.0.113.0/24).
MinLength: 9
MaxLength: 18
AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
ConstraintDescription: Must be a valid IP CIDR range (x.x.x.x/x).
Mappings:
RegionMap:
us-east-1:
AMI: ami-0c55b159cbfafe1f0
us-west-2:
AMI: ami-0c94855ba95c71c99
Resources:
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH access
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref SSHLocation
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType
KeyName: !Ref KeyName
ImageId: !FindInMap [RegionMap, !Ref AWS::Region, AMI]
SecurityGroupIds:
- !Ref InstanceSecurityGroup
Outputs:
InstanceId:
Description: The Instance ID
Value: !Ref EC2Instance
PublicIP:
Description: Public IP address of the instance
Value: !GetAtt EC2Instance.PublicIp
Notes:
- AMI IDs: These are examples and may be outdated. Check the latest Amazon Linux 2 AMI IDs in your region and update the Mappings section. The recommended method is to use AWS Systems Manager Parameter Store which we will cover in a future article.
- Security: SSHLocation defaults to 0.0.0.0/0 (open to all), which is fine for testing but insecure for production. Use a specific range (e.g., 203.0.13.0/24).
- Assumptions: Assumes a default VPC with public IPs enabled.
How to Use This Template
- Save the Template: Copy the YAML into a file (e.g., ec2-template.yaml).
- Create a Stack:
- Go to CloudFormation in the AWS Console.
- Select Create stack > With new resources.
- Upload ec2-template.yaml.
- Enter parameters:
- InstanceType: e.g., t2.micro.
- KeyName: An existing key pair name.
- SSHLocation: e.g., 0.0.0.0/0 (or your IP range).
- Complete the wizard.
- Check Outputs: After creation, see the instance ID and public IP in the Outputs tab. SSH using the key pair and IP.
ssh -i your-ssh-key.pem ec2-user@your-ec2-public-ip
Conclusion
You've learned the basics of CloudFormation and built a template to deploy an EC2 instance. Experiment further to expand your skills!
Member discussion