Building a CloudFormation Template Demo


Course Introduction
Amazon CloudWatch
AWS Config
What is AWS Config?
AWS Control Tower
AWS Control Tower
PREVIEW19m 56s
AWS Resource Access Manager
AWS Management
AWS Service Catalog
PREVIEW10m 34s
AWS Trusted Advisor Best Practices
AWS Health Dashboard
AWS Data Visualization
Finding Compliance Data with AWS Artifact
Observability in AWS
Start course
6h 2m

This section of the AWS Certified Solutions Architect - Professional learning path introduces the AWS management and governance services relevant to the AWS Certified Solutions Architect - Professional exam. These services are used to help you audit, monitor, and evaluate your AWS infrastructure and resources and form a core component of resilient and performant architectures. 

Want more? Try a Lab Playground or do a Lab Challenge!

Learning Objectives

  • Understand the benefits of using AWS CloudWatch and audit logs to manage your infrastructure
  • Learn how to record and track API requests using AWS CloudTrail
  • Learn what AWS Config is and its components
  • Manage multi-account environments with AWS Organizations and Control Tower
  • Learn how to carry out logging with CloudWatch, CloudTrail, CloudFront, and VPC Flow Logs
  • Learn about AWS data transformation tools such as AWS Glue and data visualization services like Amazon Athena and QuickSight
  • Learn how AWS CloudFormation can be used to represent your infrastructure as code (IaC)
  • Understand SLAs in AWS

It's time to create a CloudFormation template. This template will create an EC2 instance that hosts an Apache Web Server and a security group that enables HTTP and SSH traffic. I'll start out with a blank CloudFormation template, that only has the headings of the appropriate sections. 

In this video, I'll be using YAML instead of JSON, as I like to make comments in my CloudFormation templates, and I also get very annoyed with brackets - but everything that I'm doing in this video, except for writing comments - you can also do in JSON.  

I'll start writing this CloudFormation template at the very top, where I'll specify the Template version. The latest template version is ‘2010-09-09’. If I wasn't sure how to find that value, I can google "CloudFormation latest template version", and without even clicking on the AWS documentation, I can see the latest value. 

Next, I'll write a template description in plain text. I'll describe what I'll create in this template, which is an EC2 instance with an Apache web server installed, that has a security group open for HTTP traffic. Then I’ll start working on the Resources section. 

I'll start with the EC2 instance.Chances are you won’t know all of the resource properties by heart, so keep in mind that you can open up the documentation to help you out. If you google aws, and whatever the service is you’re defining, say ec2 instance cloudformation, and click on the documentation, it will show you the appropriate syntax for both JSON and YAML format.  

With that being said, I'll start with the logical ID of EC2Instance - this is a name that I can use in other parts of the template to reference my instance. Then I'll specify the resource type, which is predefined by AWS, which I know is "“AWS::EC2::Instance”".

Next, I have the properties section, where I'll specify the instance type. I'll want whoever runs this template to be able to choose which instance type to create, so I'll reference a parameter that I haven't created yet - and I'll call it InstanceType. 

Moving on, I'll specify the Security Groups property, and here I'll reference a resource that I haven't created yet and call it InstanceSecurityGroup. Then I'll specify an ImageId, and this time I know I'll create a lookup table, or a mapping, to look up the appropriate ImageID for my instance. 

To do this, I'll use the !FindInMap intrinsic function: and then I'll make up a name for my mapping table, called RegionMap. Once again, I’ll fill in this mapping later.

Next, I'll paste in my user data. Here, I'm using the Base64 function to pass encoded data to EC2 and the Join function to append a set of values into a single value, separated by a delimiter. In this case, I’ll be joining together all the lines of my user data script, separated by a new line delimiter. Then, I'll have my bash script, I'll install an apache web server, start it up, create an index html page that has a header saying "Hello from Cloud Academy" and then make sure that file is in the appropriate place on my instance for the web server. 

Now, since I have all the necessary values for my instance, I'm going to switch gears and fill in some of this information I’m referencing but haven't created yet. 

So I'll start with the instance type parameter. I'll name it InstanceType, to match the logical ID I referenced earlier, give it a description: of EC2 Instance Type for Webserver, a type of “string”, provide the default value of “t2.micro” which is the free tier EC2 instance option so I can be frugal, and then specify all of the allowed values. Maybe, in this case, I only want them to be able to spin up a t2.micro, a t2.small, and a t2.nano and then the user can choose from that list. 

Additionally, I can specify allowed patterns as well here, so that whoever puts in values follow my rules and only uses characters I want them to put in. For now, I’ll be nice and let users type in whatever they want, but I will create a constraint description, and I'll say "must be a valid EC2 instance type."

So that parameter is done - I’m good to go there. Onto the next ref value, which is referencing another resource - in this case, my security group for my instance. I'll go ahead and copy and paste the security group in this template and I’ll run through it quickly. The logical ID matches the value that I'm referencing from my EC2 instance. The type is of AWS::EC2::SecurityGroup, I have a quick description, and then I have two ingress rules. One of which specifies that I'm allowing in all HTTP traffic from the internet via port 80. And then I have another ingress rule that specifies that I’m allowing in all SSH traffic from the internet via port 22. 

So now I’m properly referencing a resource that exists for my EC2 instance. To be able to properly SSH into my instance, I’m going to have to do a few more things. First, I’m going to paste in a couple of other parameters, one for the KeyPair, and one for the security group SSH CIDR address, so that users can specify what IP addresses can SSH into this instance.  And then I’ll quickly reference each of those logical IDs, the KeyPair for my EC2 instance, and the CIDR IP property for my security group resource, overwriting that hardcoded value. 

Onto the next piece of information to fill in, and that's our mappings section. I'm going to paste in a mapping here that you can use to look up an amazon machine image ID using the region and architecture of an instance. 

Then I reference that using the !FindInMap function, by specifying the key as the region where the stack is created using the AWS::Region pseudo parameter, and HVM64 as the name of the value to map to. I know that all allowed instance type values use the HVM64 virtualization. However, if I didn't know this virtualization  value, I could use a more complex map structure to look the value up. 

Last, there’s the outputs section. Here I want the stack to output two pieces of info about my instance. I want the Availability Zone the instance is in and the instance's public IP address. The first output, I will give the logical name of AZ, a quick description, and then provide the value. Here I am going to use the !GetAtt function to return the value of an attribute from my EC2 instance resource. So I'll type in !GetAtt, specify my EC2 instance, and then the attribute I want to get, which is AvailabilityZone. 

Then next, I'll be doing the same for the public IP. Provide a logical name, in this case PublicIP. And the value will be a Gett Att of the EC2Instance resource and the attribute is PublicIP.

And with that, I've created a cloudformation template! I know some of this syntax might be tough to understand initially, but if you're ever unclear about how to structure things, you can find examples for both JSON and YAML templates in the CloudFormation documentation.

About the Author
Learning Paths

Danny has over 20 years of IT experience as a software developer, cloud engineer, and technical trainer. After attending a conference on cloud computing in 2009, he knew he wanted to build his career around what was still a very new, emerging technology at the time — and share this transformational knowledge with others. He has spoken to IT professional audiences at local, regional, and national user groups and conferences. He has delivered in-person classroom and virtual training, interactive webinars, and authored video training courses covering many different technologies, including Amazon Web Services. He currently has six active AWS certifications, including certifications at the Professional and Specialty level.