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
- If you see "run containers with the LEAST operational overhead" and no special hardware, think AWS Fargate.
- If you see GPUs or specific instance types but "don't want to patch or scale instances", think ECS Managed Instances.
- If you see custom AMIs, host-level daemons or Capacity Reservations, think self-managed EC2 capacity.
- If you see "mostly Spot to save money, but keep a guaranteed minimum", think a
FARGATEbase plusFARGATE_SPOTweight in one capacity provider strategy. - If you see AWS Copilot in a new design, think ECS Express Mode or the AWS CDK.
- If you see
OutOfMemoryError: container killed due to memory usage, think raise the container's hardmemorylimit. - If you see files shared by containers of one task, think bind mount; durable files shared by many tasks → EFS; high-IOPS block storage per task → EBS.
- If you see a helper container whose exit stops the task, think
essential: falseplusdependsOn. - If you see
AccessDeniedfrom application code in a task, think task role. - If you see image pull,
awslogsorsecretsfailures, think task execution role. - If you see containers on EC2 using the instance role's permissions, think block IMDS for tasks and use task roles.
- If you see "shell into a running Fargate container without SSH", think ECS Exec.
- If you see a rotated secret that running tasks don't pick up, think
update-service --force-new-deployment. - If you see
unable to pull secrets or registry authin private subnets, think Secrets Manager or SSM endpoints plus execution-role permissions. - If you see several tasks per EC2 instance behind an ALB, think
bridgemode with dynamic host ports and the ephemeral range opened from the load balancer. - If you see Fargate or
awsvpctasks behind a load balancer, think target typeip. - If you see slow-starting tasks killed by health checks, think
healthCheckGracePeriodSeconds. - If you see "run a container on a schedule or on an event", think EventBridge Scheduler or an EventBridge rule with
ecs:RunTaskandiam:PassRole. - If you see a queue worker that must keep its backlog under control, think target tracking on backlog per task.
- If you see EC2 tasks waiting because instances are full, think an Auto Scaling group capacity provider with managed scaling.
- If you see "deploy without any extra capacity", think
maximumPercent100 withminimumHealthyPercentbelow 100. - If you see "roll back automatically when new tasks fail", think the deployment circuit breaker with
rollback; metric regressions → deployment alarms. - If you see blue/green with test traffic and a bake period but no CodeDeploy, think
strategyBLUE_GREENwith an alternate target group. - If you see gradual percentage-based traffic shifting on ECS without CodeDeploy, think the
LINEARorCANARYstrategy. - If you see "use the fewest instances", think
binpack; "survive an AZ failure", thinkspreadon Availability Zone first. - If you see "one task per instance", think
distinctInstance; "only on a given instance type", thinkmemberOf. - If you see
ImageTagAlreadyExistsException, think push a unique tag per build. - If you see "keep only the newest N images" or "clean up untagged images", think an ECR lifecycle policy.
- If you see Fargate in private subnets failing to pull from ECR, think
ecr.dkr+ecr.apiendpoints plus an S3 gateway endpoint. - If you see EKS pods needing AWS permissions, think EKS Pod Identity on EC2 nodes and IRSA on Fargate.
Memory hooks
- Blueprint (task definition) → copy (task) → keeper (service).
- Fargate: no servers to babysit; Managed Instances: EC2 power, AWS chores; EC2: you own the patching.
- Base first, weights after; through the API a provider without a weight gets nothing.
- Two minutes to pack: Fargate Spot sends
SIGTERM, thenSIGKILLafterstopTimeout. - Edit means new revision: task definitions never change in place.
- Hard limit kills, soft limit reserves.
- Health check 30-5-3: every 30 s, 5 s to answer, 3 strikes.
- Task role = what my code may do; execution role = what ECS needs to start me; instance role = what the host needs to join.
- No pass, no run: whoever starts tasks with roles needs
iam:PassRole. - Exec = Session Manager in a box: task role
ssmmessages, plugin, new tasks. - Secrets are a start-time snapshot: rotate, then redeploy.
- Colons count:
…:json-key:stage:id, keep the empty ones. - Fargate behind an ALB =
iptargets; bridge on EC2 = instance plus dynamic port. - Grace period = warm-up shield, not a weaker health check.
- Services scale tasks; capacity providers scale instances.
- Backlog per task keeps queue workers honest.
- Min rounds up, max rounds down.
- ECS blue/green: two target groups, one listener-rule switch, bake before clean-up.
- Pack to save, spread to survive.
- Strategies prefer, constraints insist.
- 12-hour pass:
get-login-passwordat the start of every push job. - Immutable tags: every build gets a new name.
- Private pull = two ECR endpoints + one S3 gateway.
- Pod Identity for EC2 pods, IRSA for Fargate pods.
- Copilot has landed: Express Mode or CDK for new apps.