Always Use ECS Spot Containers
Over the past decade there has been a steady but sure increase in the use of containers as the principle compute of modern business applications.
Although VMs still hold an important place in contemporary IT architectures (yes, that's right, VMs are still a mature, important technology and not necessarily a dust-ridden fossil destined for immediate gunshot euthanasia) the increased adoption of containers by businesses can not be understated.
The recent findings of a report by cloud company Nutanix found that out of over 1500 companies they surveyed across the world, nearly 90% are now running containers across their applications in some shape or form.
For anyone who has spent even a short amount of time working in tech or tech adjacent industries, it is clear the containers are a big deal and will likely dominate the future posture of cloud infrastructure for many years to come.
Out of the many lauded benefits of shifting IT workloads to containers like scalability, resource-efficiency, portability, self-healing, dependency management, deployment rollbacks), something that I think is taken for granted is cost.
Now, this isn't to disagree with what is fact: running virtual machines is generally more expensive than running containers. They are more cumbersome in their resource allocation, and suffer from the burden of hypervisor overhead and OS duplication that containers have been designed to avoid. VMs ran (or rather, crawled) so containers could fly.
The Sobering Truth
With the increased use of cloud managed containerisation services, there is often a naΓ―ve and sometimes dangerous belief that using containers through services like ECS is so much cheaper than using EC2.
If we compare a single ECS Fargate container with a T3.Medium EC2 instance in the same region, with the same compute resources, that both run on Linux, how does the cost compare?
FARGATE - EU-West-2 - ARM - Linux - 2 vCPU - 4GB MEM - $57.75 per month
EC2 - EU-West-2 - ARM - Linux - 2 vCPU - 4GB MEM - $26.86 per month
Yes... that's right. The EC2 instance is less than half the cost of a single ECS Fargate container. Isn't that shocking? Well, not really. The key thing to remember is that ECS Fargate (compared to the ECS "EC2" Launch type - how I wish they called it something less confusing) is an AWS managed service.
In a nutshell, this means that for the luxury of less operational overhead (and flinging even the thought of patch and node management into the sky) you will pay a premium to AWS. The Abstraction of serverless comes at a cost.
Now, this shouldn't scare you away from using ECS Fargate entirely. It is an excellent product and, in my own experience, especially useful for small tech start-ups working on greenfield projects without a large operations team at hand.
However, you should walk into your deployments of ECS Fargate with your eyes wide open, and understand the most effective cost-saving strategies at your disposal to avoid a burning hole in your wallet.
Always Use ECS Spot Containers
AWS owns an ENORMOUS number of servers. No one knows how many for sure, but if AWS has over 300 data centers across the globe and, according to CloudZero, each data center can individually host as many as 50,000 servers, it would not be ludicrous to assume that their total number of servers exceeds the 15 million mark.
300+ of these == a LOT of server racks and probably enough thermal paste to butter every piece of bread in the UK for the foreseeable future (disgusting taste withstanding).
Inevitably, when dealing with such a colossal amount of processing power there is bound to be hours, days, and weeks when large portions of this compute is idly chugging away, eating up electricity and bandwidth without anyone actually using it.
To make use of this spare compute, AWS has a pricing model for both EC2, ECS and EKS called Spot. In a nutshell, spot instances and containers are offered to users at a price between 70-90% cheaper than their persistent, on-demand counterpart pricing model.
It should be noted that compared to EC2, which requires a more manual process of "Spot Bidding" (where you set the maximum price you're willing to pay per hour for your spot EC2), by setting a few cluster and service settings to a certain way, ECS automatically handles spot pricing in the background without the need to get involved in any bidding process.
But the caveat is that with just a two-minute interruption notice, and at any point, AWS can put your spot container into a shutdown state before it is terminated.
It's a Sicilian message. It means your containerised webapp sleeps with the fishes.π
However, although this lack of persistence would not be suitable for a large number of critical business applications, we can use a mixture of on-demand FARGATE and ephemeral FARGATE_SPOT tasks to lower costs and make sure that our infrastructure still has redundancy:
Step 1:
Set your ECS cluster so that the services that sit within it have the option to use either the default, on-demand FARGATE capacity provider and the cheaper, ephemeral FARGATE_SPOT capacity provider. This is done within the aws_ecs_cluster_capacity_providers block.
resource "aws_ecs_cluster" "ecs_cluster" {
name = "my-cluster"
setting {
name = "containerInsights"
value = "disabled"
}
}
resource "aws_ecs_cluster_capacity_providers" "fargate_capacity_provider" {
cluster_name = aws_ecs_cluster.ecs_cluster.name
capacity_providers = ["FARGATE", "FARGATE_SPOT"]
}
Step 2:
To ensure redundancy in our mixed spot/on-demand service, set the settings within the default_capacity_provider_strategy configuration block so that FARGATE is the default capacity provider, the base is 1 and the weight is 100. This means that, at a minimum, at least 1 on-demand ECS task will run 100% of the time.
resource "aws_ecs_cluster_capacity_providers" "fargate_capacity_provider" {
cluster_name = aws_ecs_cluster.ecs_cluster.name
capacity_providers = ["FARGATE", "FARGATE_SPOT"]
default_capacity_provider_strategy {
base = 1
weight = 100
capacity_provider = "FARGATE"
}
}
Step 3:
Finally, from the ECS service block, we can now set up the individual service strategy of both the FARGATE and FARGATE_SPOT capacity providers we made possible to use in Step 1 and 2.
resource "aws_ecs_service" "ecs_service" {
name = "app-service"
cluster = aws_ecs_cluster.cluster
task_definition = aws_ecs_task_definition.task_def.arn
desired_count = 2
capacity_provider_strategy {
capacity_provider = "FARGATE"
weight = 2
base = 0
}
capacity_provider_strategy {
capacity_provider = "FARGATE_SPOT"
weight = 1
base = 1
}
By setting FARGATE (for on-demand tasks) with a base of 0, and FARGATE_SPOT to have a base of 1, we are ensuring that when our ECS service starts up, it will make sure that at least 1 of our tasks will running using spot pricing.
Weight, in turn, decides the ratio for distributing the tasks when the base requirements are met. In this case, with FARGATE having a weight of 2 and FARGATE_SPOT having a weight of 1, we are ensuring that there is a 2:1 ratio between on-demand and spot ECS tasks in the service.
this means that for every 3 additional tasks in the service, 2 will be running regular Fargate, and at least 1 will be running using spot.
Now if we individually inspect our two tasks that are now running in our ECS Service:
We can see clearly that the first one is running on the on-demand, stable FARGATE capacity provider:
However, the second task is now definitely running on the money saving FARGATE_SPOT capacity provider: πππ
So do everything you can to lower your managed containerisation costs. Containers in the cloud are more expensive than you would expect and only relying on the merit them being cheaper than virtual machines is not a good idea. Spot ECS tasks give us the chance to retain high availability for our applications while still lowering costs as we scale up.
Always use spot ECS spot containers,
thanks for reading,
Mehmet