Skip to content

Latest commit

 

History

History
353 lines (274 loc) · 10.6 KB

File metadata and controls

353 lines (274 loc) · 10.6 KB

ECS, ECR & EKS — Container Services

What Is It?

ECS (Elastic Container Service) is AWS's managed Docker container orchestration. ECR (Elastic Container Registry) is the private Docker registry. Together they let you run containers without managing Kubernetes.

Real-World: Your Node.js microservices run in Docker containers. ECR stores the images. ECS runs them, auto-scales them, and health-checks them. No Kubernetes expertise required.


ECS Core Concepts

ECS Cluster
├── Service: checkout-service (maintains 3 running tasks)
│   ├── Task: checkout-task-abc (running: container checkout:v2)
│   ├── Task: checkout-task-def (running: container checkout:v2)
│   └── Task: checkout-task-ghi (running: container checkout:v2)
└── Service: payment-service (maintains 2 running tasks)
    ├── Task: payment-task-xyz
    └── Task: payment-task-uvw
  • Cluster: logical grouping of compute resources
  • Task Definition: blueprint for a container (image, CPU, memory, ports, env vars, IAM role)
  • Task: running instance of a task definition
  • Service: maintains N running tasks, handles health checks and restarts

Launch Types: EC2 vs Fargate

Feature EC2 Launch Type Fargate
Infrastructure You manage EC2 instances AWS manages infrastructure
Pricing Pay for EC2 hours (even when idle) Pay per vCPU + memory per second
Control Full OS access, custom AMIs No OS access
Scaling Must scale EC2 capacity + containers Just scale containers
Use when Cost optimization at scale, GPU, specific AMIs Simplicity, small teams, variable load

Rule: Start with Fargate (simpler). Move to EC2 if cost becomes significant at large scale.


Task Definition

{
  "family": "checkout-service",
  "networkMode": "awsvpc",       // Required for Fargate
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",                  // 0.25 vCPU
  "memory": "512",               // 512MB
  "executionRoleArn": "arn:aws:iam::123:role/ecsTaskExecutionRole",
  "taskRoleArn": "arn:aws:iam::123:role/checkoutTaskRole",
  "containerDefinitions": [
    {
      "name": "checkout",
      "image": "123456789.dkr.ecr.us-east-1.amazonaws.com/checkout:v2.1",
      "portMappings": [{"containerPort": 8080}],
      "environment": [
        {"name": "NODE_ENV", "value": "production"}
      ],
      "secrets": [
        {
          "name": "DB_PASSWORD",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:123:secret:prod/db"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/checkout",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "checkout"
        }
      },
      "healthCheck": {
        "command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
        "interval": 30,
        "timeout": 5,
        "retries": 3
      }
    }
  ]
}

Two IAM Roles in Task Definition

Role Purpose
Execution Role ECS agent permissions — pull ECR image, write CloudWatch logs, get Secrets Manager secrets
Task Role Application permissions — what your code can call (DynamoDB, S3, SQS, etc.)
Execution Role → needs:
  ecr:GetAuthorizationToken
  ecr:BatchGetImage
  logs:CreateLogStream
  logs:PutLogEvents
  secretsmanager:GetSecretValue (if using secrets)

Task Role → needs whatever your app does:
  dynamodb:Query
  s3:GetObject
  sqs:SendMessage

Networking Modes

Mode Description Use with
awsvpc Each task gets its own ENI + IP Fargate (required), EC2 (recommended)
bridge Docker bridge network (NAT) EC2 only, legacy
host Container uses EC2's network interface EC2 only, high performance
none No network EC2 only, isolated tasks

Fargate always uses awsvpc — each task has its own private IP in your VPC.


ECS Service Auto Scaling

Scale tasks based on metrics:

Scaling Policy: Target Tracking
Metric: ECS Service Average CPU Utilization = 70%
Min Tasks: 2
Max Tasks: 20

→ ECS automatically adjusts task count to maintain 70% CPU

Scale-out trigger: CPU > 70% for 3 minutes → add tasks Scale-in trigger: CPU < 70% for 15 minutes → remove tasks

For EC2 launch type: also need to scale the EC2 instances (use Capacity Provider + ASG).


ECS Service Discovery

How do services find each other?

checkout-service → calls payment-service.prod.local:8080

Route 53 Auto Naming Service maintains DNS:
payment-service.prod.local → [10.0.1.5, 10.0.1.6, 10.0.1.7]
Updates automatically when tasks start/stop

Load Balancer Integration

Internet → ALB → Target Group → ECS Service Tasks

For awsvpc mode: each task registers directly with ALB target group (different port fine because different IP).

For bridge mode: ALB uses dynamic port mapping (host port randomized).


ECS Blue/Green Deployment (with CodeDeploy)

Current (Blue): Service running v1 tasks behind ALB
New (Green): CodeDeploy creates new task set with v2

ALB test traffic on port 8080 → validate green
Shift production traffic → green becomes production
Terminate blue

