Introduction to AWS CloudFormation 📜
Tags: aws, beginners, tutorial
Published: 2021-08-30 13:56:09

Deploying more than just a handful of services on AWS and setting each one up manually can get quite tedious. Having to configure each AWS resource by hand also leaves you at a much higher risk of making errors or introducing inconsistencies.

Enter AWS CloudFormation.

CloudFormation is a service that provides an easy way to create and manage a collection of AWS resources in a controlled and predictable way.

## How does AWS CloudFormation work?

The key concepts in CloudFormation are templates, stacks, and change sets.

- **Template:** A template is a description of your infrastructure, written in JSON or YAML, that can be interpreted by CloudFormation.
- **Stack:** Infrastructure created by CloudFormation using a template is known as a stack.
- **Change Set:** A summary of proposed changes to your stack that will allow you to see how those changes might impact your existing resources before implementing them

The first thing you do is to create a CloudFormation template in JSON or YAML format.

You then deploy the template using the CloudFormation console, API, or AWS CLI. CloudFormation provisions and configures resources by making calls to the AWS services that are described in your template.

![Screenshot 2021-08-27 at 4.20.14 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630061730047/_VLhDFzO7.png)

After all the resources have been created, CloudFormation reports that your stack has been created. If stack creation fails, CloudFormation rolls back your changes by deleting the resources that it created.

To update a stack, create a change set by submitting a modified version of the original stack template, different input parameter values, or both. CloudFormation compares the modified template with the original template and generates a change set. You can then view the changes that will be deployed before you decide to execute the change.

![Screenshot 2021-08-27 at 4.18.09 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630061748879/gtgSI8Cf8.png)

## Template Basics

The template can consist of the following sections:

- **Format Version:** The AWS CloudFormation template version that the template conforms to.
- **Description:** A text string that describes the template.
- **Metadata:** Arbitrary JSON or YAML objects that provide additional information about the template.
- **Parameters:** Values to pass to your template at runtime.
- **Rules:** Validates a parameter or a combination of parameters passed to a template during stack creation or stack update.
- **Mappings:** A mapping of keys and associated values that you can use to specify conditional parameter values, similar to a lookup table.
- **Conditions:** Conditions that control whether certain resources are created or whether certain resource properties are assigned a value during stack creation or update.
- **Transform:** Set of macros to process your template. Basically creates a processed version of your template.
- **Resources:** AWS resources that you want to include in your stack.
- **Outputs:** Declares output values that you can import into other stacks, return in response (to describe stack calls), or view in the console.

This is what a basic template looks like 👇

![Screenshot 2021-08-27 at 10.08.00 AM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630061768889/EtshsE9jH.png)

Let's go a bit more in-depth on some of the sections.

### Parameters

Parameters are used to customize a template with values. They give us the flexibility to change settings without having to modify the template code.

![Screenshot 2021-08-27 at 12.38.02 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630061782160/e6Cw6ltIGm.png)

### Resources

This is the bulk of the template. Here is where we define and configure the resources that CloudFormation will manage for us. When defining resources, you need to know about the type and that type’s properties.

![Screenshot 2021-08-27 at 12.38.59 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630061816994/T44l8NEDN.png)

### Outputs

These are like return values for the template. We use them to make it easy to find some of the resources that CloudFormation will create for us.

![Screenshot 2021-08-27 at 12.39.16 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630061829480/EpSSoaMHGp.png)

## Intrinsic Functions

CloudFormation has several intrinsic functions that you can use to refer to other resources and their properties. You can use them to assign values to properties that are not available until runtime.

- **Fn::Base64** - returns the Base64 representation of the input string
- **Fn::Cidr** - returns an array of CIDR address blocks
- **Condition functions** - Used to conditionally create stack resources. These are Fn::And, Fn::Equals, Fn::If, Fn::Not and Fn::Or.
- **Fn::FindInMap** - returns the value corresponding to keys in a two-level map that's declared in the Mappings section
- **Fn::GetAtt** - returns the value of an attribute from a resource in the template
- **Fn::GetAZs** - returns an array that lists Availability Zones for a specified region in alphabetical order
- **Fn::ImportValue** - returns the value of an output exported by another stack
- **Fn::Join** - appends a set of values into a single value, separated by the specified delimiter
- **Fn::Select** - returns a single object from a list of objects by index
- **Fn::Split** - split a string into a list of string values using a delimiter
- **Fn::Sub** - substitutes variables in an input string with values that you specify
- **Fn::Transform** - specifies a macro to perform custom processing on part of a stack template
- **Ref** - returns the value of the specified parameter or resource

CloudFormation allows you to either use the full function name (Fn::Sub) or the short form (!Sub).

This is what a sample template would look like with intrinsic functions 👇

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Creating an EC2 instance using a security group that has already been created or a new security group'

Parameters:
  ExistingSecurityGroup: 
    Description: An existing security group ID (optional).
    Default: NONE
    Type: String

Conditions:
  CreateNewSecurityGroup: !Equals [!Ref ExistingSecurityGroup, NONE]

Resources:
  MyInstance:
    Type: "AWS::EC2::Instance"
    Properties: 
      ImageId: "ami-0ff8a91507f77f867"
      SecurityGroups: !If [CreateNewSecurityGroup, !Ref NewSecurityGroup, !Ref ExistingSecurityGroup]
			Tags:
			  - Key: Name
			    Value: !Sub '${AWS::StackName}-webserver'

  NewSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Condition: CreateNewSecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 80
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

Outputs:
  SecurityGroupId:
    Description: The group ID of the security group used.
    Value: !If [CreateNewSecurityGroup, !Ref NewSecurityGroup, !Ref ExistingSecurityGroup]
```

## Conclusion

By leveraging an IaC tool such as CloudFormation, you can streamline the AWS deployment process. You can define your resource configurations once, then deploy them as many times as you need. You can manage anything from a single Amazon EC2 instance to a complex multi-tier multi-region application.

Feel free to reach out to me on [Twitter](https://twitter.com/anuj_bansal_)! 😊