Building a CloudFormation Template Demo


DVA-C02 Introduction
Amazon CloudWatch
Anomaly Detection
PREVIEW14m 35s
Options for Operating Programmatically with AWS
AWS AppConfig
AWS Cloud Development Kit (CDK)

The course is part of this learning path

Start course
3h 58m

This course provides detail on the AWS Management & Governance services relevant to the AWS Certified Developer - Associate exam.

Want more? Try a lab playground or do a Lab Challenge!

Learning Objectives

  • Learn how AWS AppConfig can reduce errors in configuration changes and prevent application downtime
  • Understand how the AWS Cloud Development Kit (CDK) can be used to model and provision application resources using common programming languages
  • Get a high-level understanding of Amazon CloudWatch
  • Learn about the features and use cases of the service
  • Create your own CloudWatch dashboard to monitor the items that are important to you
  • Understand how CloudWatch dashboards can be shared across accounts
  • Understand the cost structure of CloudWatch dashboards and the limitations of the service
  • Review how monitored metrics go into an ALARM state
  • Learn about the challenges of creating CloudWatch Alarms and the benefits of using machine learning in alarm management
  • Know how to create a CloudWatch Alarm using Anomaly Detection
  • Learn what types of metrics are suitable for use with Anomaly Detection
  • Create your own CloudWatch log subscription
  • Learn how AWS CloudTrail enables auditing and governance of your AWS account
  • Understand how Amazon CloudWatch Logs enables you to monitor and store your system, application, and custom log files
  • Explain what AWS CloudFormation is and what it’s used for
  • Determine the benefits of AWS CloudFormation
  • Understand what each of the core components are and what they are used for
  • Create a CloudFormation Stack using an existing AWS template
  • Learn what VPC flow logs are and what they are used for
  • Determine options for operating programmatically with AWS, including the AWS CLI, APIs, and SDKs
  • Learn about the capabilities of AWS Systems Manager for managing applications and infrastructure
  • Understand how AWS Secrets Manager can be used to securely encrypt application secrets

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

Stuart has been working within the IT industry for two decades covering a huge range of topic areas and technologies, from data center and network infrastructure design, to cloud architecture and implementation.

To date, Stuart has created 150+ courses relating to Cloud reaching over 180,000 students, mostly within the AWS category and with a heavy focus on security and compliance.

Stuart is a member of the AWS Community Builders Program for his contributions towards AWS.

He is AWS certified and accredited in addition to being a published author covering topics across the AWS landscape.

In January 2016 Stuart was awarded ‘Expert of the Year Award 2015’ from Experts Exchange for his knowledge share within cloud services to the community.

Stuart enjoys writing about cloud technologies and you will find many of his articles within our blog pages.