All configured in CodeDeploy appspec.yaml:

version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: "arn:aws:ecs:us-east-1:123:task-definition/checkout:5"
        LoadBalancerInfo:
          ContainerName: checkout
          ContainerPort: 8080

ECR — Elastic Container Registry

Basic Operations

# Authenticate Docker to ECR
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin \
  123456789.dkr.ecr.us-east-1.amazonaws.com

# Create repository
aws ecr create-repository --repository-name checkout

# Tag and push image
docker build -t checkout:v2 .
docker tag checkout:v2 123456789.dkr.ecr.us-east-1.amazonaws.com/checkout:v2
docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/checkout:v2

# Pull image
docker pull 123456789.dkr.ecr.us-east-1.amazonaws.com/checkout:v2

ECR Lifecycle Policies

{
  "rules": [
    {
      "rulePriority": 1,
      "description": "Keep only last 10 production images",
      "selection": {
        "tagStatus": "tagged",
        "tagPrefixList": ["prod"],
        "countType": "imageCountMoreThan",
        "countNumber": 10
      },
      "action": {"type": "expire"}
    },
    {
      "rulePriority": 2,
      "description": "Delete untagged images after 1 day",
      "selection": {
        "tagStatus": "untagged",
        "countType": "sinceImagePushed",
        "countUnit": "days",
        "countNumber": 1
      },
      "action": {"type": "expire"}
    }
  ]
}

ECR Image Scanning

# Enable scan on push
aws ecr put-image-scanning-configuration \
  --repository-name checkout \
  --image-scanning-configuration scanOnPush=true

Scans for CVEs (Common Vulnerabilities and Exposures). Results in Console/EventBridge.

Cross-Account ECR Access

// ECR Repository Policy (Account A)
{
  "Effect": "Allow",
  "Principal": {"AWS": "arn:aws:iam::ACCOUNT_B:root"},
  "Action": [
    "ecr:GetDownloadUrlForLayer",
    "ecr:BatchGetImage"
  ]
}

EKS — Elastic Kubernetes Service

AWS manages the Kubernetes control plane. You manage (or Fargate manages) worker nodes.

When to use EKS over ECS:

  • Team already knows Kubernetes
  • Need Kubernetes ecosystem (Helm, Istio, operators)
  • Multi-cloud portability
  • Advanced networking (service mesh)

EKS Fargate: Kubernetes pods run on Fargate (no nodes to manage).

EKS Cluster
├── Control plane (managed by AWS)
└── Worker nodes
    ├── Option A: EC2 managed node groups
    └── Option B: Fargate profiles (pods → Fargate automatically)

Good Practices

Practice Reason
Use Fargate for new workloads No infrastructure management
Separate Execution Role from Task Role Least privilege
Use ECR lifecycle policies Prevent image storage explosion
Enable container health checks ECS replaces unhealthy containers
Use awsvpc networking Each task gets own IP, simpler security groups
Use Secrets Manager for secrets in task def Secure, rotatable
Enable ECR image scanning Catch vulnerabilities before deploy
Pin image tags (use SHA digest) Avoid latest tag in production

Bad Practices

Anti-Pattern Impact Fix
Running as root inside container Security risk Use USER directive in Dockerfile
Using latest tag in production Unpredictable deploys Pin to specific version tag or SHA
Not setting resource limits Container uses all host resources Set CPU and memory limits in task definition
Storing secrets in environment variables (hardcoded) Visible in task definition Use secrets with Secrets Manager ARN
No health check Unhealthy container keeps receiving traffic Add healthCheck to container definition

Exam Tips

  1. Execution Role = ECS agent pulling image/logs. Task Role = application code calling AWS APIs.
  2. Fargate requires awsvpc network mode — no choice.
  3. ECS on EC2 requires ECS Agent running on each instance.
  4. ECR authentication token expires after 12 hours — refresh before long-running builds.
  5. ECS + CodeDeploy Blue/Green = AppSpec + two target groups in ALB.
  6. ECS Service Auto Scaling is separate from EC2 ASG (if using EC2 launch type, need both).
  7. ECS Exec: SSH into running containers for debugging: aws ecs execute-command.
  8. Capacity Provider: links ECS to an ASG, manages EC2 scaling automatically.

Common Exam Scenarios

Q: Container needs to read from S3 — how to give it permissions? → Add an IAM Task Role to the task definition with S3 permissions.

Q: Secrets Manager secret in ECS container environment? → Use secrets array in task definition with valueFrom pointing to Secrets Manager ARN. Requires permissions in Execution Role.

Q: Zero-downtime deployment for ECS service?CodeDeploy Blue/Green with ECS or configure rolling update in ECS service.

Q: ECS task failing health checks — where to look? → Check CloudWatch Logs (if awslogs configured), or use ECS Exec for interactive debugging.

Q: Run a container once (batch job) not a long-running service? → Use ECS Task (not Service) — invoke as a standalone task, perhaps triggered by EventBridge.