Microservices with AWS ECS
Tags: Containers, Aws Ecs, Elastic Container Service, AWS, Microservices

In this blog, I am going to create a sample microservice application (bookingapp) which has 3 services in total. For each service, I have a dedicated GitHub Repository. When you call the service, it is going to display the instance id and number of times the webpage has been hit so far. I will be using Redis to manage my webpage hit count. Below are the 3 GitHub Repositories I have.

Bookingapp-home. Bookingapp-movie. Bookingapp-bus.

Refer the GitHub repo bookingapp-home for the python code which I used.

The first part is to create the containers. Ideally when developer creates or updates any repository code and if it’s tested locally we will create a new docker image and push it to the repo. Let’s assume we created a new service called bookingapp-home and we validated everything and planning to deploy it to further environments.

I have cloned the repo and created a docker image and pushed it to docker hub.

ubuntu@ip-10–10–0–60:~$ cd ~ && git clone https://github.com/deepanmurugan/Bookingapp-home.git

Docker image

Push the image to your repository, I pushed this image to my repository in Docker Hub.

Create Network stack

Our Docker image is now ready, Let’s create and configure our network stack now. Before creating ECS cluster, we need to create networking for fargate instances. For that, I have created a VPC, 2 private subnets with NAT attached to route tables and 2 public subnets with Internet Gateway attached.

VPC

Subnet

Public Route Table

Private Route Table

I am going to spin Fargate instances in private subnet. The Fargate instances has to connect to the internet to pull docker images as I am having my docker images in docker hub. So, NAT is needed to reach the internet from private subnet. If you are using private repo inside your local network, you may not need NAT for private subnets.

Spin up ECS Cluster

Our Network is configured properly now, Let’s spin up ECS Cluster. I am using Fargate, so selecting Networking only mode and launching an ECS Cluster.

Once we created our cluster, we need to configure task definition.

Task definition on a high level is the definition of our container (container image, memory, env vars etc…).

Create new task definition → Launch type Fargate.

Select task memory needed for your task. I selected 1GB memory and 0.5vCPU for my task.

On the add container part define your container parameters.

Select proper image name which you created and pushed to repo. I mapped port 5000 of the container to port 5000 of the Fargate Instance. All other parameters are optional, you can use the few more parameters if you need. Finally, add the container and create the task definition.

Let’s create the task definition for redis also. We are going to use the same method, only the name and container image details will change here.

As you see, I am using redis:alpine image as redis container image. You can use the same or any other redis image. Once you add the container, create this task definition also. Now we have 2 task definitions one for shoppingapp-home and other for redis.

ECS service enables you to run and maintain a specified number of instances of a task definition simultaneously in an Amazon ECS cluster.

Let’s head over to our ECS Cluster and create a service.

Select our VPC and Private Subnets that we created.

I am not using any load balancer for redis service, so directly come to the service discovery part.

Here I am creating a new namespace called internal-bookingapp.com and the redis service name is redis. This will be resolved using service_name.namespace_name (dig redis.internal-bookingapp.com). Also, configure TTL for the DNS record, I used 30seconds for this.

I am not using auto scale for redis service. Finally, Review and create the service. Once you create the service you will see the task will be creating automatically. Number of task is the one which you declared in desired/minimum task count.

Let’s create our shoppingapp-home service. The steps are exactly similar except that we are going to use internet facing ALB and auto-scaling for this service. Before creating shoppingapp-home service let’s quickly create the ALB now.

I am creating internet-facing ALB in and using public subnets in 2 AZ. Right now using HTTP and Security group inbound HTTP open to anywhere.

Create a sample target group and do not register any hosts. All the hosts will be registered by our ECS service.

Review and create the ALB. Once ALB is created successfully, create a new service for bookingapp-home.

For security group, allow all traffic from load balancer security group. Health check grace period if you need. Configure ALB setting now.

Select existing listener on port 80 and create a new target group for path patter /home* and evaluation order to the highest.

Enable service discovery if you need.

Include auto-scale based on CPU.

Review everything and create the service.

Once you the service is created, it creates a deployment and try to create 2 tasks using the container that we specified in the task definition, also the two Fargate instances will be registered to the Target group of the ALB we created.

Understanding the Service Discovery Implementation

Let’s discuss something about service discovery part now. As soon as you create service discovery for any service in ECS, it will create a namespace in AWS Cloud Map service. All the services will be created inside the namespace as well.

Now AWS Cloud Map Creates a Route 53 internal domain name same as namespace name and creates DNS A records/srv records for each of our service. In this example we defined it as A records.

Note: You cannot delete or create records in this domain because its completely managed by Cloud Map. Whenever there is any change in the service, if you add a new task to the service, the corresponding Route 53 entry will be automatically updated by Cloud Map.

We are done with creating and configuring both of our services using AWS ELB. Let’s try to access the application using ALB Public DNS name.

As you can see my request has been load balanced to both the Fargate instances and no of hit information has been retrieved from redis successfully.

Quickly add a new microservice

Let’s see how we can quickly expand one more service called bookingapp-movie. I have created the new repo named Bookingapp-movie for the new service, created docker image and pushed to Docker Hub. Created task definition using bookingapp-movie container which we pushed. And service exactly similar to bookingapp-home service with a new target group bookingapp-movie-tg. ECS registers the Fargate instances in the ALB target group, also the service endpoint is resolvable correctly.

Conclusion

So far we have seen how we can create microservices and deploy it with AWS ECS using Fargate with rolling upgrade strategy. Its fairly simple to deploy a microservice and enable service discovery (which replaces other service discovery tools like consul, etcd, zookeeper etc…). You can safely update and deploy a service without impacting any other service as well. Also, you can auto-scale in or scale out based on load. In part 2 of this tutorial let’s see how we can deploy service using blue/green deployment model and how auto-scale works.