Collections /

Docker and AWS ECS

Last updated Jul 11, 2018
3

A high level look on Docker and Amazon Web Services's own docker container orchestration service: I will start with a quick intro on docker, then expand on ECS while breaking it down to components while pointing out some references and diagrams to help you have an overall good understanding of the service.

To better understand the use cases and benefits of ECS, understanding of Containers / Docker is needed so we will start from there.

Containers / Docker

Docker is a way to manage and run containers - it is an abstraction that lets you share host resources with your application by process isolation.

Docker ecosystem consists of mainly four components to achieve this:

  • Docker Daemon: runs in the host machine or VM, that manages your containers and exposes an API for the 'docker' command.
  • Docker Image: composition of changes, filesystem for the container
  • Docker Repo: a git-alike repo that is used to store images (ie dockerhub)
  • Docker Container: your working unit, your process

If you are familiar with virtual machines (ie VBox, VMware or AWS EC2), "sharing host resources" part may sound a lot like a VM - and docker feels no different than working in a VM for starts, and this is by design. However, that's about it when it comes to similarities between a VM and a Docker container. It is sharing OS level components such as kernel functionality rather than just physical resources; it is an extra layer of isolation with the support of good tooling and APIs.

Docker has the ability to build images by composing other images without actually re-building from an inherited base image. All mutations that you make (ie. install a package or copy a file) results with an incremental change in a layered file system, without actually touching the inherited image at all -- to put things in perspective: in a VM, when we add change a line to a 1GB base image, you would have to still distribute 1 GB for that small change. For docker though the amount of data that is distributed is almost equal to the size of the change you are making. This leads to much smaller units when you deploy, making deployments fast and cause much less stress to the network.

All that said, Docker is not an alternative for VM in many cases. Docker and VM can co-exist in same physical machine and when they do, their use case expands where VM isolates the system resources (ram, cpu, and so on) and Docker isolates application processes.

Above is the case with ECS.

ECS Cluster

ECS Cluster is basically a predefined auto scale configuration of EC2 instances that are designed to run docker daemons for your containers. They use AWS autoscale groups (ASGs) and launch configurations behind the scene.

ECS cluster comes to play with:

  • ECS Task Definitions: configurations used to run Tasks (read docker containers)
  • Service Definitions: configurations used to deploy Tasks, eventually into provisioned EC2 instances that makes the cluster.

In one sentence, ECS utilizes ECS Clusters as EC2 ASGs and uses Service Definitions to deploy and run Tasks (containers) using Task Definitions across EC2 instances / host machines:
ECS > [ECS Clusters > ASGs > EC2s > Tasks] | Task Definitions | Service Definitions

More on each of these concepts are explained later in post.

The goal is while having a much smaller deployment unit, you get an extra level of granularity on scaling where:

  • you scale your ECS clusters via good old ASG and then,
  • use ECS task definitions to form containers and then,
  • use service definitions to say how you want your tasks to be scaled or distributed amongst your fleet for EC2 instances 'the cluster'

While ASGs are essential part of the setup that is utilized under the hood, it is fairly abstracted away in ECS. I encourage you to take a look at ASGs as it might help you understand how you scale the hosts (link provided below), however ASG is more of a subject of VM orchestration in AWS rather than docker.

So, we will keep on focusing on ECS. Next up, Task Definitions.

ECS Task Definitions

An ECS task definition tell the ECS service how a container should be put into utilization as a ECS task. It contains details as, container image name, port mapping, memory and cpu needs, permission needs (via IAM policies) and so forth.

So, to put things in perspective in an example, if you put higher memory limits than what you have available in your single EC2 instance, the health of the application would be in great risk since the container will be created and tuned to use that amount of memory inside the EC2.

ECS Tasks

On AWS UI (console), sometimes a Task is also referred as a Task definition. However, they are different concepts and in official AWS references, thankfully, they are separated:

