☰ All modules Tier 3 · Containers (ECS, ECR, Fargate) GuideCheat sheet ‹ monitorings3 ›
Contents
  1. ECS building blocks and capacity
  2. Task definitions and container settings
  3. IAM roles
  4. Environment variables and secrets
  5. Services, standalone tasks and load balancing
  6. Auto scaling and capacity
  7. Deployments
  8. Task placement
  9. Amazon ECR
  10. Amazon EKS
  11. Numbers to know
  12. Decision rules
  13. Memory hooks

Containers (ECS, ECR, Fargate) — Cheat Sheet (DVA-C02)

Verified against AWS documentation on 2026-10-12 · ⚠️ = changed vs older material: learn the value shown here (older practice material may say otherwise; full list in notes/containers-guide.md#changed-vs-older-material) · ⚠️ unverified = AWS docs don't confirm it, don't rely on it · explanations and examples: notes/containers-guide.md.

ECS building blocks and capacity

Topic Current facts Memory hook
Core objects Cluster = boundary for capacity, tasks and services; task definition = versioned JSON blueprint; task = one running copy; service = keeps the desired count, replaces failed tasks, registers them with load balancers, scales and deploys them Blueprint → copy → keeper
Capacity types ⚠️ ECS Managed Instances (since 2025-09-30), Fargate, self-managed EC2, plus external instances (ECS Anywhere) Three ways to rent the floor
Fargate Serverless capacity per task; awsvpc only; per-task isolation (no shared kernel, CPU, memory or ENI); pay for task vCPU and memory Least operational overhead
ECS Managed Instances AWS provisions, patches (Bottlerocket) and scales EC2 instances in your account; several tasks per instance; GPUs and specific instance types; billed per instance + management charge; drained after 14 days; no SSH, no custom AMIs EC2 power, AWS chores
Self-managed EC2 ECS-optimized AMI + container agent + container instance role; ECS_CLUSTER=<name> in /etc/ecs/ecs.config (otherwise the default cluster) You patch, you scale
Launch type vs strategy Set launchType or capacityProviderStrategy, never both; neither → cluster default strategy; Managed Instances only through a strategy One or the other
Strategy fields base = first N tasks (0–100,000, one provider only); weight = share of the rest (0–1,000); API/CLI default weight 0 (console 1); one provider type per strategy Base first, weights after
Fargate Spot Discounted spare capacity; 2-minute warning as ECS Task State Change (stopCode SpotInterruption) + SIGTERM; SIGKILL after stopTimeout; no automatic On-Demand fallback Two minutes to pack
Fargate platform LATEST = Linux 1.4.0, Windows 1.0.0; new tasks get the newest patched revision; retirement wait fargateTaskRetirementWaitPeriod 0, 7 (default) or 14 days, EC2 event windows since 2025-12-18; only service tasks are replaced New task, new patches
AWS Copilot CLI ⚠️ End of support 2026-06-12 (announced 2026-03-06); deployed stacks keep running; use ECS Express Mode or the AWS CDK Copilot has landed
ECS Express Mode Since 2025-11-21: image + task execution role + infrastructure role → Fargate service with URL, shared HTTPS ALB, auto scaling, monitoring; no extra charge Image in, URL out
Exam scope ⚠️ Exam guide v2.1 (2024-12-12): Containers = Amazon ECR, ECS, EKS; AWS Copilot removed (v1.x listed it) Copilot left the syllabus

Task definitions and container settings

Topic Current facts Memory hook
Revisions family:revision; immutable, any change = new revision; deregister → INACTIVE, then delete-task-definitions Edit = new revision
Limits 10 containers per task definition (fixed); 64 KiB; 1,000,000 revisions per family (deleted ones still count)
Network modes awsvpc (own ENI, IP, SGs; required on Fargate), bridge (Linux EC2 default; dynamic ports), host (one task per host port), none; Managed Instances: awsvpc, host
Fargate sizes ⚠️ Task-level cpu/memory pairs: 0.25 vCPU → 0.5–2 GB … 16 vCPU → 32–120 GB; 32 vCPU with 60/120/244 GB on Linux 1.4.0
memory vs memoryReservation memory = hard limit → container killed (OutOfMemoryError: container killed due to memory usage); memoryReservation = soft, used for placement Hard kills, soft reserves
essential Default true; an essential container that stops stops the task; at least one essential per task
dependsOn START, COMPLETE, SUCCESS, HEALTHY; COMPLETE/SUCCESS not allowed on essential containers
healthCheck interval 30 s (5–300), timeout 5 s (2–60), retries 3 (1–10), startPeriod off (0–300 s) = bootstrap grace: failures inside it don't count toward retries, a pass inside it → healthy and later failures count; exit 0 = healthy 30-5-3
Timeouts stopTimeout default 30 s, max 120 s on Fargate; startTimeout max 120 s
awslogs awslogs-group + awslogs-region required; awslogs-stream-prefix required on Fargate → prefix/container-name/task-id; awslogs-create-group needs logs:CreateLogGroup
Log drivers Fargate: awslogs, awsfirelens, splunk; EC2 adds json-file, syslog, journald, gelf, fluentd
Log mode ⚠️ Default non-blocking since 2025-06-25 (max-buffer-size 10m, overflow dropped); blocking via mode or defaultLogDriverMode Don't freeze for logs
Image digests Tag resolved to a digest per deployment (versionConsistency enabled); re-pushed tag needs a new deployment Tag at deploy, digest after
Shared scratch in a task Bind mount (volumes + mountPoints/volumesFrom); Fargate ephemeral storage 20 GiB default, up to 200 GiB Bind = same task
Persistent storage EFS (shared across tasks and AZs); EBS ⚠️ (one new volume per task, configuredAtLaunch, infrastructure role, deleted with service tasks; a standalone task can keep it with deleteOnTermination: false); S3 Files (Fargate, Managed Instances; EC2 ⚠️ unverified); Docker volumes and FSx for Windows: EC2 only EFS shares, EBS per task

IAM roles

Role Used by Facts Memory hook
Task role (taskRoleArn) Your application code Trust ecs-tasks.amazonaws.com; credentials from 169.254.170.2 + AWS_CONTAINER_CREDENTIALS_RELATIVE_URI; valid 6 h, auto-rotated; CloudTrail assumed-role/<role>/<task-id> What my code may do
Task execution role (executionRoleArn) ⚠️ ECS / Fargate agent ECR pull + awslogs (Fargate, Managed Instances, external); secrets, repositoryCredentials, S3 env files (Fargate and EC2); AmazonECSTaskExecutionRolePolicy What ECS needs to start me
Container instance role ECS agent on EC2 AmazonEC2ContainerServiceforEC2Role; register, poll, submit state; trust ec2.amazonaws.com via instance profile; keep minimal What the host needs to join
Infrastructure role ECS on your behalf Trust ecs.amazonaws.com (pass with iam:PassedToService = ecs.amazonaws.com); EBS volumes, Service Connect TLS, VPC Lattice, native blue/green load balancer edits, Managed Instances, Express Mode ecs without -tasks = infrastructure
Service-linked role ECS AWSServiceRoleForECS: ENIs, target registration, scaling; created automatically
EventBridge or Scheduler role Rules and schedules ecs:RunTask + iam:PassRole (iam:PassedToService = ecs-tasks.amazonaws.com); managed AmazonEC2ContainerServiceEventsRole No pass, no run
Topic Current facts Memory hook
Trust conditions aws:SourceAccount + aws:SourceArn = arn:aws:ecs:<region>:<account>:* (a single-cluster ARN isn't supported)
Block IMDS on EC2 ECS_AWSVPC_BLOCK_IMDS=true (awsvpc); iptables drop docker+ → 169.254.169.254 (bridge); ECS_ENABLE_TASK_IAM_ROLE_NETWORK_HOST=false (host); Fargate containers get no instance profile Block the host's keys
ECS Exec Task role ssmmessages:CreateControlChannel/CreateDataChannel/OpenControlChannel/OpenDataChannel; --enable-execute-command (new tasks only); CLI + Session Manager plugin; caller ecs:ExecuteCommand; runs as root; 20-min idle timeout; no readonlyRootFilesystem; CloudTrail ExecuteCommand Exec = Session Manager in a box

Environment variables and secrets

Mechanism Current facts Memory hook
environment Plaintext in the task definition; beats the same name in env files; never for secrets
environmentFiles S3 .env objects (UTF-8, VARIABLE=VALUE, # comments); max 10 files; first file wins on duplicates; Fargate 1.4.0+ or agent 1.39.0+; no Windows; execution role s3:GetObject + s3:GetBucketLocation
Secrets Manager reference valueFrom = secret ARN[:json-key:version-stage:version-id], empty fields keep colons (…:password::); default AWSCURRENT; JSON key needs Fargate 1.4.0+ or agent 1.37.0+ Colons count
Parameter Store reference Name (same Region) or full ARN (other Region); execution role ssm:GetParameters (+ kms:Decrypt for a customer managed key) Other Region → ARN
Injection timing At container start only; rotation never reaches running tasks → update-service --force-new-deployment, or read at runtime with the SDK and the task role Start-time snapshot
Private registry login repositoryCredentials.credentialsParameter = Secrets Manager ARN; execution role secretsmanager:GetSecretValue
ResourceInitializationError unable to pull secrets or registry auth → network path (AWS's documented cause: NAT, public IP or Secrets Manager/SSM/ECR endpoints); "check whether the secret exists in the specified Region" → ARN, Region, execution-role GetSecretValue or a network timeout Network or execution role

Services, standalone tasks and load balancing

Topic Current facts Memory hook
REPLICA vs DAEMON Service field schedulingStrategy (create-service --scheduling-strategy); REPLICA default (spread across AZs); DAEMON = one task per instance, no desired count, strategy or auto scaling, not on Fargate; daemon defaults min 0 % (API), max 100 %
Grace period healthCheckGracePeriodSeconds default 0, up to 2,147,483,647 s; ignores ELB, VPC Lattice and container health checks after start Warm-up shield
Load balancers ⚠️ ALB (recommended; path/host rules; dynamic ports), NLB (TCP/UDP), GWLB (appliances); Fargate and Managed Instances → target type ip; Classic legacy (EC2, 1 per service); max 5 target groups per service
Changing the load balancer Only API, CLI or CloudFormation with the ECS controller; starts a deployment
Bridge dynamic ports Omit hostPort (or 0) → ephemeral port; instance SG allows the ephemeral range from the load balancer SG; reserved 22, 2375, 2376, 51678–51680; max 100 reserved ports per instance Instance + port
awsvpc networking Own ENI, IP, SGs; ≤ 16 subnets and ≤ 5 SGs per awsvpcConfiguration; public subnet needs assignPublicIp: ENABLED; ENI limits on EC2 (awsvpcTrunking) Task = its own IP
Standalone tasks RunTask ≤ 10 tasks per call; StartTask ≤ 10 instances; ECS never restarts them Run once, watch yourself
EventBridge launches Rule (event pattern → RunTask target) or Scheduler (rate, cron, one-time, time zones, retry policy + SQS DLQ; syntax in notes/monitoring-guide.md §6); both roles need ecs:RunTask + iam:PassRole; Scheduler retries only a failed invocation
ECS events Source aws.ecs; ECS Task State Change (lastStatus, stoppedReason, stopCode); deployment events incl. SERVICE_DEPLOYMENT_FAILED; dedupe on detail.version
Service-to-service Service Connect (Cloud Map namespace, short names, managed proxy) or Cloud Map DNS discovery (≤ 1,000 tasks per service)

Auto scaling and capacity

Topic Current facts Memory hook
Engine Application Auto Scaling; namespace ecs; dimension ecs:service:DesiredCount; resource service/<cluster>/<service>
Policy types ⚠️ Target tracking, step, scheduled, predictive; predefined ECSServiceAverageCPUUtilization, ECSServiceAverageMemoryUtilization, ALBRequestCountPerTarget, plus …CPUUtilizationHighResolution / …MemoryUtilizationHighResolution (20-second metrics, service monitoring resolutionSeconds 20)
Predictive scaling ≥ 24 h history (14 days ideal); 48-h hourly forecast refreshed every 6 h; forecast-only first; never scales in; needs the service-linked role
Queue workers Target tracking on backlog per task (visible messages ÷ running tasks) Backlog per task
During deployments Scale-in paused (except EXTERNAL controller); scale-out continues
Several policies Scale out if any policy wants to; scale in only if all agree; never edit their alarms
ASG capacity provider Managed scaling + targetCapacity %; CapacityProviderReservation (AWS/ECS/ManagedScaling) = needed ÷ running × 100; 100 % = no headroom (new tasks wait for instances; ≤ 500 tasks in PROVISIONING per cluster); from 0 launches 2 instances Lower target, more headroom
ASG rules No other scaling policies on that group; keep the AmazonECSManaged tag; creator needs autoscaling:CreateOrUpdateTags; with managed scaling one cluster per provider
Fargate capacity Nothing to scale; vCPU-based quotas limit concurrency
Container Insights Cluster setting or containerInsights account setting; task and service metrics such as RunningTaskCount; billed as custom metrics

Deployments

Topic Current facts Memory hook
Controllers ⚠️ ECS (strategies ROLLING, BLUE_GREEN, LINEAR, CANARY), CODE_DEPLOY, EXTERNAL
Rolling math minimumHealthyPercent rounded up (default 100 %); maximumPercent rounded down (default 200 %); must allow stopping or starting at least 1 task Min rounds up, max rounds down
Desired 4 examples 50/100 → 2 at a time, no extra capacity; 100/150 → +2 then −2; 100/200 → +4 then −4
What triggers a deployment New task definition revision, platform version, network or load balancer settings, --force-new-deployment; a desired-count change doesn't
Circuit breaker ⚠️ enable + rollback; rolling and native blue/green on the ECS controller (not CODE_DEPLOY/EXTERNAL); default threshold 50 % of desired (min 3, max 200); configurable COUNT/BOUNDED_PERCENT/UNBOUNDED_PERCENT and resetOnHealthyTask
Alarm rollback alarms (alarmNames, enable, rollback) on application metrics; can combine with the breaker
Native blue/green ⚠️ Since 2025-07-17; green at full size, test listener rule, all-at-once production shift, bakeTimeInMinutes required; advancedConfiguration: alternate target group, production (+ test) listener rule, roleArn Two TGs, one rule switch
Linear and canary ⚠️ Since 2025-10-30; same traffic-shifting resources as native blue/green; LINEAR steps of 3–100 % with 0–1,440 min bake between steps; CANARY = small slice, wait, then the rest
Lifecycle hooks Lambda returns hookStatus SUCCEEDED/FAILED/IN_PROGRESS within 15 min; pause hooks wait for ContinueServiceDeployment (timeout up to 14 days; not at TEST_TRAFFIC_SHIFT/PRODUCTION_TRAFFIC_SHIFT); each stage ≤ 24 h; deployment ≤ 30 days
CodeDeploy blue/green CODE_DEPLOY controller, AppSpec, ECSCanary…/ECSLinear…/ECSAllAtOnce; no circuit breaker; details in notes/cicd-guide.md §8

Task placement

Topic Current facts Memory hook
Scope ⚠️ Strategies: EC2 only; constraints: EC2 and Managed Instances (attributes ecs.subnet-id, ecs.availability-zone, ecs.instance-type, ecs.cpu-architecture); Fargate: neither (best-effort AZ spread) No placement on Fargate
Process Resources (CPU, GPU, memory, ports) → constraints → strategies → place
binpack Field cpu or memory; least remaining resource that fits → fewest instances Pack to save
spread Field instanceId/host or an attribute (attribute:ecs.availability-zone); default for services Spread to survive
random No field; no balance guarantee
Combining Order matters: spread on AZ, then binpack on memory
distinctInstance One task per instance; only at RunTask/CreateService, not in task definitions
memberOf Cluster query language expression; also allowed in task definitions; ≤ 10 constraints per task
Binding? Strategies are best effort; constraints are binding → unmatched tasks stay PENDING Strategies prefer, constraints insist
Query language ==, !=, >, <, exists, in, =~, !~, and/or/not; e.g. attribute:ecs.instance-type =~ g2.*

Amazon ECR

Topic Current facts Memory hook
Image URI <account>.dkr.ecr.<region>.amazonaws.com/<repo>:<tag> or @sha256:<digest>; layers stored in S3
Login ⚠️ aws ecr get-login-password --region <r> | docker login --username AWS --password-stdin <registry>; token valid 12 h; get-login removed in CLI v2 12-hour pass
ECR Public login aws ecr-public get-login-password --region us-east-1 → public.ecr.aws Public = us-east-1
Pull permissions ecr:GetAuthorizationToken (identity policy, "*") + ecr:BatchGetImage + ecr:GetDownloadUrlForLayer (+ ecr:BatchCheckLayerAvailability) Token + manifest + layers
Push permissions + ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:PutImage
Managed policies AmazonEC2ContainerRegistryPullOnly (2024-10-10), …ReadOnly, …PowerUser (no repo deletion or policy edits), …FullAccess
Repository policy Cross-account or service access to one repository; can't grant GetAuthorizationToken
Tag immutability ⚠️ IMMUTABLE → ImageTagAlreadyExistsException on an existing tag; exclusion filters IMMUTABLE_WITH_EXCLUSION/MUTABLE_WITH_EXCLUSION New build, new tag
Scanning ⚠️ Basic = AWS native, OS packages, on push or manual, 1 scan per image per 24 h; enhanced = Amazon Inspector, OS + language packages, continuous, EventBridge findings
Lifecycle policy ⚠️ rulePriority low first; tagStatus tagged/untagged/any (any last); imageCountMoreThan, sinceImagePushed, sinceImagePulled, sinceImageTransitioned; expire or transition → archive (archived images can't be pulled or scanned until restored); within 24 h; preview first
Replication Registry-level, cross-Region and cross-account; new pushes only; destination registry policy ecr:ReplicateImage (+ ecr:CreateRepository); repository policies not copied
Pull through cache ECR Public, Quay, Kubernetes registry (no auth); Docker Hub, GHCR, ACR, GitLab, Chainguard (secret named ecr-pullthroughcache/…, same account and Region); a pull re-checks upstream once the cache is 24 h old; first pull needs an internet route; not for Lambda Cache the upstream
Create on push ⚠️ Needs a CREATE_ON_PUSH repository creation template (no template → no repository)
Private pulls com.amazonaws.<region>.ecr.dkr + com.amazonaws.<region>.ecr.api interface endpoints + S3 gateway endpoint (+ logs for awslogs) Two ECR + one S3
Encryption AES256 default or KMS; fixed at repository creation

Amazon EKS

Topic Current facts Memory hook
When EKS Organisation standardised on Kubernetes, portability, ecosystem tools; clusters are Regional
Compute ⚠️ EKS Auto Mode (2024-12-01), managed node groups, self-managed nodes, Fargate, Hybrid Nodes
Fargate on EKS Fargate profiles (namespace + labels); private subnets only; no DaemonSets, privileged, HostPort/HostNetwork, GPUs or EBS; EFS static provisioning; ip targets; no Fargate Spot; no IMDS
Pod Identity ⚠️ Trust pods.eks.amazonaws.com (sts:AssumeRole, sts:TagSession); aws eks create-pod-identity-association; no OIDC provider or annotation; session tags; ≤ 5,000 per cluster; Linux EC2 nodes only Pod Identity for EC2 pods
IRSA OIDC provider per cluster (100 per account by default); sts:AssumeRoleWithWebIdentity; annotation eks.amazonaws.com/role-arn; works on Fargate IRSA for Fargate pods
Node role For kubelet and node agents; pods can reach it through IMDS → no application permissions
Cluster access ⚠️ aws eks update-kubeconfig --region <r> --name <cluster> (needs eks:DescribeCluster); authorization from access entries; aws-auth ConfigMap is legacy Kubeconfig connects, access entry authorizes
Storage ⚠️ EBS CSI (one AZ, one node, not Fargate), EFS CSI (shared, Fargate, also S3 Files), FSx for Lustre/ONTAP/OpenZFS, File Cache, Mountpoint for S3, instance store
Load balancing AWS Load Balancer Controller: ALB for Ingress, NLB for LoadBalancer services

Numbers to know

Item Value Note
Containers per task definition 10 Not adjustable
Task definition size 64 KiB
Revisions per task definition family 1,000,000 Deregistered or deleted revisions still count
Clusters per account (per Region) 10,000 Adjustable
Services per cluster · tasks per service · container instances per cluster 5,000 each Cloud Map discovery caps a service at 1,000 tasks
Tasks per RunTask call 10 StartTask: 10 container instances
Target groups per service 5 ALB or NLB; Classic Load Balancers: 1
Capacity providers per strategy or per cluster 20
Subnets / security groups per awsvpcConfiguration 16 / 5
Placement constraints per task 10 Task definition + run time combined
Placement strategy rules per service 5 ⚠️ unverified CreateService API says 5, the service-definition page says 4
Fargate task size 0.25 vCPU + 512 MiB up to 16 vCPU + 120 GB; 32 vCPU + 244 GB ⚠️ 32 vCPU: Linux, platform 1.4.0
Fargate ephemeral storage 20 GiB default, 200 GiB max Platform 1.4.0+ (ephemeralStorage)
stopTimeout on Fargate 30 s default, 120 s max Grace between SIGTERM and SIGKILL
Fargate Spot interruption warning 2 minutes Event + SIGTERM
Fargate retirement wait 7 days default 0, 7 or 14 days (fargateTaskRetirementWaitPeriod)
ECS Managed Instances lifetime 14 days Then drained for patching
Task role credentials 6 hours Rotated automatically
Container health check defaults 30 s interval, 5 s timeout, 3 retries startPeriod 0–300 s, off by default
healthCheckGracePeriodSeconds 0 default, max 2,147,483,647 Seconds
Rolling defaults (replica service) min 100 %, max 200 % Daemon: min 0 % (API), max 100 %
Circuit breaker default threshold 50 % of desired count, min 3, max 200 Configurable ⚠️
Lifecycle hook Lambda response Within 15 minutes Each stage up to 24 h
Reserved host ports per container instance 100 Defaults 22, 2375, 2376, 51678–51680
Dynamic host port fallback range (Linux) 49153–65535 Normally read from ip_local_port_range
CPU units 1,024 per vCPU (per core on EC2)
Environment files per task definition 10 .env, UTF-8
Non-blocking log buffer (max-buffer-size) 10m Default mode since 2025-06-25 ⚠️
ECS Exec idle timeout 20 minutes Fixed; 1,000 sessions per container
Predictive scaling history ≥ 24 hours (14 days ideal) 48-hour forecast, refreshed every 6 h
ECR authorization token 12 hours Per IAM principal
ECR images per repository · repositories per Region 100,000 each Adjustable
ECR lifecycle policy 50 rules, 30,720 characters Acts within 24 h
ECR basic scans 1 per image per 24 h 100,000 per 24 h per Region
ECR maximum layer size 52,000 MiB API layer parts 5–10 MiB
ECR archive restore Typically within 20 minutes ⚠️ new storage class; re-push restores at once
ECR replication 25 rules, 25 destinations Most images within 30 minutes
ECR pull through cache 50 rules per registry A pull re-checks upstream after 24 h
EKS Pod Identity associations 5,000 per cluster
IAM OIDC providers (IRSA) 100 per account by default One per EKS cluster

Decision rules

Memory hooks