CloudFormation

AWS CloudFormation is a service that helps deploy infrastructure as code. You create a template that describes all the AWS resources that you want (like Amazon EC2 instances or Amazon RDS DB instances), and AWS CloudFormation takes care of provisioning and configuring those resources for you. You don’t need to individually create and configure AWS resources and figure out what’s dependent on what; AWS CloudFormation handles all of that. There are similar resources for other services as well, for example, Azure Resource Manager for Microsoft Azure.

Advantages

  1. Simplify infrastructure management
  2. Quickly replicate your infrastructure
  3. Reproducible infrastructure deployment
  4. Easily control and track changes to your infrastructure
  5. Automatic resource removal

Concepts

  • Templates: The CloudFormation template is a JSON or YAML formatted text file that contains the configuration information about the AWS resources you want to create. When fed to CloudFormation, the template will direct it to create the required resources on AWS. Templates can also be created using the AWS CloudFormation Designer
  • Stacks: When you use AWS CloudFormation, you manage related resources as a single unit called a stack. You create, update, and delete a collection of resources by creating, updating, and deleting stacks. All the resources in a stack are defined by the stack’s AWS CloudFormation template. You can create, update or delete stacks by using the AWS CloudFormation console, API, or AWS CLI.
  • Change Sets: If you need to make changes to the running resources in a stack, you update the stack. Before making changes to your resources, you can generate a change set, which is summary of your proposed changes. Change sets allow you to see how your changes might impact your running resources, especially for critical resources, before implementing them

Template Components

The anatomy of a CloudFormation template:

{
  "AWSTemplateFormatVersion": "version date",
  "Description": "description of the template",
  "Parameters": {"set of parameters"},
  "Mappings": {"set of mappings"},
  "Conditions": {"set of conditions"},
  "Resources": {"set of resources"},
  "Outputs": {"set of outputs"}
}

All templates consist of the following:

  1. Parameters: Values to pass to your template at run-time (during stack creation), containing the specifics for the EC2 or S3 needed. A parameter is an effective way to specify sensitive information, such as user names and passwords or unique information, that you don’t want to store in the template itself. You can refer to parameters from the Resources and Outputs sections of the template. Multiple parameters can be passed such as the EC2 instance type, SSH security protocols, etc. For example, the code section below defines an InstanceTypeParameter for an EC2 instance.
{
  "Parameters": {
    "InstanceTypeParameter": {
      "Type": "String",
      "Default": "t2.micro",
      "AllowedValues": [
        "t2.micro",
        "m1.small",
        "m1.large"
      ],
      "Description": "Enter t2.micro, m1.small, or m1.large. Default is t2.micro."
    }
  }
}
  1. Mappings: A mapping of keys and associated values that you use to specify conditional parameter values, similar to a lookup table. You can match a key to a corresponding value by using the Fn::FindInMap intrinsic function in the Resources and Outputs section. In this example, it will match the corresponding AMI for a given AWS region
{
  "Mappings": {
    "RegionMap": {
      "us-east-1": {
        "32": "ami-6411e20d"
      },
      "us-west-1": {
        "32": "ami-c9c7978c"
      },
      "eu-west-1": {
        "32": "ami-37c2f643"
      },
      "ap-southeast-1": {
        "32": "ami-66f28c34"
      },
      "ap-northeast-1": {
        "32": "ami-9c03a89d"
      }
    }
  }
}
  1. Conditions: Conditions that control whether certain resources are created or whether certain resource properties are assigned a value during stack creation or update. For example, you could conditionally create a resource that depends on whether the stack is for a production or test environment.
  2. Resources: The Resources section specifies the stack resources and their properties, such as an AWS EC2 instance or an AWS S3 bucket. This is the only part of the template that is mandatory. Each resource is listed separately and specifies the properties that are necessary for creating that particular resource. You can refer to resources in the Resources and Outputs sections of the template. The following code section describes an EC2Instance resource and InstanceSecurityGroup resource. The resource declaration begins with a string that specifies the logical name for the resource.
{
  "Resources": {
    "EC2Instance": {
      "Type": "AWS::EC2::Instance",
      "Properties": {
        "InstanceType": "InstanceType",
        "SecurityGroups": [
          "InstanceSecurityGroup"
        ],
        "KeyName": "KeyName",
        "ImageId": "ami-08f569078da6ad4c2"
      }
    },
    "InstanceSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": "Enable SSH access via port 22",
        "SecurityGroupIngress": [
          {
            "IpProtocol": "tcp",
            "FromPort": 22,
            "ToPort": 22,
            "CidrIp": "SSHLocation"
          }
        ]
      }
    }
  }
}
  1. Outputs: Describes the values that are returned whenever you view your stack’s properties. For example. you can declare an output for an EC2 instance to display its id and availability zone
{
  "Outputs": {
    "InstanceId": {
      "Description": "InstanceId of the newly created EC2 instance",
      "Value": "EC2Instance"
    },
    "AZ": {
      "Description": "Availability Zone of the newly created EC2 instance",
      "Value": {
        "Fn::GetAtt": [
          "EC2Instance",
          "AvailabilityZone"
        ]
      }
    }
  }
}

Note

  1. The Resource Type attribute has the format - AWS::ProductIdentifier::ResourceType. Eg: The Resource Type for an S3 bucket is AWS::S3:Bucket and that for an EBS volume is AWS::EC2::Volume.
  2. The Ref function returns the value of the object it refers to. The Ref function can also set a resource’s property to the value of another resource.
  3. Depending on the resource type, some properties are required, other optional properties are assigned default values.
  4. Some resources can have Multiple properties and some properties can have one or more subproperties.

Best Practices

Take a look at the official best practices to be able to use AWS CloudFormation more effectively and securely.