Skip to content

Use CloudFormation, relax and enjoy an easy life

Posted in Building future-proof software, and Go Cloud

Hello everybody, here we are. The day that I finally tackle CloudFormation. As far as I can remember I always told myself. Even though I kept telling myself that there is too much to cover, that I don’t know where to start.

Still, I thought I could introduce it as the sequel to a post introducing Serverless or even through AWS CDK. But neither stuck, I either forgot or dropped it each time. I didn’t have any interest left in Serverless and didn’t feel like showcasing it anymore. However, concerning the Cloud Development Kit, I could still introduce it later as its own thing. At last, I got to write this post, as a sequel, but to my Go Cloud series where I deploy a Golang app to AWS. In the previous post, we deployed the application through the AWS console, now is the time to deploy it using CloudFormation. Before we begin, you need to know that this gets pretty technical and you will need a basic understanding of AWS services.

What is CloudFormation?

CloudFormation is a free service that allows to model and set up your AWS resources through what is called a stack. The stack can represent a system you want to deploy, if we take the previous post as an example, all the components we deployed back then could be part of a stack. If we create a stack to deploy these resources either through the CloudFormation part of the AWS console, through the AWS CLI or directly through the CloudFormation API.

Here, since I will use the designer mode in the example I will give you. But first, we need to know what elements we will need in order to meaningfully define our CloudFormation stack. Let’s just jump into it!

Listing what we will need

Overall, we will need to have a Fargate task running our containerised application which needs to talk to Dynamo DB. From there we need to define a DynamoDB table and a Fargate task.

  • DynamoDB table
  • Fargate task

Now for the Fargate task, we need to create a task definition which will contain the characteristics of our task. That includes the location of our Docker image, alongside with the task permissions required to our container and the permissions we will give our container to access DynamoDB. Now an updated list looks like this:

  • Fargate task
    • Task definition
      • Role to access DynamoDB
      • Role to launch task
      • Container image in ECR

As we now have a task definition, we need a service to execute it, that service requires us to create a cluster and a VPC (virtual private cloud) for it.

  • ECS service
    • ECS cluster
    • VPC

In order to allow our container logs and metric to be accessible via CloudWatch, we will need to add some config to the cluster in order to enable that so let’s keep that in mind for later.

Also, we will need to create at least one subnet alongside a security group within our VPC to regulate traffic towards and from our application. With that information, here is the list of the elements we created in the last post.

  • DynamoDB table
  • Fargate task
    • Task definition
      • Role to access DynamoDB
      • Role to launch task
      • Container image in ECR
    • ECS service
      • ECS cluster
        • CloudWatch container insights config
      • VPC
        • Public subnets
        • Security group

Those almost match the CloudFormation components we need to define. Although, there is one element we cannot create from CloudFormation, the container image in ECR. That part we will still need to build from a local machine or through continuous integration in order to push it to an Elastic Container Registry.

First, let’s define our VPC, I’ll show you some reasoning for that part of the CloudFormation template. Afterwards, I will fast forward to giving you the CloudFormation template that will allow you to deploy our application.

Fairly detailed example: VPC setup through the CloudFormation designer

Accessing the CloudFormation designer

The first thing we need to do is creating a new CloudFormation template through the AWS Console. You can access the CloudFormation section of AWS through that link.

Empty CloudFormation home

This one is empty, let’s get ready to fill by clicking on “Create stack”.

CloudFormation create stack screen
CloudFormation “Create stack” screen

From there, select “Create template in Designer” and click on the button with the same label. Then you will face the empty template designer screen and we can finally get to work.

The central part is where our components will appear as we add them. The top-left part contains all the AWS services we can add resources from with sub-trees containing the belonging resources. The bottom area contains textual configuration we can add to adjust our components and add parameters to create our stack.

Alright, let’s define our VPC.

What is a Virtual Private Cloud?

Because I enjoy making my life easier and that AWS allows us, I will use the CloudFormation designer to create our template. We will start with our Virtual Private Cloud or VPC.

According to AWS website, a VPC lets you provision a logically isolated section of the AWS Cloud where you can launch AWS resources in a virtual network that you define. It provides complete control over your virtual networking environment, including the selection of your own IP address range, creation of subnets, and configuration of route tables and network gateways.

That VPC will allow us to group a couple of subnets we can spread across at least two availability zones (AZ). An instance of our app will be deployed through one of these so there is little use to have more than one for now. However, if we get two or three instances running we increase the app resilience. AWS guarantees that not more than one AZ can fall at a time through a region so that allows us to still serve requests even when some instances aren’t available. Yes, I passed the AWS Solutions Architect exam. The flex is necessary, now let’s actually work.

Creating our VPC

On the left side of the screen, click on EC2 then scroll down to VPC. Drag the VPC item to the center and you will see this:

In my case, it gets created with the default identifier EC2VPC1PM23. Since I will need to reference it later on, I will pick an easier one like GoCloudVpc. You can change a resource identifier by clicking on it and editing it through the text part visible below.

Now what? Well, we need to configure the thing and lucky for us noobs, AWS has extensive documentation for CloudFormation. We can go straight to the VPC section and find what fields we need to set.

