AWS Cloudformation Template
The bottom line of infrastructure deployment with automation in today's cloud-centric environment is scalability, consistency, and efficiency. AWS CloudFormation provides you with a simple text file that defines what AWS resources you want to create and configure. This enables you to create, update, and manage any resource, such as EC2 instances, S3 buckets, and more, with one single and automated process.
In this article, you will go through the steps in creating an AWS CloudFormation stack that will deploy an EC2 instance with an S3 bucket, we will go through how to define resources in a CloudFormation template, how to initiate the creation of a stack, and how common errors are being debugged using CloudFormation. By the end of this, you should have a basic level of understanding of how to use CloudFormation in managing the deployment automation of your AWS infrastructure.
Primary Terminologies
- CloudFormation Template: In simple words, this is a text file in JSON or YAML format that defines AWS resources and their configurations. This template describes what to create: the EC2 instance, Databases, or S3 bucket.
- Stack: A collection of AWS resources that you can manage as a single unit, when you create a stack AWS CloudFormation provisions the specified resources together.
- Parameters: These provide input to customize the stack while creating or updating a stack. This would be without actually touching the template. Parameters make templates reusable and flexible.
- Outputs: Values that you return back after the creation or update of the stack. You can use outputs to fetch information such as resource IDs or URLs which your stack has created.
- Resources: AWS resources and components defined in the template, such as EC2 instances, RDS databases, S3 buckets, etc. Each resource will be provisioned based on the specification set forth by a given template.
- Mappings: Static values that can be indexed into several places within the template. Mappings are really helpful for use cases like region-based configurations where you may have to define multiple AMIs for each region.
Step-by-Step Process for Creating AWS CloudFormation Template
Step 1: Define Resources
- Start by defining the essential AWS resources you need in your CloudFormation template. Each resource must have a unique logical ID, type, and properties. For example, an EC2 instance would look like this in YAML:
Resources:
MyEC2Instance:
Type: "AWS::EC2::Instance"
Properties:
InstanceType: "t3.micro"
KeyName: "my-key"
ImageId: "ami-0abcdef1234567890"

Step 2: Add Parameters
- Next, add parameters to make your template more dynamic. For example, allowing users to choose the instance type during stack creation:
Parameters:
InstanceTypeParam:
Type: String
Default: t3.micro
AllowedValues:
- t3micro
- t3.small
- t3.medium

Step 3: Add Mappings
Mappings allow you to create static variables that can be referenced throughout your template. A common use case is for region-specific values like AMIs.
Mappings:
RegionMap:
eu-north-1:
"AMI": "ami-0abcdef1234567890"
eu-north-2:
"AMI": "ami-0fedcba9876543210"
ami-0244e31dc33c47ac0

Then, you can use the mapping to dynamically select the AMI based on the region:
Resources:
MyEC2Instance:
Type: "AWS::EC2::Instance"
Properties:
InstanceType: !Ref InstanceTypeParam
KeyName: !Ref KeyNameParam
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", "AMI"]

Step 4: Add Conditions
Conditions are useful when you want to create resources only under specific circumstances, such as when a parameter is set to a certain value.
For example, you might only create a specific resource if the instance type is t3.medium:
Conditions:
CreateMediumInstance: !Equals [!Ref InstanceTypeParam, "t3.medium"]

You can then associate this condition with a resource:
Resources:
MyEC2Instance:
Type: "AWS::EC2::Instance"
Properties:
InstanceType: !Ref InstanceTypeParam
KeyName: !Ref KeyNameParam
ImageId: "ami-0abcdef1234567890"
Condition: CreateMediumInstance

Step 5: Add Outputs
- If you want to access certain data post-deployment (like the public IP of an EC2 instance), add outputs:
Outputs:
InstancePublicIP:
Description: "Public IP address of the EC2 instance"
Value: !GetAtt MyEC2Instance.PublicIp

