CloudFormation = Magic

Table of Contents

Intro and tooling

The main idea behind CloudFormation is to declare your infrastructure as in "I want to launch two VMs, one in a poublic, one in private subnets" in a text file - a "stack" and instruct AWS to launch these resources. 

Natively you can do this via the CloudFormation Designer but since we are l33t h4x0rz we'll try something else - Visual Studio Code + some cool extensions. If you are a paranoid, tinfoild hat sporting individual, concerned about telemetry data you can grab VSCodium instead.

CF templates can be in JSON or YAML. I had no idea what YAML is but it is much more user readable than JSON so even people like me, without developer background, can make sense of it. 

Behold the same declaration in JSON (top) and in YAML (bottom):

JSON - 18 lines, curly braces, quotes...
YAML - 11 lines, not curly braces, sanity

Template structure and "Hellow World"To setup Visual Studio Code optimally I would suggest following this excellent guide written by Matthew Hodgkins. I would also suggest installing this extension - Cloudformation YAML snippets for VS Code. 

One of the simplest objects to declare is an S3 bucket. And we do so like this:

The "skeleton" of a template includes the sections below but only Resources: is mandatory:

AWSTemplateFormatVersion: 2010-09-09
Invocation, aka launching the stack

Now that we have a template, we can launch the stack using the AWS CLI  (if you have it installed) like this:

aws cloudformation create-stack --stack-name s3bucket --template-body file:///s3bucket.yaml
How it feels when you successfully launch your first stack

You can just as easily deprovision the deployed resources by deleting the stack which makes sure nothing gets oveloooked (and you don't get billed for lingering resources). 

aws cloudformation delete-stack --stack-name s3bucket

Of course we can also use the CloudFormation web UI to launch/delete/change the stack.

CloudFormation UI

Here's a bit more fleshed out example of a template demonstrating the use of the Parameters section and the !Ref function. It creates a VPC and a private subnet:

AWSTemplateFormatVersion: 2010-09-09

Description: |
  Test CF template - create a VPC and a private subnet
    Description: VPC CIDR Block
    Type: String

    Description: Private Subnet CIDR Block
    Type: String

    Type: "AWS::EC2::VPC"
      CidrBlock: !Ref VPCCidrBlock #required
      EnableDnsHostnames: true
      EnableDnsSupport: true
      InstanceTenancy: default
        - Key: Name 
          Value: TestVPC 

    Type: "AWS::EC2::Subnet"
      CidrBlock: !Ref Subnet1Block #required
      MapPublicIpOnLaunch: false 
      VpcId: !Ref VPC #required
        - Key: Name
          Value: PrivateSubnet

Once you have a base template structure you can keep iterating. For example, you can add a NAT Gateway so that the resource in the private subnet can communicate with the internet, a public subnet, Internet Gateway, routing table, security groups, etc. - all can be easily defined. 

Using such unholy incantations you can conjure up infrastructure in the cloud literallty in minutes (and you can also add to your resume that IaC is in your skillset). 

Lessons learned

If you create a template with sections like Parameters, Outputs, etc. they cannot be empty. This is why in the gif above you see me removing them. If you leave them, the template will fail validation and you will be greeted with the following messages: 

Additional Resources: