Container Services (ECS, EKS, Fargate)
Key concepts
ECS vs EKS decision criteria
Fargate serverless containers
Task definitions
Service auto scaling
ECR for container images
Overview
AWS offers two container orchestrators and one serverless compute engine for them. Amazon ECS (Elastic Container Service) is the AWS-native orchestrator. Amazon EKS (Elastic Kubernetes Service) is managed Kubernetes. AWS Fargate is a serverless compute option that runs containers for either ECS or EKS without you managing EC2 instances. Amazon ECR (Elastic Container Registry) stores the images they run.
This topic is high-yield on the SAA-C03 exam through "which container service" scenarios. You should know the ECS versus EKS decision, the EC2 versus Fargate launch-type trade-off, what a task definition contains, how service auto scaling works, and the role of ECR.
Two Orchestrators, One Serverless Engine
Choose ECS for simple, AWS-native orchestration and EKS when you need Kubernetes portability and ecosystem. Independently, choose Fargate to skip server management or EC2 when you need fine control or lower cost at steady high scale.
Separate the two decisions: orchestrator (ECS vs EKS) and launch type (EC2 vs Fargate). Know that Fargate removes instance management, EKS adds a $0.10/hour control-plane fee per cluster, task definitions need awsvpc networking for Fargate, and Service Auto Scaling uses Application Auto Scaling.
Key Concepts
ECS vs EKS
Picking the Orchestrator
ECS is AWS-proprietary, simpler to operate, and integrates deeply with AWS services, with no control-plane fee. EKS runs upstream Kubernetes, so it brings portability and the Kubernetes ecosystem (Helm, operators, kubectl) at the cost of more operational complexity and a per-cluster control-plane charge. Pick ECS for speed and simplicity, EKS when you already invest in Kubernetes or need multi-cloud portability.
ECS vs EKS
| Dimension | Amazon ECS | Amazon EKS |
|---|---|---|
| Orchestration | AWS-native | Upstream Kubernetes |
| Operational complexity | Lower | Higher |
| Control-plane cost | None | About $0.10 per hour per cluster |
| Portability | AWS-focused | Kubernetes anywhere |
| Best for | Fast AWS-native delivery | Kubernetes teams, portability |
EC2 vs Fargate Launch Types
Who Manages the Compute
With the EC2 launch type you provision and patch the instances that run your containers, which gives control over instance types, GPUs, and daemon workloads, and can be cheaper at steady high utilization. With Fargate there are no instances to manage: you declare CPU and memory per task and pay per second. Both ECS and EKS can run on Fargate.
EC2 vs Fargate
| Dimension | EC2 Launch Type | Fargate |
|---|---|---|
| Instance management | You manage and patch | Fully managed |
| Pricing | Per EC2 instance | Per vCPU and GB-second |
| Control (GPU, daemons) | Full | Limited |
| Cost at steady high scale | Often lower | Often higher |
| Best for | Fine control, dense packing | No-ops, variable workloads |
Task Definitions (ECS)
The Container Blueprint
A task definition is a JSON blueprint for running containers: image, CPU and memory, port mappings, environment variables, log configuration, and IAM roles. The task role grants the application permissions; the execution role lets ECS pull images and write logs. Fargate requires the awsvpc network mode, which gives each task its own elastic network interface.
{
"family": "orders-service",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789012:role/ordersTaskRole",
"containerDefinitions": [
{
"name": "orders",
"image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/orders:1.4.0",
"portMappings": [{ "containerPort": 8080 }],
"logConfiguration": {
"logDriver": "awslogs",
"options": { "awslogs-group": "/ecs/orders", "awslogs-region": "us-east-1" }
}
}
]
}Services and Auto Scaling
Keeping Tasks Running and Scaling
An ECS service maintains a desired number of tasks, replaces unhealthy ones, and registers them with a load balancer. Service Auto Scaling uses Application Auto Scaling to add or remove tasks with target tracking (for example, keep average CPU at 60%), step, or scheduled policies. On EKS the equivalents are the Horizontal Pod Autoscaler and node scalers such as Cluster Autoscaler or Karpenter.
Scaling Layers
| Layer | ECS | EKS |
|---|---|---|
| Scale tasks/pods | Service Auto Scaling (target tracking) | Horizontal Pod Autoscaler |
| Scale capacity | Capacity providers / ASG | Cluster Autoscaler or Karpenter |
| Serverless option | Fargate (no capacity to scale) | Fargate profiles |
Amazon ECR
The Image Registry
ECR is a managed private container registry. It supports image vulnerability scanning, lifecycle policies that expire old images, cross-region replication, and immutable tags. Access is controlled with IAM, and ECS and EKS pull images from ECR using the task execution role or node role.
Best Practices
1. Default to Fargate to remove undifferentiated ops
└── Move to EC2 launch type for GPUs, daemons, or steady dense scale
2. Choose ECS unless you need Kubernetes
└── EKS pays off when portability or k8s tooling is required
3. Separate task role from execution role
├── Task role: least-privilege app permissions
└── Execution role: pull images and write logs
4. Scale with target tracking
└── Keep CPU or ALB request count at a target value
5. Manage images in ECR with lifecycle policies
├── Scan on push for vulnerabilities
└── Expire untagged and old images automaticallyCommon Pitfalls
Pitfall 1: Choosing EKS for a Simple Workload
Mistake: Standing up EKS for a small AWS-only service with no Kubernetes requirement.
Why it fails: Adds operational complexity and a per-cluster control-plane fee with no benefit.
Correct Approach: Use ECS on Fargate for simple AWS-native workloads; reserve EKS for teams that need Kubernetes.
Pitfall 2: Confusing Task Role and Execution Role
Mistake: Granting application permissions on the execution role, or expecting the task role to pull images.
Why it fails: The execution role pulls images and writes logs; the task role grants the running app its AWS permissions.
Correct Approach: Keep them separate and least-privilege for each purpose.
Pitfall 3: Assuming Fargate Is Always Cheapest
Mistake: Defaulting to Fargate for a large, steady, high-utilization fleet.
Why it fails: At constant high scale, well-packed EC2 instances are often cheaper than per-task Fargate pricing.
Correct Approach: Use Fargate for variable or low-ops workloads; compare against EC2 with Savings Plans for steady high scale.
Test Your Knowledge
A small team wants to run a stateless containerized API on AWS with the least operational overhead and no servers to patch. Which combination fits best?
A company already runs Kubernetes on-premises with Helm charts and wants to keep that tooling while moving to AWS. Which service preserves portability?
An ECS service on Fargate must scale out automatically when average CPU stays high during traffic spikes. What should the architect configure?
Related Services
Quick Reference
Decision Summary
Quick Decisions
| If you need... | Choose |
|---|---|
| Simplest AWS-native orchestration | ECS |
| Kubernetes portability or tooling | EKS |
| No servers to manage | Fargate |
| GPUs, daemons, or steady dense scale | EC2 launch type |
| A private image registry | ECR |
Common CLI Commands
# Authenticate Docker to ECR
aws ecr get-login-password --region us-east-1 \
| docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
# Register a task definition
aws ecs register-task-definition --cli-input-json file://task-def.json
# Create a Fargate service behind a load balancer
aws ecs create-service \
--cluster prod --service-name orders \
--task-definition orders-service \
--launch-type FARGATE --desired-count 2 \
--network-configuration "awsvpcConfiguration={subnets=[subnet-abc],securityGroups=[sg-123]}"
# Register a target-tracking scaling policy (via Application Auto Scaling)
aws application-autoscaling put-scaling-policy \
--service-namespace ecs --policy-type TargetTrackingScaling \
--resource-id service/prod/orders \
--scalable-dimension ecs:service:DesiredCount \
--policy-name cpu60 --target-tracking-scaling-policy-configuration file://cpu60.json