AWS CloudFormation (CFN) Basics – Study Lab – Part 1

Like many others I’m also passionate about Infrastructure as a Code (IaC) and automation stuff so I just started exploring AWS CloudFormation service in my lab so thought of writing this post about whatever I learned about this.
In this blog post I would walk you through fundamentals of AWS CloudFormation and then we will create a very simple CloudFormation template to deploy Windows Server 2016 EC2 instance. I will not get into much of explaining theoretically here but I will highlight key points about different CloudFormation components so that you can understand its fundamentals.

To start with AWS CloudFormation, we need to have fundamental understanding of following components and features that makes up this solution:
1. What is AWS CloudFormation ?
–An Infrastructure as code (IaC) solution provided in AWS Cloud without any additional cost. CloudFormation supports JSON and YAML as its supported configuration language for deployment automation. In short, AWS CloudFormation helps simplifying large complex infrastructure deployment by automating it and also keeps track of configuration changes in the infrastructure.  CloudFormation is intelligent enough to deploy your AWS resource in required order so generally we don’t have to explicitly define the sequence of resource deployment.

2. CloudFormation Templates
–Simply a text file in JSON or YAML format, We write the configuration in template file and CloudFormation takes this as declarative configuration and deploys the resources the way we have defined in the templates. You can write CloudFormation Templates either using JSON or YAML whatever you feel comfortable with. Syntax in both these configuration language is different.

3. CloudFormation Stacks
–Stack is basically a logical management unit, so all the AWS resources deployed by a Stack’s CloudFormation template will be treated as single unit. Stack manages the lifecyle of Stack’s resources, it creates the resources when you create a Stack and it will be deleting all the resources when you delete the stack. You should follow the best practices to keep the separate CloudFormation Stacks based on application lifecyle and requirement so not to mix up all the infrastructure in one single Stack. If any resource creation fails in the Stack for some reason the Stack will failed to create and would rollback the deployed resources.

4. CloudFormation Stacksets
–Stacksets helps us creating and managing CloudFormation Stacks across multiple AWS accounts and regions, before this feature came we had to manage CloudFormation Stacks independently in each AWS account and regions and that was an additional overhead in the large infrastructure spread across various AWS accounts and regions. With CloudFormation Stacksets we can now centrally manage all the Stacks across various AWS accounts/regions from a central (administrative) AWS account.

5. CloudFormation Designer
–Graphical tool that you can use to create CloudFormation Templates using a drag-and-drop interface.
 
6. CloudFormer
–This tool helps us creating CloudFormation Template from existing AWS resources. So let’s say, you have many AWS resources already created and configured in your environment and later you decided to use CloudFormation to provision similar kind of resources then you can simply use CloudFormer to generate CloudFormation Template from those existing resources. This is really helpful tool that saves lots of time creating templates from scratch.

7. Understanding JSON Basics
–Platform independent, Text based format for storing and exchanging data.
–Data stored in JSON document is in key-value pair. Each Key-Value pair is separated by comma.
–Data in curly braces {} represents JSON objects.
–Data in square brackets [] represents arrays.
–Like any other programing/scripting, JSON also has similar data types:
Array
Number
Objects
String
Boolean
Null

Note: Please note that in this blog post I will be creating and explaining JSON based CloudFormation template only.

CloudFormation Lab configuration steps:

1. Understand CloudFormation Template Schema
I referred below official AWS CloudFormation documentation to understand the structure (schema) of JSON based CloudFormation template.

CloudFormation Template Anatomy:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html
Below are sections in the CFN template, “Resources” section is the ONLY mandatory section in CFN template. “Parameters” section is used to define parameters that we use to pass values to CFN template during Stack creation. “Resources” and “Parameters” are two important section in the template schema, so basically in the “Resources” section we define what AWS resources we would be creating using this template and what are their required properties.

{
"AWSTemplateFormatVersion" : "version date",
"Description" : "JSON string",
"Metadata" : {
template metadata
},
"Parameters" : {
set of parameters
},
"Mappings" : {
set of mappings
},
"Conditions" : {
set of conditions
},
"Transform" : {
set of transforms
},
"Resources" : {
set of resources
},
"Outputs" : {
set of outputs
}
}

2. Creating a basic CloudFormation Template to launch an EC2 Instance with new Security Group
   –I created below CFN template that has very basic JSON configuration to create a new Windows Server 2016 EC2 Instance with a Security Group allowing RDP traffic from any source. To create this basic template I referred following CloudFormation Resource Type Reference documentation to understand what all are the different Resource Type and its properties and sub-properties that can be declared for a resource.

CloudFormation Resource Type Reference:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_EC2.html

AWS::EC2::Instance:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html

There are 3 parameters “KeyName”, “InstanceType” and “SourceCidrForRDP” in below templates and I’m referencing in my “Resource” section.

