Part 20 of Learn AWS from Scratch

Containers: ECS, Fargate and EKS

What a container is and how it differs from a virtual machine, storing images in ECR, running them with ECS on Fargate, the difference between the two IAM roles, when to choose EKS, and a hands-on where a service replaces a stopped task.

In this article
  1. What's a container?
  2. Amazon ECR: your images' home
  3. Amazon ECS: AWS's way of running containers
  4. Amazon EKS: Kubernetes
  5. Hands-on: a service replaces a stopped task
  6. Summary
  7. Test yourself

In part nineteen we separated the services from each other. Each service still needs somewhere to run, and on an EC2 server that means an image, updates, libraries and the famous sentence: "it works on my machine".

Containers solve this: you package the application with everything it needs in one unit, and it runs the same way on your laptop and in production.

What's a container?

A container is an isolated process with its own files and libraries, which shares the host's operating system instead of carrying its own.

Virtual machines App App Full OS Full OS Hypervisor Hardware Containers App App App Container engine Shared OS Hardware
Each virtual machine carries a full operating system. Containers share the host's system, so they are lighter and start in seconds.
Virtual machine Container
Contains A full operating system and the application The application and its libraries
Size Gigabytes Often megabytes
Startup Minutes Seconds
Isolation Stronger, with a separate system Lighter, with a shared kernel

Image, container and registry

Three words you'll keep hearing:

  • Image: a read-only package of the application and its libraries, like a recipe.
  • Container: a running copy of an image. One image can run as a thousand containers.
  • Registry: where images are stored, such as Docker Hub or Amazon ECR.

The most common tool for building images is Docker. You write what the image contains in a Dockerfile:

dockerfile
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/

Then you build it, try it on your machine, and push it to a registry:

Bash
docker build -t shop .
docker run -p 8080:80 shop
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/shop

Amazon ECR: your images' home

ECR (Elastic Container Registry) is AWS's image registry, with storage on S3 behind the scenes:

  • Private repositories: access to them goes through IAM, so a server or task needs permission to pull.
  • Public repositories: anyone can pull from them, through the ECR Public Gallery.
  • Extras: image scanning for vulnerabilities, versions with tags, and lifecycle rules that delete old images.

Amazon ECS: AWS's way of running containers

ECS (Elastic Container Service) takes your images and runs them, keeps them running, and places them behind a load balancer. It's AWS's own service, simpler than Kubernetes, and the service itself has no extra charge. You pay for the capacity it runs on.

Four terms cover the whole service:

Term Meaning Comparable to
Cluster A logical group that tasks run in Your fleet of servers
Task definition A recipe: the image, CPU, memory, ports and roles A launch template
Task One or more running containers from that recipe A server
Service Keeps a set number of tasks running, and replaces failed ones An Auto Scaling group
ALB Load balancer ECS cluster Service: keep 3 tasks running Availability Zone A Task 1 Task 2 Availability Zone B Task 3 New when load grows
The service keeps the number of tasks you asked for across Availability Zones, and the load balancer sends visitors to whichever tasks are healthy.

Who runs the containers?

Containers need computing capacity, and you have three options:

Option Who manages the servers Suits
Fargate AWS entirely, with no servers to see Most applications; start here
Managed Instances AWS manages them, and you choose the instance types Needing GPUs or specific instances without the management
EC2 You, through an Auto Scaling group Full control, or reducing the cost of steady load

With Fargate you state the CPU and memory for a task, and pay for those while it runs. Fargate Spot cuts the price sharply for tasks that can tolerate interruption, in the same way as Spot servers.

Two IAM roles, and confusing them is a classic

Every Fargate task can have two roles, and they do different jobs:

Role Who uses it Example
Task execution role ECS itself, to prepare the task Pulling the image from ECR and sending logs to CloudWatch
Task role Your code inside the container Reading from S3 or writing to DynamoDB

If the task fails at startup with a pull error, look at the execution role. If your code gets AccessDenied while it's running, look at the task role. And give each service its own task role, not one shared role.

Network and load balancing

On Fargate each task gets its own network interface and private IP, so it has its own security group like a server. Put an Application Load Balancer in front of the service, and it registers new tasks automatically and removes failed ones. It suits most web applications, and you'd choose a Network Load Balancer for very high throughput or fixed IP addresses.

Storage

A container's disk disappears with it. To share files between tasks, mount EFS, which works on both Fargate and EC2. And for anything that matters, store it outside the container in S3 or a database.

Scaling

Service Auto Scaling changes the number of tasks based on average CPU or memory, requests per task from the load balancer, or a schedule. The policies are the same ones we saw in part seven.

On Fargate that's all you need. With EC2 there's a second layer, because you need servers for the new tasks to land on. A capacity provider links the service to an Auto Scaling group and adds servers when tasks need them.

Not just web services

Tasks don't have to stay running. Three common patterns:

Pattern How it works
Reacting to an event A file lands in S3, EventBridge starts a Fargate task to process it, and it stops when done
Scheduled work EventBridge Scheduler starts a task every night for a batch job
Queue workers A service pulls from SQS, and scales by the number of messages waiting

