Use AWS ECS Fargate deploy Microservices
In this project, we will build a microservice using ECS Fargate that can count the number of times you visit the website.
we use Golang to create the website, and expose 8000 port to allow traffic to enter from this port.
And using Redis as the database, which port is 6379 by default.
We need to deploy the Web and Redis in a different container and allow them to communicate with each other.
Due to data security, Web and Redis can’t be accessed directly by internet, the traffic can only come in from ALB.
Overview
How will we achieve this?
- Create a VPC environment.
- Prepare the Dockerfile & Docker-Compose and build it into image.
- Use command to create ECR repository, and push images to it.
- Create ECS Cluster and Task Definition.
- Create Application Load Balancer.
- Add the Task to Cluster Service.
Preparation / Prerequisites
- Basic understanding of AWS VPC, ELB, Auto Scaling, and Container knowledge.
- Make sure the region is US East (N. Virginia).
- This is my Github LINK for the simple web code which I used.
1. Download the source file: vpc.yaml
2. Download the project: materials
Step by Step
Step 1:use CloudFormation template — vpc.yaml to setup VPC network.
Step 2:Use Cloud9 to push images to ECR
Step 2.1:Create AWS Cloud9 Environment
- Let all setting default. Then Create environment.
Step 2.2:Modify IAM role
- Go to EC2 Instances console.
- Find the instance we create through Cloud9, right-click and find Security, then click Modify IAM role.
- In Modify IAM role, select Allow EC2 Access ECR.
Step 2.3:Build images
- Go back to Cloud9 IDE and upload local files. (materials)
- First, install docker-compose.
sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
# Enable executable permissions
sudo chmod +x /usr/local/bin/docker-compose
# Confirm installation is successful
docker-compose version
- Second, in the command-line interface, login to AWS.
$(aws ecr get-login --no-include-email --region us-east-1)
- Third, create an ECR repository from docker-compose using aws-cli.
- Remember update{ID}.dkr.ecr.{Region}.amazonaws.com
in.env
file
Use
grep
to findimage-name
in the docker-compose.yml. And use For-Loop to automatically generate ECR repository.
for r in $(grep 'image: \${DOCKER_REGISTRY}' docker-compose.yml | sed -e 's/^.*\///'); do aws ecr create-repository --repository-name "$r"; done
- Then, build docker-compose into images.
docker-compose build
- Finally, push images to ECR.
In docker-compose
image
, already tag image and repository.
docker-compose push
Step 2.4:Check ECR
- Click into the repository, you will find there has an image you just pushed from Cloud9.
Step 3: Create ECS Cluster
- Go to ECS console -> Cluster.
- Choose Fargate as a launch type.
- In Networking, do not Create VPC. We already setup vpc network from CloudFormation.
Step 4: Create Task Definition
In this section, we put the two containers (web & redis) in the same Task Definition.
- In ECS console, click Task Definitions in the left penal.
- Choose Fargate as a launch type.
- In Task Definition Name, type web-redis-task.
- In Task Role, select ecsTaskExecutionRole.
- In Task size, select memory and CPU.
- In Container Definitions, click Add Container. We will create two containers, one for web, the other for redis.
- Find web Image URI from ECR.
- In Port mappings, type 8000 as expose port.
- Then, click Add. We have completed the creation of web container.
- Click Add Container again.
- Find redis Image URI from ECR.
- In Port mappings, type 6379 as expose port.
- Then, click Add. We have completed the creation of redis container.
You can choose paste repository-url, or {image name}:{tag} as an image.
If you choose repository-url, every time you push the latest image into ECR, task will always select the image which tag is the latest.
In Container Definitions, Storage and Logging has already set up CloudWatch by default.
If you run container that has any problem or bug, can go to cloudwatch to check logs.
Also, you can setup the file you want to mount between local and container in this part.
Step 5:Create Service
Step 5.1:Create Application Load Balancer for web
In this section, we let Load Balancer listen port 80 and forward all traffic from port 80 to port 8000 of the web.
So it is important to set the right Listen (80) and Target Group (8000).
- Go to EC2 -> Load Balancers
- In load balancer type, choose HTTP/HTTPS.
- In Basic Configuration
- In Name, type web-lb.
- In Scheme, choose internet-facing.
- In Listeners, type 80 Port.
- In Availability Zones, choose Web VPC and Public Subnet. So that you can use public DNS name to access
- In Configure Security Groups
- Choose http-sg, which allows traffic enter from 80 & 443 port.
- In Target Group
- In Target Type, select IP.
- In Port, type 8000, which is web’s port. - In Health checks, type /home as path. ALB will ping this URL to check website is healthy or not.
Step 5.2:Go back to ECS to create service for web.
- In the Services, click Create.
- In Configure Service
- In Launch type, choose Fargate.
- In Task Definition, select web-redis-task.
- In Service name, type web.
- In Number of tasks, type 2.
- In Configure network
- In Cluster VPC, select Web VPC we create at first.
- In Subnets, we put the container into Private Subnet.
- In Security group, select golang-sg & redis-sg, which allows traffic entering from 8000 & 6379 port.
- In Auto-assign public IP, select DISABLED.
- In Container to load balance
- Click Add to load balancer.
- In Load Balancer name, select web-lb.
- In Target group name, choose web-tg, which created from ALB.
Step 6:Verify the Service is Success
- Wait for Last status of tasks on ECS cluster change to “RUNNING”.
- Go back to EC2 -> Load Balancers, select the load balancer you created.
- Copy DNS name, add the path “/home”, and paste to browser. You will see your IP and the number of visits to the website
Note !!
Maybe you will confuse, why Web can connect to Redis? We didn’t set anything.
The key point is we put web and redis container in the same task definition.
Also, you can find the variable RedisEndpoint is setting as “localhost:6379” in the code of main.go.
According to official document,
In Fargate, when you launch multiple containers as part of a single task, they can also communicate with each other over the local loopback interface. Fargate uses a special container networking mode called awsvpc, which gives all the containers in a task a shared elastic network interface to use for communication.
Each task has its own Elastic Network Interface (ENI) which include a private IP.
The multiple containers in an ENI can share the same network.
That is the reason why IP address set to “localhost” or “127.0.0.1” can run.
Alternatively, if you put the containers in the different Task Definition, the localhost won’t be work because the two tasks have different network environments.
There has another solution called “Service Discovery”, which combined with “AWS Cloud Map”.
If you are interested in, try it.
Conclusion
Congratulations!!
You have learned how to use AWS ECS to create containers, and allow containers to communicate with each other.
Next time you want to deploy a website, there is a lightweight way you can choose, run on the container instead of the VM.
Reference
AWS ECS Developer Guide
Task Networking in AWS Fargate
How to make two containers connectable in AWS ECS Fargate?
docker-compose push image to aws ecr
Docker-Compose: Image and build together