The Anatomy of a CloudFormation Template
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

The cornerstone of CloudFormation is the template file. Whether you’re using a JSON formatted or YAML formatted template, the anatomy of the template is the same. For every template, there are several main sections.

The format version and date, the document description, parameters, mappings, conditions, transform, resources and output information. Let’s go through these one by one. 

The AWS template format version is the version of the CloudFormation template. The latest template format version is 2010-09-09 and is also the only valid value at this point in time.

Description is an optional field that you can use to leave comments to describe your infrastructure. It's your template documentation.  That way, other collaborators will know exactly what’s happening in the template without having to look further.

Resources is the only required section of a CloudFormation template, meaning you have to declare at least one infrastructure resource. Each resource is broken up into three parts, a logical ID that is unique within the template, a resource type, and properties for that resource. 

The logical ID is used to describe the resources, and can be referenced in other parts of the template.

The resource type is a CloudFormation predefined code for the resource that you’re creating. You’ll need to look this up in the CloudFormation documentation. For example, the code for an EC2 instance is type of “AWS::EC2::Instance”. 

Resource properties are additional options that you can specify for a resource. For example, to create an EC2 instance, you can declare properties such as Instance Type, ImageID, user data and more. 

Now depending on the infrastructure you’re creating, you may have a situation where you need to avoid hard coding values and instead dynamically choose certain attributes of resources. For example, if you’re building a template to create an EC2 instance, you may need to choose what kind of EC2 instance should be used or how many instances should be created - and those values may change each time you run the template. 

You can do this using the parameter section of your template. With parameters, you can pass values to resources during the stack creation. You can also set parameters to have default values that can be overwritten when a user creates the stack. This means that at run time, a user can choose things like instance type, instance key pair name, and more - in order to customize the template to their own environment. 

There are also predefined parameters that you don’t have to declare called pseudo parameters. For example, you can use the predefined AWS account ID pseudo parameter to retrieve your account ID or the AWS region pseudo parameter to get the AWS region in which the resource has been created. You don't have to declare these yourself in the parameters section, you can simply reference them whenever you need them in your template. 

When you reference a parameter, a pseudo parameter, or even another resource, you can reference each of these using their logical IDs. For example, if you’re creating an EC2 Instance resource, and you have a parameter that enables a user to pass in their EC2 key pair name, in your EC2 instance resource block, you can use the “!Ref” keyword and specify the logical ID of the key pair parameter. 

This !Ref keyword is a CloudFormation-specific keyword that is a part of built-in functions called intrinsic functions. Other common intrinsic functions are: 

  • !GetAtt, which returns a value of from a resource attribute in your template 

  • !FindInMap, which finds a value in a map by using a key, and

  • Join, which joins two values using a delimiter, in this case the new line delimiter

As you create your template, you may need to look up certain values based on chosen parameters. For example, think about how to choose the right AMI for an EC2 instance type. This might be tough to hardcode since the same OS image usually has different IDs depending on the AWS region. So if you hard coded one AMI ID for our instance, you would need to make sure it launches in the same region every time. 

You can solve this problem using mappings. Mappings are very beneficial for cross-region usability, because I can then create a lookup table for AMI ID based on region and OS architecture and quickly find the right AMI ID for my instance. 

The conditions section is where you control what resources are created based on conditions that you define. You can think of this as an if/else statement. If my condition is true, create my resources. If it’s false, don’t create them or create different resources. For example, you could conditionally create a resource depending on whether the stack is for production or a test environment. To do this, you can create a parameter called the environment type parameter with allowed values of test and prod. 

From there, the isProduction condition will evaluate if the string the user passed in for the environment type parameter is equal to prod or not. 

If it’s equal to prod, the CloudFormation template will create the EC2 instance that specifies the isProduction condition. 

Then, there’s the transform section which enables you to specify macros that you can use in your template. Macros can be pretty advanced, so I won’t talk much about them in this introductory course, but they provide you more custom processing in your templates. 

And finally, you can use the template output section to return resource information once the stack has been created. For example, if you have a template creating an EC2 instance, you can use the outputs section to pass back the Public IP address of that instance or the instance ID. You can then see these values in the CloudFormation console, or import them to another stack if you’d like. 

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.