- Here's a basic template example that provisions an EC2 instance and an S3 bucket:
AWSTemplateFormatVersion: "2010-09-09"
Description: "A CloudFormation template to create an EC2 instance and an S3 bucket, with Mappings, Conditions, and Outputs."
Parameters:
InstanceTypeParam:
Type: String
Description: "The EC2 instance type"
Default: t3.micro
AllowedValues:
- t3.micro
- t3.small
- t3.medium
ConstraintDescription: "Must be a valid EC2 instance type."
KeyNameParam:
Type: AWS::EC2::KeyPair::KeyName
Description: "The name of an existing EC2 KeyPair to enable SSH access to the instance."
ConstraintDescription: "Must be the name of an existing EC2 KeyPair."
Mappings:
RegionMap:
us-east-1:
AMI: "ami-0abcdef1234567890"
us-west-2:
AMI: "ami-0fedcba9876543210"
Conditions:
CreateMediumInstance: !Equals [!Ref InstanceTypeParam, "t3.medium"]
Resources:
MyEC2Instance:
Type: "AWS::EC2::Instance"
Properties:
InstanceType: !Ref InstanceTypeParam
KeyName: !Ref KeyNameParam
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", "AMI"]
Condition: CreateMediumInstance # Only create if InstanceType is t3.medium
MyS3Bucket:
Type: "AWS::S3::Bucket"
Properties:
BucketName: !Sub "my-unique-bucket-name-${AWS::Region}-${AWS::AccountId}"
Outputs:
EC2PublicIP:
Description: "The public IP address of the EC2 instance."
Value: !If [CreateMediumInstance, !GetAtt MyEC2Instance.PublicIp, "No instance created"]
S3BucketName:
Description: "The name of the S3 bucket."
Value: !Ref MyS3Bucket

Step 4: Validate the Template
Before deploying, it’s crucial to validate your CloudFormation template to avoid syntax errors, you can use the AWS Management Console or the AWS CLI for validation.
Using the AWS CLI:
aws cloudformation validate-template --template-body file://template.yaml

Step 5: Upload and Deploy the Template
- AWS CLI: Run the following command to deploy the CloudFormation template using the AWS CLI:
aws cloudformation create-stack \
--stack-name MyStack \
--template-body file://template.yaml \
--parameters ParameterKey=InstanceType,ParameterValue=t3.micro \
--capabilities CAPABILITY_IAM

Step 6: Monitor Stack Creation
Once the deployment begins, you can monitor the progress in the CloudFormation console. CloudFormation will display the status of each resource being created or updated.
- If there’s an error during the process, AWS will roll back the changes automatically.
- If the creation is successful, you’ll see the CREATE_COMPLETE status.

Step 7: Retrieve Outputs
If you defined outputs in your template, such as the public IP address of an EC2 instance, you can retrieve them from the Outputs section in the CloudFormation console or by using the AWS CLI:
aws cloudformation describe-stacks --stack-name MyEC2AndS3Stack --query "Stacks[0].Outputs"

- We can check in Instance dashboard
- Now we can see that same IP Addresses output of CloudFormation and created instance

- Now go to S3 Console and check S3 Bucket creation

Delete the Stack:
To delete the stack and remove all the resources provisioned by it:
aws cloudformation delete-stack --stack-name MyStack

Conclusion
Here in this article, we have created a complete process for building the AWS CloudFormation stack, which will be used to deploy an EC2 instance and an S3 bucket. In this section, CloudFormation makes AWS resources much easier to provision by infrastructure as code: you are capable of defining and automating the resource creation. We had automated the process of infrastructure deployment, hence making it swifter and with less probability of errors in configurations manually. AWS CloudFormation provides powerful capabilities for consistently managing cloud resources at scale and, therefore, can be a very useful utility. It can be much easier to create and manage AWS resources with CloudFormation through proper planning, validation of templates, and error resolution to keep dependable and scalable cloud infrastructure.