4 min read

Demystifying AWS CloudFormation: Understanding Key Template Sections

A Beginner's Guide to AWS CloudFormation - This covers the basics of CloudFormation and includes a complete working template to deploy an EC2 instance with a security group.
Demystifying AWS CloudFormation: Understanding Key Template Sections
Image by 愚木混株 Cdd20 from Pixabay

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

  1. Save the Template: Copy the YAML into a file (e.g., ec2-template.yaml).
  2. 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.
  3. 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!