I am running applications in production with AWS ECS Fargate provisioning with Terraform. I was suffering that Terraform scripts (HCL) tends to be very long because it defines infrastracture atomically and manually, so I was looking for some tools to reduce them.
This time I found Fargate CLI very useful to keep provisioning scripts very simple. Let me introduce it!
Demo project: https://github.com/acro5piano/terraform-fargate-example
Summary
- Create basic AWS ECS environment using Terraform
- Create fargate services and task definitions using Fargate CLI
- Deploy applications with Fargate CLI, without downtime
Motivation
There are some options to create an production ECS Fargate environment:
- Using the AWS management console
- AWS CLI
- ECS CLI
- Terraform
- Fargate CLI
Each of them has cons:
- makes the environment quite implicit, finally nobody understands the infrastructure
- is hard to configure, and it does not re-create & reverse the environment, so almost same as (1)
- does not create everything; Security Groups and ALB, and so on
- enables to provision everything as code, but makes the scripts very long and difficult to update the service
- does not create everything; Security Groups and ALB, and so on (same as (3))
So I would like to suggest mixing (4) and (5) and take good parts of them.
Please take a look at the complete code here:
https://github.com/acro5piano/terraform-fargate-example
Step-by-Step guide
Assuming we are creating a simple web app.
Dockerfile
Anything is okay if it listen port 3000.
# Dockerfile
FROM python:3.7.7-alpine3.11
CMD python -m http.server 3000
Terraform
Terraform has the following responsibilities:
- Creating an ECS cluster (which runs the Fargate service)
- Creating two Security Groups (which is like firewall)
- ALB
- ECS (which is allowed to communicate only with ALB)
Please replace the content or the file path for aws-credentials.ini
depends on your environment.
# main.tf
# depends on your environment
provider "aws" {
region = "ap-northeast-1"
shared_credentials_file = "./aws-credentials.ini"
profile = "default"
}
resource "aws_ecs_cluster" "webapp" {
name = "webapp"
}
resource "aws_security_group" "webapp" {
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 3000
to_port = 3000
protocol = "tcp"
security_groups = [aws_security_group.webapp_lb.id]
}
}
resource "aws_security_group" "webapp_lb" {
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
output "webapp_ecs_security_group" {
value = aws_security_group.webapp.id
}
output "webapp_lb_security_group" {
value = aws_security_group.webapp_lb.id
}
Note: We set output
to gettings the value easily later.
Fargate CLI
Next, let's create a Fargate Service with Fargate CLI.
To install Fargate CLI, please visit the following link:
https://github.com/awslabs/fargatecli/releases
And run the following script.
Please replace the content or the file path for aws-credentials.ini
depends on your environment.
#!/bin/bash
# create.sh
export AWS_SHARED_CREDENTIALS_FILE=$PWD/aws-credentials.ini
export AWS_PROFILE=default
export AWS_REGION=us-east-1
# First, create ALB
fargate lb create webapp \
--cluster webapp \
--port HTTP:80 \
--security-group-id `terraform output webapp_lb_security_group`
# Next, create Fargate Service
fargate service create webapp \
--cluster webapp \
--lb webapp \
--num 1 \
--port HTTP:3000 \
--cpu 256 \
--memory 512 \
--security-group-id `terraform output webapp_ecs_security_group`
The fargate service create
command can take --image
argument explicitly, but without the argument Fargate CLI will:
- Build
Dockerfile
under the current directory - Push the docker image to ECR
- Create a service based on the image
Confirm
Confirm the service has been created:
$ fargate lb list --cluster webapp
NAME TYPE STATUS DNS NAME PORTS
webapp Application Active webapp-xxxxxxxxxx.us-east-1.elb.amazonaws.com HTTP:80
Open webapp-xxxxxxxxxx.us-east-1.elb.amazonaws.com
and your service is running!
What is created?
By Terraform:
- ECR Repository
- ECS Cluser
- EC2 Security Group
By Fargate CLI:
- ECS Task Definition
- ECS Service
- ECS Task
- ECS Task Execution Role
- ALB
- ALB Target Group
- CloudWatch Log Group
Update service
We can update service (deploy) without downtime thanks to Fargate:e
$ fargate service deploy webapp --cluster webapp
Delete
Unfortunately Fargate CLI doesn't have idempotency, but deleting is supported:
$ fargate service scale webapp 0 --cluster webapp
$ fargate service destroy webapp --cluster webapp
$ fargate lb destroy webapp
$ terrform destroy
Note: ECS Execution Role will not be deleted.
Conclusion
I'm glad if you find Fargate CLI very useful tool to create ECS Fargate service.
You can write further DevOps tools for your project based on these code. The demo repository contains Makefile
wrapper script of fargate, which make things more simpler. Please take a look:
Top comments (0)