ECS Express Mode: the short way

Just want a web application from an image, without setting up every piece? ECS Express Mode takes an image and two roles, and creates the Fargate service, load balancer, health checks, scaling and a link. All of it stays in your account, so you can customize it later.

Amazon EKS: Kubernetes

Kubernetes is an open-source system for running containers, widely used across clouds and data centers. EKS (Elastic Kubernetes Service) runs its control plane for you, across several Availability Zones, at $0.10 per hour per cluster for versions under standard support, on top of the capacity. A version that's past that period costs $0.60 per hour.

Terms differ from ECS: a task is a Pod, and a server is a Node.

Node option How it works
EKS Auto Mode AWS provisions, updates and scales the nodes; it's what AWS recommends going forward
Managed node groups AWS creates and updates the servers, and you choose them
Self-managed nodes You handle everything, for special requirements
Fargate Each Pod runs in isolation without nodes; still available, though Auto Mode is preferred

For storage, EKS uses CSI drivers to mount EBS, EFS or FSx.

ECS or EKS?

ECS EKS
Complexity Fewer concepts, and quick to learn A big system with a lot to learn
Portability AWS only The same tools work elsewhere
Ecosystem Close integration with AWS A huge open-source ecosystem
Cost of the service itself Free Per hour per cluster
Choose it if You're starting out, and your work is on AWS Your team knows Kubernetes, or you run across several clouds

If nothing is pushing you toward Kubernetes, start with ECS on Fargate.

Containers on your own servers

Need the same tools outside AWS, such as in your data center?

Option What it does
ECS Anywhere Registers your own servers or virtual machines in an ECS cluster
EKS Hybrid Nodes Adds your own servers as nodes in an EKS cluster
EKS Anywhere Runs Kubernetes clusters on your own infrastructure, for isolated environments
EKS Distro The Kubernetes components behind EKS, for you to run and support yourself

Hands-on: a service replaces a stopped task

We'll run a public Nginx image on Fargate, with no build needed. From CloudShell, create the cluster and write the recipe. An image from a public registry with no logs doesn't need an execution role:

Bash
aws ecs create-cluster --cluster-name series-cluster \
  --query cluster.status

cat > task.json <<'EOF'
{
  "family": "web",
  "requiresCompatibilities": ["FARGATE"],
  "networkMode": "awsvpc",
  "cpu": "256",
  "memory": "512",
  "containerDefinitions": [{
    "name": "web",
    "image": "public.ecr.aws/nginx/nginx:latest",
    "portMappings": [{"containerPort": 80}],
    "essential": true
  }]
}
EOF

aws ecs register-task-definition --cli-input-json file://task.json \
  --query taskDefinition.family

Prepare the network: the default VPC, a subnet, and a security group that allows port 80 from your CloudShell only:

Bash
VPC=$(aws ec2 describe-vpcs --filters Name=isDefault,Values=true \
  --query "Vpcs[0].VpcId" --output text)
SUBNET=$(aws ec2 describe-subnets --filters Name=vpc-id,Values=$VPC \
  --query "Subnets[0].SubnetId" --output text)