An ECS task is an instantiated task definition. In more words, task definition is the configuration and task is what the configuration is for and in many ways, it's the running container itself and your processing unit - application.

While you can run a single task by referring to its task definition through the command line or console. This is mostly used for one-time tasks such as migration or ETLs.

For services, ie. APIs; task definitions can also be automatically instantiated and deployed via service configuration and scaling rules defined in your Service Definition.

ECS Service definition

An ECS Service definition tells ECS how you want your tasks to be scheduled. It is another abstraction layer on top of task definitions and defines how tasks should scale within your ECS Cluster while acting as a glue for other AWS components, such as becoming a target group for your load balancers.

I think at this point, it's worth mentioning load balancers and other surrounding ECS components.

Notes and other surrounding AWS components

ECS is an application platform, and there are a frequent components that help you achieve a good infrastructure setup;

Namely;

  • ALBs and Target Groups: ALB is AWS's new application load balancers that designed to replace old elastic load balancers (ELB). ALBs lets you target various types of sources (aka target group) which lets you abstract away from port mappings. This gives you the ability to target containers, rather than ports defined in EC2 hosts (which would be a pain point, since containers would use different ports on a EC2 host) - so your resulting load balancer can source traffic from containers that are spread across your cluster.
  • ASGs: see ECS Cluster for links and why it is relevant.
  • ECRs: AWS native docker repo. AWS now gives you the option to go with any docker repo you'd like. Main reason you might want to go with ECR is ease of setup within AWS. However, there are also drawbacks. Treat this decision as if where you'd prefer to store your code; could be an internal network, a community repo (ie. dockerhub), or be close as possible to where your containers run. The setup can be found in ECS section of AWS. It was a requirement once and there are some out of date articles on the absolute requirement of ECR, which is not true these days.
  • AMIs: For custom EC2 hosts, you have the option to customize the setup ECS cluster via changing the host AMI. eg. have additional software installed in host for special use cases, and make containers communicate with the said software through unix sockets

Helpful Links and Diagrams

Some use cases and diagrams that help understand the use of ECS

Final words

On ECS ---

While ECS provides an environment where we have simple way to orchestrate your containers - of course it is not the only way. That said, compared to other solutions the complexity and cost of ownership of ECS may be significantly lower at the end.

Depending on your technical needs, we could consider:

  • Kubernetes
  • Nomad
  • Marathon / Apache Mesos
  • Centurion
  • and many others.

While some are (notably Kubernetes) is supported natively in AWS as EKS, we would need to provision your own fleet of EC2s for other solutions. There are also other hosted cloud solutions like Docker Swarm, and many other somewhat equivalent solutions in other IaaS providers, like Azure and Google Cloud.

On docker ---

There are a ton of use cases where you don't need to take it to production. Use it to quickly experiment on things, such as learning a new language. You can use it to achieve development environment parity with your fellow team mates. You can use it to isolate your testing suite. It is extremely developer friendly and it constantly gets better. Even just working with it on your local dev env is a joy.

And when you take it to the production - the optimizations you can have on deployment pipelines and DevOps procedures are huge.

Even though it's hard to write a non-biased article as a heavy docker fan, towards that effort, it is worth to mention that docker might not be really a good fit to be used in production environments where;

  • there is a need of running multiple concurrent processes running next to each other - docker is designed to run a single process at a time,
  • you have very tightly coupled services (ie shared code)
  • you don't really know the app you want to containerize
  • you want to run stateful services
  • you are not well versed with system administration or networking
    then chances are docker will not be able to serve you well.

Even in cases where you find you way out off those issues by going through elaborate setups that you share things in host level, or by following manuals line by line to have it set up, the value you would get from docker in that setup is questionable. Moreover, TCO is likely come out as expensive compared to others. Lastly, when there is a hype, there is good risk in jumping into that bandwagon; containerizing things just for the sake of it is likely to cause more harm than good.

Like this collection? Save it to read later.
3