CloudFormation documentation provided by AWS for the VPC resource type

Scrolling down, we find that the only mandatory field is the boolean “CidrBlock” which is our primary IPv4 address block. For that value we will go for “10.0.0.0/16” this means that the network addresses within will be within the 10.0.0.0-10.0.255.255 range. Select the VPC then edit the properties as such:

And that’s it, it was all we needed to define our VPC. It’s time to define our subnets.

Defining our subnets

Reproducing what we need to add our VPC, we can now add two subnets to the designer drawing area.

Let’s rename these GoCloudSubnet1 and GoCloudSubnet2. The first property we need to set is the “VpcId” which is the parent network to our sub-networks.

Next, we set the “CidrBlock”. We can give these “10.0.0.0/24” and “10.0.1.0/24”. Finally, we set which availability zones each subnet will belong to using the “GetAZs” function. Now the code for GoCloudSubnet1 will be:

"GoCloudSubnet1": {
    "Type": "AWS::EC2::Subnet",
    "Properties": {
        "CidrBlock": "10.0.0.0/24",
        "VpcId": {
            "Ref": "GoCloudVpc"
        },
        "AvailabilityZone": {
            "Fn::Select": [
                "0",
                {
                    "Fn::GetAZs": ""
                }
            ]
        }
,
        "MapPublicIpOnLaunch": true
    }
}

Linking the VPC id to our subnets created a link in the designer. It’s great to have a visual indicator that validates you set your properties correctly. Now let’s add the security group.

Security groups a.k.a cloud border control

A security group acts as a virtual firewall for your instance to control inbound and outbound traffic, they work at a VPC level. We can define what traffic we accept towards and from our network. This includes addresses, ports and so on. We can use one to determine that traffic can come onto our VPC only through a certain port and from certain addresses.

Here we will create a simple security group which can receive traffic through any address but from port 8080.

Looking at the doc, the only mandatory field for a security group is “GroupDescription”. You can put whatever you want but I’ll go with “GoCloud security group”. Here I’ll add “GoCloudSecurityGroup” as the name for good form.

Next, we add the ingress and egress settings through the “SecurityGroupIngress” and “SecurityGroupEgress” properties and voila:

"GoCloudSecurityGroup": {
    "Type": "AWS::EC2::SecurityGroup",
    "Properties": {
        "GroupName": "GoCloudSecurityGroup",
        "GroupDescription": "GoCloud security group",
        "VpcId": {
            "Ref": "GoCloudVpc"
        },
        "SecurityGroupEgress": [
            {
                "CidrIp": "0.0.0.0/0",
                "IpProtocol": "tcp"
,
                "FromPort": 8080,
                "ToPort": 8080
            }
        ],
        "SecurityGroupIngress": [
            {
                "CidrIp": "0.0.0.0/0",
                "IpProtocol": "tcp",
                "FromPort": 8080,
                "ToPort": 8080
            }
        ]
    }
}

Now that we have the security group in place, our base network definition is complete. I will add a few more things to allow internet access so that we can pull the app image from ECR among other things.

Since this takes quite some time to take notes and screenshots while going through each CloudFormation components I will summon the power of the textual scene-jump.

Fast froward

After a couple of hours of tuning my template and deploying it over and over, I eventually reached a favourable result.

complete cloudformation template for our todo app
Complete CloudFormation template for our todo app

Here we have all the elements listed previously plus some additional networking components. The additional components allow the Fargate tasks to pull our todo app container, don’t worry I will share it all. In order to make this a ready to share, I extracted the image name as a parameter.

If we press the “deploy” button, the one with a cloud and arrow, we will land there:

From here, pressing “Next” will take us to the screen where we define the name of our stack alongside with our parameters. Here, I chose GoCloudStack as name and put the tag I pushed to ECR for the todo app built and pushed in the previous entry.

From there we press “Next” again and we will see a bunch more input settings for our stack. Not much useful here, you can set tags that will be useful for billing but that’s about it as beginners.

Next, we press “Next” again, we now are on the review screen. Scrolling all the way down, there is a capability requirement where we need to tick a box, ticking that box means that we’re okay with that template creating IAM roles that we need.

As you expect we will now press “Create stack”, that button will take you to the stack’s CloudFormation page which will list its events in a tab. It allows you to follow the progression of your stack as the state of its resources evolves. All the way from creation to deletion.

Since the resources from this stack take about 2-3 minutes to spawn you should get a drink.

Our stack is now created and we can test it with a postman collection, exactly the same way as last time. However, if you missed that post click here for the steps.

The complete CloudFormation stack

Since you’ve been patient, enjoy the full CloudFormation stack which you can use to deploy containers through Fargate tasks. It contains both resource definitions and metadata from the designer.

At last, we’re done, thank you for checking out this new entry of my Go Cloud collection. Feel free to let me know if you feel like anything you think can help improve the post. Although I like to think that what I write is good enough to publish, feedback is always good.

Photo by Simon Migaj from Pexels

Be First to Comment

    Leave a Reply

    This site uses Akismet to reduce spam. Learn how your comment data is processed.

    %d bloggers like this: