
Deploying individual containers is not difficult. However, when you need to coordinate many container deployments, a container management tool like ECS can greatly simplify the task (no pun intended).
For serverless approach, the best combination recipe for ECS cluster is AWS OnDemand and spot Fargate. The blog will describe how we can deploy ECS cluster by infrastructure as code (IAC) with optimal cost.
Introduction
ECS consists of a few components:
- ECS Cluster: The Cluster definition itself where you will specify how many instances you would like to have and how it should scale.
- Task Definition: ECS refers to a JSON formatted template called a Task Definition that describes one or more containers making up your application or service. The task definition is the recipe that ECS uses to run your containers as a task on your EC2 instances or AWS Fargate.
- Service: Based on a Task Definition, is used to guarantee that you always have some number of Tasks running at all times. A Service is responsible for creating Tasks.
From this blog, you will be using Docker Nginx to create a fully working solution ECS cluster with autoscaling and capacity provider strategy that mixes OnDemand and Spot for optimal cost.

TL;DR: The sources being used in this blog are available at GitHub.
Fargate OnDemand vs Spot

Moreover Fargate Spot allows you to deploy your containers as you would normally in Fargate, but benefit from savings since your containers will be running on spare AWS capacity. Below is the comparation between Fargate OnDemand vs spot in eu-west-1 region Ref.
Fargate | Fargate Spot | Fargate Spot saving | |
---|---|---|---|
CPU | $0.04048 | $0.01334053 | 67% |
Memory | $0.004445 | $0.00146489 | 67% |
Cost example: a 0.25 vCPU and 0.5 GB Fargate container running for 24 hours would cost $0.29622.
Cost example: a 0.25 vCPU and 0.5 GB Fargate Spot container running for 24 hours would cost $0.09762186.
Cloudforamtion IAC structure
Our Cloudformation code was structure by these following components:
Description and Metadata
The template Description enables you to provide arbitrary comments about your template. It is a literal variable string that is between 0 and 1024 bytes in length; its value cannot be based on a parameter or function.
You can use the optional Metadata section to include arbitrary JSON or YAML objects that provide details about the template.
Parameters
Use the optional Parameters section to customize your templates. Parameters enable you to input custom values to your template each time you create or update a stack. For example, you can pass parameters in the AWS CLI or you can type the values in the AWS console while creating an instance.
Resouce
In the Resources section, you declare the AWS resources you want as part of your stack. Each resource must have a logical name unique within the template. This is the name you use elsewhere in the template as a dereference argument. Because constraints on the names of resources vary by service, all resource logical names must be alphanumeric [a-zA-Z0-9] only. You must specify the type for each resource. Type names are fixed according to those listed in Resource Property Types reference on the AWS website. If a resource does not require any properties to be declared, you can omit the Properties section of that resource.
Outputs
The optional Outputs section declares output values that you can import into other stacks (to create cross-stack references), return in response (to describe stack calls) or view on the AWS CloudFormation console. For example, you can output the S3 bucket name for a stack to make the bucket easier to find.
Image registry
ECS supports both public image and private image ECR. For simplicity, we will use the public registry nginx for our main image. To create a private image ECR is somehow simple, you can following this guide to create private repositories.
VPC and Client-sg network
VPC network
A VPC is a virtual network inside AWS where you can isolate your workload. A VPC consists of several subnets. Each subnet is bound to an Availability Zone. A public subnet has a direct route to/from the Internet. As long as your service have an public IPv4/IPv6 address, they can communicate (in and out) with the Internet. A private subnet does not have a IPv4 route to/from the Internet but an Ipv6 route to the Internet exists. Service in private subnets can not be accessed from the public Internet. If you want to access the Internet from a private subnet, you need to create a NAT gateway/instance or assign an IPv6 address. You can deploy a bastion host/instance to reduce the attack surface of internal applications.

Client Security Group network
Some data stores are integrated into the VPC, others are only accessible via the AWS API. For VPC integration, you have to create a Client Security Group stack. The stack is used as a parent stack for security groups ElastiCache, Elasticsearch, and RDS. To expand communication with the data store from an EC2 instance, you have to attach the Client Security Group to the EC2 instance. The Security Group does not have any rules, but it marks traffic. The marked traffic is then allowed to enter the data store.

With this appoarch, we can well separate of concerns and security our app. Only service that subscribers to our client sg can communicate in cluster stack.
The full template file is in GitHub repo vpc-2azs.yml and client-sg.yml, below is bash CLI to run these stack.
bash aws-init-vpc.sh
The Cloudformation stack can be displayed in CloudFormation and navigate to the Stack section. In the Events tab of the stack, the progress of creating the stack can be followed.

Outputs
- VPC with public and private subnets in two availability zones.
- Internet Gateway.
- Route tables and Network ACLs.
- Client security group.
ECS cluster and Load Balancer
ECS cluster
This file starts from the cluster-fargate.yml file where you will add the cluster and ALB configuration.
Application load balancer (ALB)
The ALB configuration requires the configuration of the subnets to use. We will define ALB with enable both HTTP/HTTPS and S3 logging.

To start ecs cluster stack, run the below command.
bash aws-init-cluster.sh
Outputs
- ECS cluster with enabling both Fargate OnDemand and Spot provider.
- Dedicate load balancer for this specific cluster.
- HTTP/HTTPS ALB.
- Logging to s3 (Optional).
- CloudWatch alarm 5xx and maximum number of connections (Optional).

The red rectangle is domain DNS for our application that will be used in task definition.
Task Definitions and Autoscaling
Task Definitions
Configure task and ECS service in Cloudformation with mix provider strategy.
Autoscaling
You can increase or decrease your desired task count by integrating Amazon ECS on Fargate with Amazon CloudWatch alarms and Application Auto Scaling. Then, you can use CloudWatch metrics to configure your CloudWatch alarms and only scale if CPU utilization higher/lower than certain threshold.

To start ecs service, run the below command with app-demo.yml.
bash aws-init-task.sh
Outputs
-
ECS task with nginx image.
-
Fargate task with strategy 2(OnDemand): 1(Spot), task running should be n+1 for voting policy
-
Autoscaling group and healthcheck.
Navigate to the cluster-stack, retrieve the public DNS in Output section and verify whether the containers can be reached and a welcome message from Nginx.

We can run the following command to see how tasks spread across capacity providers.
The output of the above command should display a table as below.
AZ | CapacityProvider | Instance | Status | TaskArn |
---|---|---|---|---|
ap-southeast-1b | FARGATE | None | RUNNING | arn:aws:ecs:XXXXXXXX:task/cluster-fargate-demo-nginx-Cluster/task-1 |
ap-southeast-1a | FARGATE | None | RUNNING | arn:aws:ecs:XXXXXXXX:task/cluster-fargate-demo-nginx-Cluster/task-2 |
ap-southeast-1b | FARGATE_SPOT | None | RUNNING | arn:aws:ecs:XXXXXXXX:task/cluster-fargate-demo-nginx-Cluster/task-3 |
Cleanup
Cleaning up the resources is fairly easy now. Navigate to the Stack and click the Delete button. The progress of deletion can be tracked in the Events tab. This will take some minutes, but the good news is, that no manual deletion of resources must be done. Everything which has been created with the template is automatically removed.
TL;DR
GUI Installation Guide
-
Click Next to proceed with the next step of the wizard.
-
Specify a name and all parameters for the stack.
-
Click Next to proceed with the next step of the wizard.
-
Click Next to skip the Options step of the wizard.
-
Check the I acknowledge that this template might cause AWS CloudFormation to create IAM resources. checkbox.
-
Click Create to start the creation of the stack.
-
Wait until the stack reaches the state CREATE_COMPLETE
CLI Installation Guide
Clone the code and run following command.
Verify ECS stack working by access ALB endpoint and check status ECS running.

Congratulations! you have reached the end of the blog. We covered a lot of ground learning how to apply ECS Fargate Spot best practices such as diversification, as well as the use of capacity providers.
In the blog, we have covered:
- Deployed a CloudFormation Stack that prepared our environment, including our VPC and a Client-SG environment.
- Created and configured an ECS cluster with ALB.
- Created Auto Scaling Groups and Capacity Providers associated with them for OnDemand and Spot.
- Configured a Capacity provider strategy that mixes OnDemand and Spot.
- Learned how ECS Cluster Scaling works with Capacity Providers.
Some afterthought
- Fargate Spot is configured automatically to capture Spot Interruptions and set the task in DRAINING mode, a SITERM is sent to the task and containers and the application. That’s why the service application have to be handle graceful timeout, if you should use gunicorn like me, here is the link to configure deployment option.
- Choosing Fargate task sizes sometimes is tricky, you have to monitor your application’s usual usage and should set memory tasks always below 75% utilization to get the best performance Ref.
- The combined technique ECS-Fargate is so great and cost-effective that making k8s is too complicated for small-medium team size.
Комментарии