CloudFormation simplifies provisioning and managing resources. We just create templates for the services and applications we want to build. CloudFormation uses those templates to provision the services and applications, called stacks. We can easily update and replicate the stacks as needed. We can combine and connect different types of resources to create a stack.
Using CloudFormation to deploy and manage services has a number of nice benefits over more traditional methods (AWS CLI, scripting, etc.).
- Infrastructure-as-Code
A template can be used repeatedly to create identical copies of the same stack (or to use as a foundation to start a new stack). Templates are simple YAML- or JSON-formatted text files that can be placed under our normal source control mechanisms, stored in private or public locations such as Amazon S3, and exchanged via email. With CloudFormation, we can see exactly which AWS resources make up a stack. we retain full control and have the ability to modify any of the AWS resources created as part of a stack.
- Self-documenting
Fed up with outdated documentation on our infrastructure or environments? Still keep manual documentation of IP ranges, security group rules, etc.?
With CloudFormation, our template becomes our documentation. Want to see exactly what we have deployed? Just look at our template. If we keep it in source control, then we can also look back at exactly which changes were made and by whom.
- Intelligent updating & rollback
CloudFormation not only handles the initial deployment of our infrastructure and environments, but it can also manage the whole lifecycle, including future updates. During updates, we have fine-grained control and visibility over how changes are applied, using functionality such as change sets, rolling update policies and stack policies.
Nearly every AWS service and resource we can create in AWS can be modeled in CloudFormation.
CloudFormation has two parts: templates and stacks. A template is a JavaScript Object Notation (JSON) text file that defines what AWS resources are required to run the application.
Here is a simple template in json to create an EC2 instance:
{ "Resources": { "testEC2Instance": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId" : "ami-47157264", "InstanceType" : "t2.medium", "KeyName" : "foxutec1", "BlockDeviceMappings" : [ { "DeviceName" : "/dev/sdm", "Ebs" : { "VolumeType" : "standard", "DeleteOnTermination" : "true", "VolumeSize" : "30" } } ] } } } }
The sample template shows the “Resources” section. Though the “Resources” section is the real meat of the template, usually there are other sections as well:
A stack is a collection of AWS resources that you can manage as a single unit. In other words, you can create, update, or delete a collection of resources by creating, updating, or deleting stacks. All the resources in a stack are defined by the stack’s AWS CloudFormation template. A stack, for instance, can include all the resources required to run a web application, such as a web server, a database, and networking rules. If you no longer require that web application, you can simply delete the stack, and all of its related resources are deleted.
AWS CloudFormation ensures all stack resources are created or deleted as appropriate. Because AWS CloudFormation treats the stack resources as a single unit, they must all be created or deleted successfully for the stack to be created or deleted. If a resource cannot be created, AWS CloudFormation rolls the stack back and automatically deletes any resources that were created. If a resource cannot be deleted, any remaining resources are retained until the stack can be successfully deleted.
-from Stacks
Template Anatomy
The following example shows a JSON-formatted template fragment:
{ "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 } }
Templates include several major sections. The Resources section is the only required section. Some sections in a template can be in any order. However, as we build our template, it might be helpful to use the logical ordering of the following list, as values in one section might refer to values from a previous section. The list gives a brief overview of each section:
Specifies the AWS CloudFormation template version that the template conforms to. The template format version is not the same as the API or WSDL version. The template format version can change independently of the API and WSDL versions.
A text string that describes the template. This section must always follow the template format version section.
Objects that provide additional information about the template.
Specifies values that we can pass in to our template at runtime (when we create or update a stack). We can refer to parameters in the Resources and Outputs sections of the template.
A mapping of keys and associated values that we can use to specify conditional parameter values, similar to a lookup table. We can match a key to a corresponding value by using the Fn::FindInMap intrinsic function in the Resources and Outputs section:
{ ... "Mappings" : { "RegionMap" : { "us-east-1" : { "32" : "ami-6411e20d", "64" : "ami-7a11e213" }, "us-west-1" : { "32" : "ami-c9c7978c", "64" : "ami-cfc7978a" }, "eu-west-1" : { "32" : "ami-37c2f643", "64" : "ami-31c2f645" }, "ap-southeast-1" : { "32" : "ami-66f28c34", "64" : "ami-60f28c32" }, "ap-northeast-1" : { "32" : "ami-9c03a89d", "64" : "ami-a003a8a1" } } }, "Resources" : { "myEC2Instance" : { "Type" : "AWS::EC2::Instance", "Properties" : { "ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "32"]}, "InstanceType" : "m1.small" } } } }
The intrinsic function Fn::FindInMap returns the value corresponding to keys in a two-level map that is declared in the Mappings section:
{ "Fn::FindInMap" : [ "MapName", "TopLevelKey", "SecondLevelKey"] }
The example above shows how to use Fn::FindInMap for a template with a Mappings section that contains a single map (RegionMap), that associates AMIs with AWS regions:
-
- The map has 5 top-level keys that correspond to various AWS regions.
- Each top-level key is assigned a list with two second level keys, “32” and “64“, that correspond to the AMI’s architecture.
- Each of the second-level keys is assigned an appropriate AMI name.
The example template contains an AWS::EC2::Instance resource whose ImageId property is set by the FindInMap function.
MapName is set to the map of interest, “RegionMap” in this example. TopLevelKey is set to the region where the stack is created, which is determined by using the “AWS::Region” pseudo parameter. SecondLevelKey is set to the desired architecture, “32” for this example.
FindInMap returns the AMI assigned to FindInMap. For a 32-bit instance in us-east-1, FindInMap would return “ami-6411e20d”.
Defines conditions that control whether certain resources are created or whether certain resource properties are assigned a value during stack creation or update. For example, we could conditionally create a resource that depends on whether the stack is for a production or test environment.
For serverless applications (also referred to as Lambda-based applications), specifies the version of the AWS Serverless Application Model (AWS SAM) to use. When we specify a transform, we can use AWS SAM syntax to declare resources in our template. The model defines the syntax that we can use and how it is processed.
We can also use the AWS::Include transform to work with template snippets that are stored separately from the main AWS CloudFormation template. We store our snippet files in an Amazon S3 bucket and then reuse the functions across multiple templates.
Specifies the stack resources and their properties, such as an Amazon Elastic Compute Cloud instance or an Amazon Simple Storage Service bucket. We can refer to resources in the Resources and Outputs sections of the template.
Describes the values that are returned whenever we view our stack’s properties. For example, we can declare an output for an S3 bucket name and then call the aws cloudformation describe-stacks AWS CLI command to view the name.
Refer more about Template Anatomy on AWS.
Read More: aws-cloudformation-tutorial-part-2