{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "This is a very simple JSON template that deploys a Windows 2016 EC2 instance.",
"Parameters" : {
"KeyName" : {
"Description" : "Name of an existing EC2 KeyPair.",
"Type" : "AWS::EC2::KeyPair::KeyName",
"ConstraintDescription" : "This keypair must be an existing valid keypair in the AWS region."
},
"InstanceType" : {
"Description" : "EC2 instance type",
"Type" : "String",
"Default" : "t2.large",
"AllowedValues" : ["t1.micro", "t2.micro", "t2.small", "t2.medium", "t2.large"],
"ConstraintDescription" : "Must be a valid EC2 instance type."
}, 
"SourceCidrForRDP" : {
"Description" : "IP Cidr from which you are likely to RDP into the instances. You can add rules later by modifying the created security groups e.g. 54.32.98.160/32",
"Type" : "String",
"MinLength" : "9",
"MaxLength" : "18",
"AllowedPattern" : "^([0-9]+\\.){3}[0-9]+\\/[0-9]+$"
}
},
"Mappings" : {
"AWSRegion2AMI" : {
"us-west-2"   : {"Windows2016" : "ami-0d705356e2616369c"}
}
},
"Resources" : {    
"EC2Windows": {  
"Type" : "AWS::EC2::Instance",
"Properties": {
"ImageId" : {"Fn::FindInMap" : [ "AWSRegion2AMI", { "Ref" : "AWS::Region" }, "Windows2016"]},
"InstanceType" : { "Ref" : "InstanceType" },
"SecurityGroups" : [ {"Ref" : "EC2SecurityGroup"}],
"KeyName" : { "Ref" : "KeyName"}     
}
}, 
"EC2SecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "EC2 Windows Instance SG",
"SecurityGroupIngress" : [
{"IpProtocol" : "tcp", "FromPort" : "3389", "ToPort" : "3389", "CidrIp" : {"Ref" : "SourceCidrForRDP"}}
]
}      
}  
},
"Outputs" : {
"InstanceDNSName" : {
"Value" : { "Fn::GetAtt" :[ "EC2Windows", "PublicDnsName" ] },
"Description" : "Public DNS name of the EC2 Instance for RDP connection"
},
"InstancePrivateIP" : {
"Value" : { "Fn::GetAtt" : [ "EC2Windows", "PrivateIp"] },
"Description" : "Private IP address the EC2 Instance"
}
}  
} 

3. Uploading the JSON file to S3 Bucket:
 –I created JSON file with above configuration and uploaded to S3 Bucket in my AWS account. I will provide this S3 bucket location as Template URI when creating CFN Stack.



4. Creating CloudFormation Stack:
–So we have our JSON template file ready and uploaded to S3 bucket, now I will go ahead and create a CloudFormation Stack using this template file. I will be using AWS PowerShell to create Stack, since I’ve never used CloudFormation before with PowerShell so let’s first see what all cmdlets are available related to CloudFormation in AWS PowerShell. And here is the list.



–Now I ran below PowerShell command and created that initiated Stack creation API call and declared resource creation as well. There are many other parameters in this “New-CFNStack” cmdlet that you can use like “EnableTerminationProtection” and “StackPolicyBody” but I wanted to keep this simple for now.

New-CFNStack -StackName "MyEC2LabStack" -TemplateURL "<a href="https://mylabcfntemplates.s3-us-west-2.amazonaws.com/EC2InstanceLab.json">https://mylabcfntemplates.s3-us-west-2.amazonaws.com/EC2InstanceLab.json</a>"`
-Parameter @( @{Key="KeyName"; Value="Oragon"}, @{Key="InstanceType"; Value="t2.large"}, @{Key="SourceCidrForRDP"; Value="0.0.0.0/0"})`
-OnFailure "ROLLBACK" -TimeoutInMinutes 60 -Tag @{Key="CFN"; Value="EC2CNFLab"} -Verbose 



Note: I would advise to refer below documentation to find all details about CloudFormation PowerShell cmdlets as I did. Please note that you need to setup AWS PowerShell on your machine before you run this command.

New-CFNStack Cmdlet
https://docs.aws.amazon.com/powershell/latest/reference/items/New-CFNStack.html

AWS CloudFormation PowerShell cmdlet Reference:
https://docs.aws.amazon.com/powershell/latest/reference/items/AWS_CloudFormation_cmdlets.html

6. Verifying CloudFormation Stack events and Resources
–Now let’s have a look at the CloudFormation Stack events to see what’s is happening with it. You can run below command and you would see output like this. If you look at this result, you can see that my EC2 Instance and Security group creation API call was initiated immediately when Stack creation was initiated. If you remember we had only two “Resources” declared in the above template to be created.



–Now let’s have a look at the created CloudFormation Stack and some of its properties, We can see it was created successfully from the Stack Status and we can also see the three parameters we declared in our JSON template. Stack creation would fail if one of the resource creation fails in the Stack so since our Stack creation is completed it means it has deployed all the resources defined in the template.



–Now let’s have look at the resources that got deployed in this Stack, So we have our EC2 Instance and Security Group that was created in this Stack.


7. Deleting a CloudFormation Stack:
–By default, when you delete a CloudFormation Stack it will be deleting all the resources in that Stack. If you want to protect the resource from being deleted, you can configure “DeletionPolicy” attribute for that resource. So let’s go ahead and delete our Stack created in previous step and see what happens.
–I ran below command to delete my CFN Stack and it had deleted the Stack along with its all resources that was deployed in the stack.

Remove-CFNStack -StackName “MyEC2LabStack” -Verbose


DeletionPolicy Attribute
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html
https://aws.amazon.com/premiumsupport/knowledge-center/cloudformation-accidental-updates/

–You can run below cmdlet to see the summary of deleted CFN Stack.

Get-CFNStackSummary -StackStatusFilter “DELETE_COMPLETE”


–From AWS console also you can verify.

Other important Reference documentation:
JSON Ref function:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html
Fn::GetAtt Function:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html
Fn::FindInMap Function:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html
JSON Validator
https://jsonlint.com/

So this was the first part of my CloudFormation learning journey, In the second part I will be covering the other components and capabilities of this solution like Nested JSON templates, Stacksets and would try to create little complex CFN Stack. So stay tuned for more updates on this topic.

Any feedback is highly appreciated. Happy Learning!!

Leave a Reply

Your email address will not be published. Required fields are marked *