Infrastructure as Code using AWS CloudFormation and ECS Clusters — Step 10

Richy Great
6 min readJun 7, 2020

--

Photo by Joran Quinten on Unsplash

This story is part of a series “Initial Commit till Running on Cloud”.

Before we fly to the sky and live in the cloud, there are some recommendations from my side,

  1. Create different AWS accounts for each environment you have. At least for prod and non prod. This will save you from lot of pain in the future. This prevents accidental deletion of production resources, it gives you control over permissions of your employees and a clean financial management.
  2. Do not use root credentials for anything. Create it, write it in a paper and lock it in your locker. Everybody gets an IAM user with rights limited to their requirements.
  3. Do not spin resources on your own from console. You will definitely lose track of where you created it or may be someone might accidentally delete your precious resource. Always use CloudFormation to create resources. Also commit these Infrastructure as code files in a Git repository for versioning.
  4. Use spot instances inside ECS clusters to save huge amount of money. I repeat, huge amount of money.
  5. All resources in a VPC get default security group of the VPC. Internet facing ELB gets an additional security group which opens Http/Https traffic from the internet.
  6. Do not store files inside container, just don’t. Use S3 for this and access using S3 API.
  7. 2 availability zone should be more than enough on grounds of High availability. 3 is luxury, do it if you like the concept of trinity :)
  8. Update your nameservers of your website to AWS and use Route 53 for routing. It’s easier to have all control in one place rather jumping back and forth between 2 websites for configuring any changes in your DNS records.
  9. Buy reserved instances for unavoidable resources like NAT, this will save a lot of money.
  10. Use CloudWatch alarms to check metrics like CPU utilization and create alarms to warn you through email.
Recap of our Architecture

Following are the steps we will follow to spin up our resources

  1. Trigger a build from CodeBuild for all our latest code changes
  2. Create the VPC with Public, Private subnet, Internal Elastic Load Balancer and Internet facing Load Balancer. Also we will have 2 NAT instances in each Availability Zone https://raw.githubusercontent.com/richygreat/public-scripts/master/vpc-ha.yml
  3. Create 3 ECS clusters with 2 t3a.nano instances in all of them. 2 clusters are public and 1 in private subnets.
  4. Copy the DNS name of internal Elastic Load Balancer to the Task environment property internal.lb.uri
  5. Deploy user microservice as a service in private cluster called microservice cluster. Deploy bff application as a service in public cluster called ui cluster. Deploy api gateway as a service in public cluster called api cluster.
  6. Create listeners for Public and Private Load Balancers
  7. Create a new Security group for ELB to open port 80 to internet
  8. Configure Route 53 for a newly registered domain

Step 2 — VPC Creation

Download yml from https://raw.githubusercontent.com/richygreat/public-scripts/master/vpc-ha.yml

Navigate to CloudFormation and click Create stack button

Upload the file and click Next

Two Nexts and a click on Create stack will trigger Resource creation
Wait for the status to change to CREATE_COMPLETE

Step 3 — ECS Cluster creation

Now we will create 3 clusters to deploy our services.

Click Create Cluster button
Select EC2 Linux + Networking and click Next step
Type in the name and select On-Demand Instance with EC2 instance type t3a.nano and 2 Number of instance

Repeat the above steps for other 2 services with public-ui-cluster and public-api-cluster as name for others. Leave EC2 Ami Id, Root volume size and Key Pair (None) with defaults.

Select prod-VPC which we created
Select private subnets and the security group is chosen as the default security group

For ui and api public cluster choose the Public subnets.

Step 4 — ELB DNS environment property

Select the Task definitions of api gateway and bff to change the internal Load Balancer environment property

Navigate to EC2 and select Load Balancers to copy DNS name of prod-private-lb
Click Create new revision

Click on Container definition and scroll down to Environment variables to paste the internal lb’s hostname with http:// prefix.

Now once you click on Update in popup and click Create in main screen you will create a new version of this task. Repeat this for bff application too.

Step 5 — Deploy the tasks as service in ECS clusters

First we will deploy user microservice to private microservice cluster

Click on Create to deploy user microservice
We will select DAEMON Service Type to install 1 replica per EC2 instance in this cluster to simplify things

Click on Next Step buttons until you reach Create Service. Careful not to select any Load Balancing options.

Now 2 tasks are created and deployed in 2 different EC2 instances in the cluster.

You can view Logs of both replicas in this page or individually by clicking on the tasks

Step 6 — Create target groups to route public traffic

Create 3 target groups and select the respective instances in EC2 -> Load balancing -> Target Groups

Click target group
Make sure health check path is /actuator/health for microservices and API gateway

Select the port as 8081 for user-service-tg, 80 for api-service-tg and 80 for ui-service-tg

After creation select each and click on Targets -> Edit to select the instances
Search for the cluster name and click Add to registered

Now click on Load Balancers select public ELB and add a listener.

Select the default route for port 80 as ui-service-tg
Click View/edit rules
Add a rule with Host header match and route it to api-service-tg

Do the same for internal ELB registering a listener to 8081 with private cluster instances registered

Internal Load Balancer registered to 8081

Now our Load Balancers are ready to take on internal and internet traffic

Step 7 — Additional Security Group to open port 80

Create a security group to open port 80 of the Internet Facing Load Balancer

Inbound should open 80 to 0.0.0.0/0
Click Edit security groups and open port 80 to the internet

Select both the security groups default and internet-sg and Save

All is done :) Now the icing on this cake.

Step 8 — Route 53 configuration

I have already created a hosted zone which helps in DNS management
* as Name and ‘A’ record Type with Alias Target pointing to prod-public-lb

http://api.markoptin.com/user-service/api/v1/users/eve@apple.com

Registration is successful
Yay! it works.

Our awesome-app is up and running in production cloud. We have achieved a great feat in just few easy steps with minimal running cost. Also with high availability in AWS.

This series will now move in the direction of event driven architecture.

How was the series? Were you able to run the whole application in AWS?Leave your feedback and if you have doubts or need advice on this type of architecture for your product send me a mail to richygreat@gmail.com

--

--

Richy Great
Richy Great

Written by Richy Great

Father, Software Developer, Tech founder and a Story teller

No responses yet