Unpacking Amazon ECS

Posted by on February 22, 2021

The following post is a high-level description of Amazon Web Services’ Elastic Container Service (ECS), the relationship between its components, and how they can be used to deploy a web application.

ECS is a fully managed container service. It is akin to Kubernetes, but ultimately it is simpler and has fewer moving parts. ECS offers the security, reliability and scalability that is customary with AWS. The Fargate engine provides a serverless platform, allowing you to run applications without the overhead of managing servers.

Despite being a fully managed, serverless platform, there are multiple concepts which you need to understand to use Fargate effectively. This blog post intends to introduce and demystify some of these core concepts of ECS.

Before jumping into the specific ECS definition, let’s create an example of what we might use ECS for. Throughout this post, we’re going to explore how ECS can help us deploy a scalable, reliable web application. This web application consists of the following four containers:

  • A Ruby on Rails server
  • An Nginx Proxy
  • A logging forwarding container (e.g., Firelens)
  • An application monitoring container (e.g., DataDog)

Each of the four containers outlined above provides a useful part of an overall task, and this is exactly what an ECS Task is: one or more containers that work together to perform a single… task – in this case, a running web application.

We describe ECS Tasks in Task Definitions. Task Definitions are the building blocks that let you define which Docker Image a container will use, and how one or more containers share resources. On a conceptual level, they’re similar to docker-compose with some added AWS sugar. The types of configuration in Tasks Definitions are: CPU, memory, network, volume configuration and IAM roles.

Within the Task Definition, there are two IAM role options. I’ve highlighted the differences between them, as it’s easy to get them mixed up:

  • Task Role
  • Task Execution Role

The Task Role is the role that your running task will use to communicate with AWS APIs. For example, if the web application puts objects into S3, the Task Role should include the correct permission to allow that.

The Task Execution Role is the role that allows the ECS agent to communicate with AWS APIs. For example, if your Images are stored in ECR (Elastic Container Registry), the ECS agent will require permission to pull the Image.

As mentioned above, we want the application to be scalable, reliable and deployed multiple times a day. This is where ECS Services come in. They allow you to perform the following:

  • Run one or more tasks concurrently
  • Configure auto-scaling
  • Run tasks across Availability Zones
  • Place in a Target Group (to use with a Load Balancer)
  • Perform Deployments
  • Replace failing Tasks (think Chumbawamba, but in the Cloud)

In our example, we could create a web-application service which is configured to run two concurrent tasks (outlined above). We could place this service in a Target Group which is associated with an Application Load Balancer (ALB) via a specific listener rule granting it internet access. Each change in your application would result in a new Image, and a new task definition. Updating the service to use this new revision will prompt ECS to deploy a new task in your service, placing it in the Target Group and scaling the older version down. 

The final concept is short and sweet. Clusters (when using Fargate) are grouping mechanisms of logical tasks and services. We only have a single service in our example – a web application.

Together, we have unpacked the core concepts of ECS. We have explored how you can use it to create reliable, scalable and modern web applications. ECS (especially using Fargate) is a service that abstracts a lot of complexity for anyone looking to run a container-based application. However, there’s still a considerable barrier to entry which needs to be hurdled. Hopefully, this post has helped lower that barrier.