SG=$(aws ec2 create-security-group --group-name series-web \
  --description "Series web task" --vpc-id $VPC \
  --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id $SG \
  --protocol tcp --port 80 \
  --cidr $(curl -s https://checkip.amazonaws.com)/32

NET="awsvpcConfiguration={subnets=[$SUBNET],securityGroups=[$SG],assignPublicIp=ENABLED}"

Run a single task. If this is your first use of ECS and you get an error about the service-linked role, wait a little and repeat the command:

Bash
TASK=$(aws ecs run-task --cluster series-cluster --task-definition web \
  --launch-type FARGATE --network-configuration "$NET" \
  --query "tasks[0].taskArn" --output text)

aws ecs wait tasks-running --cluster series-cluster --tasks $TASK

Get its address and try it:

Bash
ENI=$(aws ecs describe-tasks --cluster series-cluster --tasks $TASK \
  --query "tasks[0].attachments[0].details[?name=='networkInterfaceId'].value" \
  --output text)
IP=$(aws ec2 describe-network-interfaces --network-interface-ids $ENI \
  --query "NetworkInterfaces[0].Association.PublicIp" --output text)

curl -s http://$IP | grep -i "<title>"

You'll see <title>Welcome to nginx!</title>. Your first container is running, with no server you can see. Now stop it, and it stays stopped, because nothing is looking after it:

Bash
aws ecs stop-task --cluster series-cluster --task $TASK \
  --query task.lastStatus

Create a service that keeps one task running:

Bash
aws ecs create-service --cluster series-cluster --service-name web \
  --task-definition web --desired-count 1 --launch-type FARGATE \
  --network-configuration "$NET" --query service.status

aws ecs wait services-stable --cluster series-cluster --services web

FIRST=$(aws ecs list-tasks --cluster series-cluster --service-name web \
  --query "taskArns[0]" --output text)
echo $FIRST

aws ecs stop-task --cluster series-cluster --task $FIRST \
  --query task.lastStatus

Wait a minute, then list the tasks:

Bash
aws ecs list-tasks --cluster series-cluster --service-name web \
  --query taskArns

The ID has changed. The service noticed the task was gone and started another without you lifting a finger.

Bash
aws ecs delete-service --cluster series-cluster --service web --force \
  --query service.status
aws ecs wait services-inactive --cluster series-cluster --services web
aws ecs delete-cluster --cluster series-cluster --query cluster.status
aws ecs deregister-task-definition --task-definition web:1 \
  --query taskDefinition.status
aws ec2 delete-security-group --group-id $SG

Summary

  • A container packages the application and its libraries, and shares the host's system, so it's light and fast.
  • ECR stores images, and ECS runs them through a task definition, tasks and a service.
  • Fargate spares you from managing servers, and it's the best starting point.
  • The execution role belongs to ECS, and the task role belongs to your code.
  • EKS is for those who need Kubernetes, and ECS Express Mode is the short way for a web application.

Test yourself

Before you move on, try these questions to check you've got this part. Each one is a practical scenario, and the explanation appears once you answer.

Question 1 of 6

A Fargate task starts normally and serves traffic, but when its code writes to DynamoDB it gets AccessDenied. Where should the team add the permission?

Show the answer

Correct answer: D

The task role belongs to your code inside the container. The task's normal start shows the execution role is already doing its job.

  • A: ECS uses this one to prepare the task, such as pulling the image and sending logs.
  • B: A security group controls network traffic, and this error is about permissions.
  • C: Fargate has no servers for you to attach anything to, so instance profiles aren't available.

Review: Two IAM roles, and confusing them is a classic in this part, and Amazon ECS task IAM role in the AWS docs.

Question 2 of 6

A company runs its applications on Kubernetes in its own data center and on another cloud. Its team knows the Kubernetes tools well and wants to keep using them on AWS. What fits?

Show the answer

Correct answer: B

EKS runs the Kubernetes control plane for you, and the team's tools keep working, here and elsewhere.

  • A: This is a fine start for most applications, but it's AWS's own system, not Kubernetes.
  • C: This builds an ECS web service from an image, and it isn't Kubernetes either.
  • D: This runs functions in response to events, and has no Kubernetes in it.

Review: ECS or EKS? in this part, and What is Amazon EKS? in the AWS docs.

Question 3 of 6

A batch job runs in a container every night for about two hours, and nothing needs to run for the rest of the day. What fits at the lowest cost?

Show the answer

Correct answer: C

The schedule starts a task that stops when it's done, and on Fargate you pay only while it runs.

  • A: You'd pay for a task 24 hours a day, for two hours of work.
  • B: A Lambda run ends at 15 minutes, far short of two hours.
  • D: You'd pay for the server around the clock, and have to manage it too.

Review: Not just web services in this part, and Using Amazon EventBridge Scheduler to schedule Amazon ECS tasks in the AWS docs.

Question 4 of 6

Several Fargate tasks in one service need to read and write the same uploaded files, and the files must survive when a task stops. What should the team mount?

Show the answer

Correct answer: A

EFS is a shared file system that tasks can mount on both Fargate and EC2, and the files live outside any one task.

  • B: A container's disk disappears with it, and isn't shared with other tasks.
  • C: This is a temporary disk on a server, and Fargate gives you no server to attach it to.
  • D: This stores container images, not application files.

Review: Storage in this part, and Use Amazon EFS volumes with Amazon ECS in the AWS docs.

Question 5 of 6

An ECS service runs on EC2 servers in an Auto Scaling group. At peak times the service needs more tasks, and those new tasks need servers to land on. Which two features handle this? (Choose two.)

Show the answer

Correct answer: A + E

Service Auto Scaling changes the number of tasks, and a capacity provider adds servers when tasks need them. On EC2 you need both layers.

  • B: This lets ECS pull images and send logs, and has nothing to do with scaling.
  • C: This looks for vulnerabilities in images.
  • D: This spreads traffic across the tasks that exist, and doesn't add any.

Review: Scaling in this part, and Automatically scale your Amazon ECS service and Amazon ECS capacity providers for EC2 workloads in the AWS docs.

Question 6 of 6

A company runs its containers on ECS in AWS. Some must now run on servers in its own factory, and the team wants to keep using the same ECS tools. What fits?

Show the answer

Correct answer: B

ECS Anywhere registers your own servers or virtual machines in an ECS cluster, so the team keeps its tools.

  • A: These are Kubernetes components to run and support yourself, and the team uses ECS.
  • C: This runs tasks on AWS capacity at a lower price, not on your servers.
  • D: This runs in AWS, and no longer accepts new customers.

Review: Containers on your own servers in this part, and Amazon ECS clusters for external instances in the AWS docs.

Containers still run and cost money while waiting. What if your code only ran when there was something to do, and you paid nothing otherwise? In part twenty-one we build an API with Lambda, API Gateway and DynamoDB.