Automate application deployment with AWS CloudFormation Part 2 - Resources

Part 1 of this blog series provided a brief CloudFormation introduction, introduced the CloudFormation template, and then discussed the "Parameters" section of the CloudFormation template.

CloudFormation templates can can get large pretty quickly. Click here to download the entire CloudFormation template for the www.robhughes.net (RHDN for short) website. I recommend opening up the RHDN CloudFormation template in a separate window/tab so you can quickly refer to the contents throughout this series of blogs. 

Most CloudFormation templates I have viewed come with an embedded warning which I will dutifully repeat here:

WARNING: This template creates one or more Amazon EC2 instances, an Elastic Load Balancer and an Amazon RDS DB instance. You will be billed for the AWS resources used if you create a stack from this template.

If you use the RHDN template to create a CloudFormation stack you could incur charges! See the What is the AWS Free Usage Tier regarding how you can get started using AWS for free.

CloudFormation Template Resources

The "Resources" section of the CloudFormation template is the only required section. Each resource to be created must have its own JSON block and be identified by a unique logical ID. Multiple resources are separated by commas. e.g.

"Resources" : {
    "_Logical ID1_" : {
        "Type" : "_Resource type_",
        "Properties" : {
            _Set of properties_
        }

    },

    "_Logical ID2_" : {
        "Type" : "_Resource type_",

        "Metadata" : { "Object1" : "Location1", "Object2" : "Location2" }

        "Properties" : {
            _Set of properties_
        }
    }
}

Logical IDs

The logical ID must be alphanumeric (A-Za-z0-9) and unique within the template. You use the logical ID to reference the resource in other parts of the template using intrinsic functions provided by CloudFormation. In many cases the logical ID acts as a placeholder for the actual, or physical ID, of the resource that won't come into existence until the stack is created.

Resource Types

The resource type is specified with a JSON name/value pair with name "Type" and where the value identifies the type of resource that you are declaring. For example, the AWS::EC2::Instance declares an Amazon EC2 instance. For a list of all the resource types, see AWS Resource Types Reference.

Metadata Attributes

The Metadata attribute enables you to associate structured data with a resource. By adding a Metadata attribute to a resource, you can add data in JSON format to the resource declaration. This is useful to create comments and part 3 of this blog series demonstrates the use of metadata attributes to nest a AWS::CloudFormation::Init block within a metadata attribute

Resource properties

The optional resource properties are specified with JSON "Properties" name and where the value is a JSON object with a list of one or more name/value pairs representing the additional options that you can specify for a resource. The exact set of allowable options is dependent on the resource type.

For example an AWS autoscaling group would have type AWS::AutoScaling::AutoScalingGroup and would accept the list of properties specified below:

{
   "Type" : "AWS::AutoScaling::AutoScalingGroup",
   "Properties" : {
      "AvailabilityZones" : [ String, ... ],
      "Cooldown" : String,
      "DesiredCapacity" : String,
      "HealthCheckGracePeriod" : Integer,
      "HealthCheckType" : String,
      "InstanceId" : String,
      "LaunchConfigurationName" : String,
      "LoadBalancerNames" : [ String, ... ],
      "MaxSize" : String,
      "MetricsCollection" : [ MetricsCollection, ... ]
      "MinSize" : String,
      "NotificationConfiguration" : NotificationConfiguration,
      "PlacementGroup" : String,
      "Tags" : [ Auto Scaling Tag, ..., ],
      "TerminationPolicies" : [ String, ..., ],
      "VPCZoneIdentifier" : [ String, ... ]
   }
} 

The RHDN CloudFormation template declares an autoscaling group as follows:

    "WebServerGroup" : {
      "Type" : "AWS::AutoScaling::AutoScalingGroup",
      "Properties" : {
        "AvailabilityZones" : { "Fn::GetAZs" : "" },
        "LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
        "MinSize" : "1",
        "MaxSize" : "5",
        "DesiredCapacity" : { "Ref" : "WebServerCapacity" },
        "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ]
      }
    }

The above example makes use of CloudFormation intrinsic functions

The "AvailabilityZone" property makes use of the "Fn::GetAZs" intrinsic function used to get the list of availability zones for a region. If the empty string is specified as the value then the list of availability zones for the region in which the stack will be created will be returned.

The "LoadBalancerNames" property takes advantage of the "Ref" intrinsic function. The Ref function takes a resource logical ID and returns the physical ID of the created resource.

The "DesiredCapacity" resource provides a convenient way to obtain the value of a parameter given the logical ID of the parameter within the "Parameters" section of the template. In this case the logical ID of the parameter is the "WebServerCapacity" parameter and the value returned will be the value selected when the stack is created.

The properties "MinSize" and "MaxSize" define the minimum and maximum number of EC2 instances within the autoscaling group. These values are fixed and cannot be modified at stack creation time unlike the "DesiredCapacity" property.

The "LaunchConfigurationName" property refers to a special resource with type AWS::AutoScaling::LaunchConfiguration and is used to configure how dynamically created resources, such as EC2 instances, are created over the lifetime of the stack.

Launch configurations will be covered in part 3 of this CloudFormation blog series.