Skip to main content
ECS vs EKS Comparison

Module Overview

Estimated Time: 5-6 hours | Difficulty: Advanced | Prerequisites: Compute, Networking, DevOps
Containers are the foundation of modern cloud-native applications. This module provides deep coverage of container orchestration on AWS. What You’ll Learn:
  • ECS architecture and task definitions
  • EKS cluster management and best practices
  • Fargate vs EC2 launch types
  • Service mesh with App Mesh
  • Container security and image management
  • Microservices design patterns

Container Services Overview

┌────────────────────────────────────────────────────────────────────────┐
│                    AWS Container Services                               │
├────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   ORCHESTRATION                                                         │
│   ─────────────                                                         │
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐  │
│   │                                                                  │  │
│   │   ECS (Elastic Container Service)   │  EKS (Kubernetes)         │  │
│   │   ───────────────────────────────   │  ─────────────────        │  │
│   │   • AWS-native orchestration        │  • Managed Kubernetes     │  │
│   │   • Simpler, integrated             │  • Portable, CNCF         │  │
│   │   • No cluster management           │  • Rich ecosystem         │  │
│   │   • Task definitions                │  • Pods, Deployments      │  │
│   │                                     │                            │  │
│   └─────────────────────────────────────────────────────────────────┘  │
│                                                                         │
│   COMPUTE (Launch Types)                                                │
│   ──────────────────────                                                │
│                                                                         │
│   ┌──────────────────────┐          ┌──────────────────────┐          │
│   │      EC2 Launch      │          │   Fargate Launch     │          │
│   │      ───────────     │          │   ─────────────      │          │
│   │  • You manage EC2    │          │  • Serverless        │          │
│   │  • Full control      │          │  • No infra mgmt     │          │
│   │  • Spot instances    │          │  • Per-task pricing  │          │
│   │  • GPU support       │          │  • Fargate Spot      │          │
│   │  • Lower cost at     │          │  • Best for:         │          │
│   │    scale             │          │    variable load     │          │
│   └──────────────────────┘          └──────────────────────┘          │
│                                                                         │
│   SUPPORTING SERVICES                                                   │
│   ───────────────────                                                   │
│   • ECR: Container registry                                            │
│   • App Mesh: Service mesh                                             │
│   • Cloud Map: Service discovery                                       │
│   • App Runner: Simplified containers                                  │
│                                                                         │
└────────────────────────────────────────────────────────────────────────┘

ECS Deep Dive

ECS Architecture

┌────────────────────────────────────────────────────────────────────────┐
│                    ECS Architecture                                     │
├────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   ┌──────────────────────────────────────────────────────────────────┐ │
│   │                         ECS CLUSTER                               │ │
│   │                                                                   │ │
│   │  ┌─────────────────────────────────────────────────────────────┐ │ │
│   │  │                      ECS SERVICE                             │ │ │
│   │  │                                                              │ │ │
│   │  │  Desired Count: 3    │  Load Balancer: ALB                  │ │ │
│   │  │  Min/Max: 2/10       │  Auto Scaling: Target Tracking       │ │ │
│   │  │                                                              │ │ │
│   │  │  ┌────────────┐  ┌────────────┐  ┌────────────┐            │ │ │
│   │  │  │   TASK 1   │  │   TASK 2   │  │   TASK 3   │            │ │ │
│   │  │  │            │  │            │  │            │            │ │ │
│   │  │  │┌──────────┐│  │┌──────────┐│  │┌──────────┐│            │ │ │
│   │  │  ││Container ││  ││Container ││  ││Container ││            │ │ │
│   │  │  ││   App    ││  ││   App    ││  ││   App    ││            │ │ │
│   │  │  │└──────────┘│  │└──────────┘│  │└──────────┘│            │ │ │
│   │  │  │┌──────────┐│  │┌──────────┐│  │┌──────────┐│            │ │ │
│   │  │  ││Container ││  ││Container ││  ││Container ││            │ │ │
│   │  │  ││  Sidecar ││  ││  Sidecar ││  ││  Sidecar ││            │ │ │
│   │  │  │└──────────┘│  │└──────────┘│  │└──────────┘│            │ │ │
│   │  │  └────────────┘  └────────────┘  └────────────┘            │ │ │
│   │  │                                                              │ │ │
│   │  └─────────────────────────────────────────────────────────────┘ │ │
│   │                                                                   │ │
│   │  CAPACITY PROVIDERS:                                              │ │
│   │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐           │ │
│   │  │   FARGATE    │  │ FARGATE_SPOT │  │     EC2      │           │ │
│   │  │    (70%)     │  │    (20%)     │  │    (10%)     │           │ │
│   │  └──────────────┘  └──────────────┘  └──────────────┘           │ │
│   │                                                                   │ │
│   └──────────────────────────────────────────────────────────────────┘ │
│                                                                         │
│   KEY CONCEPTS:                                                         │
│   • Cluster: Logical grouping of services                              │
│   • Service: Maintains desired count of tasks                          │
│   • Task: Running instance of task definition                          │
│   • Task Definition: Blueprint (containers, resources, IAM)            │
│   • Container: Docker container within a task                          │
│                                                                         │
└────────────────────────────────────────────────────────────────────────┘

ECS Task Definition

{
  "family": "my-app",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "1024",
  "memory": "2048",
  "executionRoleArn": "arn:aws:iam::123456789:role/ecsTaskExecutionRole",
  "taskRoleArn": "arn:aws:iam::123456789:role/ecsTaskRole",
  
  "containerDefinitions": [
    {
      "name": "app",
      "image": "123456789.dkr.ecr.us-east-1.amazonaws.com/my-app:latest",
      "essential": true,
      "portMappings": [
        {
          "containerPort": 8080,
          "protocol": "tcp"
        }
      ],
      "environment": [
        { "name": "NODE_ENV", "value": "production" }
      ],
      "secrets": [
        {
          "name": "DB_PASSWORD",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789:secret:db-password"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/my-app",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "app"
        }
      },
      "healthCheck": {
        "command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
        "interval": 30,
        "timeout": 5,
        "retries": 3,
        "startPeriod": 60
      },
      "dependsOn": [
        {
          "containerName": "envoy",
          "condition": "HEALTHY"
        }
      ]
    },
    {
      "name": "envoy",
      "image": "envoyproxy/envoy:v1.25.0",
      "essential": true,
      "user": "1337",
      "portMappings": [
        { "containerPort": 9901 },
        { "containerPort": 15000 },
        { "containerPort": 15001 }
      ],
      "environment": [
        { "name": "APPMESH_VIRTUAL_NODE_NAME", "value": "mesh/my-mesh/virtualNode/my-app-node" }
      ],
      "healthCheck": {
        "command": ["CMD-SHELL", "curl -s http://localhost:9901/server_info | grep state | grep -q LIVE"],
        "interval": 5,
        "timeout": 2,
        "retries": 3
      }
    },
    {
      "name": "xray-daemon",
      "image": "amazon/aws-xray-daemon",
      "essential": false,
      "cpu": 32,
      "memory": 256,
      "portMappings": [
        { "containerPort": 2000, "protocol": "udp" }
      ]
    }
  ],
  
  "proxyConfiguration": {
    "type": "APPMESH",
    "containerName": "envoy",
    "properties": [
      { "name": "IgnoredUID", "value": "1337" },
      { "name": "ProxyIngressPort", "value": "15000" },
      { "name": "ProxyEgressPort", "value": "15001" },
      { "name": "AppPorts", "value": "8080" },
      { "name": "EgressIgnoredIPs", "value": "169.254.170.2,169.254.169.254" }
    ]
  }
}

ECS Service with Terraform

resource "aws_ecs_cluster" "main" {
  name = "production"

  setting {
    name  = "containerInsights"
    value = "enabled"
  }

  configuration {
    execute_command_configuration {
      kms_key_id = aws_kms_key.ecs.arn
      logging    = "OVERRIDE"

      log_configuration {
        cloud_watch_log_group_name = aws_cloudwatch_log_group.ecs_exec.name
      }
    }
  }
}

resource "aws_ecs_cluster_capacity_providers" "main" {
  cluster_name = aws_ecs_cluster.main.name

  capacity_providers = ["FARGATE", "FARGATE_SPOT"]

  default_capacity_provider_strategy {
    base              = 1
    weight            = 70
    capacity_provider = "FARGATE"
  }

  default_capacity_provider_strategy {
    weight            = 30
    capacity_provider = "FARGATE_SPOT"
  }
}

resource "aws_ecs_service" "app" {
  name            = "my-app"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.app.arn
  desired_count   = 3

  # Deployment configuration
  deployment_minimum_healthy_percent = 100
  deployment_maximum_percent         = 200

  deployment_circuit_breaker {
    enable   = true
    rollback = true
  }

  # Capacity provider strategy
  capacity_provider_strategy {
    capacity_provider = "FARGATE"
    weight            = 70
    base              = 1
  }

  capacity_provider_strategy {
    capacity_provider = "FARGATE_SPOT"
    weight            = 30
  }

  # Networking
  network_configuration {
    subnets          = aws_subnet.private[*].id
    security_groups  = [aws_security_group.app.id]
    assign_public_ip = false
  }

  # Load balancer
  load_balancer {
    target_group_arn = aws_lb_target_group.app.arn
    container_name   = "app"
    container_port   = 8080
  }

  # Service discovery
  service_registries {
    registry_arn   = aws_service_discovery_service.app.arn
    container_name = "app"
  }

  # Enable ECS Exec for debugging
  enable_execute_command = true

  # Propagate tags from service
  propagate_tags = "SERVICE"

  lifecycle {
    ignore_changes = [desired_count]
  }
}

# Auto Scaling
resource "aws_appautoscaling_target" "ecs" {
  max_capacity       = 20
  min_capacity       = 3
  resource_id        = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.app.name}"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
}

resource "aws_appautoscaling_policy" "cpu" {
  name               = "cpu-scaling"
  policy_type        = "TargetTrackingScaling"
  resource_id        = aws_appautoscaling_target.ecs.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs.scalable_dimension
  service_namespace  = aws_appautoscaling_target.ecs.service_namespace

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ECSServiceAverageCPUUtilization"
    }
    target_value       = 70
    scale_in_cooldown  = 300
    scale_out_cooldown = 60
  }
}

resource "aws_appautoscaling_policy" "requests" {
  name               = "request-scaling"
  policy_type        = "TargetTrackingScaling"
  resource_id        = aws_appautoscaling_target.ecs.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs.scalable_dimension
  service_namespace  = aws_appautoscaling_target.ecs.service_namespace

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ALBRequestCountPerTarget"
      resource_label         = "${aws_lb.main.arn_suffix}/${aws_lb_target_group.app.arn_suffix}"
    }
    target_value       = 1000
    scale_in_cooldown  = 300
    scale_out_cooldown = 60
  }
}

EKS Deep Dive

EKS Architecture

┌────────────────────────────────────────────────────────────────────────┐
│                    EKS Architecture                                     │
├────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐  │
│   │                     AWS MANAGED                                  │  │
│   │   ┌───────────────────────────────────────────────────────────┐ │  │
│   │   │                  EKS Control Plane                         │ │  │
│   │   │                                                            │ │  │
│   │   │  ┌──────────┐  ┌──────────┐  ┌──────────┐               │ │  │
│   │   │  │API Server│  │  etcd    │  │Controller│               │ │  │
│   │   │  │  (HA)    │  │  (HA)    │  │ Manager  │               │ │  │
│   │   │  └──────────┘  └──────────┘  └──────────┘               │ │  │
│   │   │                                                            │ │  │
│   │   └───────────────────────────────────────────────────────────┘ │  │
│   └─────────────────────────────────────────────────────────────────┘  │
│                              │                                          │
│                              │ kubectl / API                            │
│                              ▼                                          │
│   ┌─────────────────────────────────────────────────────────────────┐  │
│   │                    CUSTOMER MANAGED                              │  │
│   │                                                                  │  │
│   │  ┌────────────────┐  ┌────────────────┐  ┌────────────────┐    │  │
│   │  │ Node Group 1   │  │ Node Group 2   │  │ Fargate Profile │    │  │
│   │  │ (On-Demand)    │  │ (Spot)         │  │ (Serverless)    │    │  │
│   │  │                │  │                │  │                 │    │  │
│   │  │ ┌────────────┐ │  │ ┌────────────┐ │  │                 │    │  │
│   │  │ │ Worker Node│ │  │ │ Worker Node│ │  │   ┌─────────┐   │    │  │
│   │  │ │ ┌────────┐ │ │  │ │ ┌────────┐ │ │  │   │Micro-VM │   │    │  │
│   │  │ │ │  Pod   │ │ │  │ │ │  Pod   │ │ │  │   │ (Pod)   │   │    │  │
│   │  │ │ └────────┘ │ │  │ │ └────────┘ │ │  │   └─────────┘   │    │  │
│   │  │ │ ┌────────┐ │ │  │ │ ┌────────┐ │ │  │                 │    │  │
│   │  │ │ │  Pod   │ │ │  │ │ │  Pod   │ │ │  │                 │    │  │
│   │  │ │ └────────┘ │ │  │ │ └────────┘ │ │  │                 │    │  │
│   │  │ └────────────┘ │  │ └────────────┘ │  │                 │    │  │
│   │  └────────────────┘  └────────────────┘  └────────────────┘    │  │
│   │                                                                  │  │
│   │  ADD-ONS:                                                        │  │
│   │  • VPC CNI (networking)       • CoreDNS                         │  │
│   │  • kube-proxy                 • AWS Load Balancer Controller    │  │
│   │  • EBS CSI Driver             • Cluster Autoscaler / Karpenter  │  │
│   │                                                                  │  │
│   └─────────────────────────────────────────────────────────────────┘  │
│                                                                         │
└────────────────────────────────────────────────────────────────────────┘

EKS with Terraform

module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 19.0"

  cluster_name    = "production"
  cluster_version = "1.28"

  vpc_id                   = module.vpc.vpc_id
  subnet_ids               = module.vpc.private_subnets
  control_plane_subnet_ids = module.vpc.private_subnets

  # Public endpoint with private access
  cluster_endpoint_public_access  = true
  cluster_endpoint_private_access = true

  # Add-ons
  cluster_addons = {
    coredns = {
      most_recent = true
    }
    kube-proxy = {
      most_recent = true
    }
    vpc-cni = {
      most_recent              = true
      before_compute           = true
      service_account_role_arn = module.vpc_cni_irsa.iam_role_arn
      configuration_values = jsonencode({
        env = {
          ENABLE_PREFIX_DELEGATION = "true"
          WARM_PREFIX_TARGET       = "1"
        }
      })
    }
    aws-ebs-csi-driver = {
      most_recent              = true
      service_account_role_arn = module.ebs_csi_irsa.iam_role_arn
    }
  }

  # Managed Node Groups
  eks_managed_node_groups = {
    # General purpose (on-demand)
    general = {
      name = "general-ng"

      instance_types = ["m6i.large", "m5.large"]
      capacity_type  = "ON_DEMAND"

      min_size     = 3
      max_size     = 10
      desired_size = 3

      labels = {
        workload = "general"
      }

      taints = []

      update_config = {
        max_unavailable_percentage = 33
      }
    }

    # Spot instances for non-critical
    spot = {
      name = "spot-ng"

      instance_types = ["m6i.large", "m5.large", "m6a.large", "m5a.large"]
      capacity_type  = "SPOT"

      min_size     = 0
      max_size     = 20
      desired_size = 2

      labels = {
        workload = "spot"
      }

      taints = [
        {
          key    = "spot"
          value  = "true"
          effect = "NO_SCHEDULE"
        }
      ]
    }

    # GPU nodes for ML
    gpu = {
      name = "gpu-ng"

      instance_types = ["g4dn.xlarge"]
      capacity_type  = "ON_DEMAND"

      min_size     = 0
      max_size     = 4
      desired_size = 0

      ami_type = "AL2_x86_64_GPU"

      labels = {
        workload = "gpu"
      }

      taints = [
        {
          key    = "nvidia.com/gpu"
          value  = "true"
          effect = "NO_SCHEDULE"
        }
      ]
    }
  }

  # Fargate Profiles
  fargate_profiles = {
    default = {
      name = "default"
      selectors = [
        {
          namespace = "kube-system"
          labels = {
            k8s-app = "kube-dns"
          }
        },
        {
          namespace = "fargate"
        }
      ]
    }
  }

  # IRSA for aws-load-balancer-controller
  enable_irsa = true

  # Cluster access
  manage_aws_auth_configmap = true

  aws_auth_roles = [
    {
      rolearn  = "arn:aws:iam::123456789:role/AdminRole"
      username = "admin"
      groups   = ["system:masters"]
    }
  ]

  aws_auth_users = [
    {
      userarn  = "arn:aws:iam::123456789:user/developer"
      username = "developer"
      groups   = ["system:masters"]
    }
  ]
}

# Install AWS Load Balancer Controller
resource "helm_release" "aws_load_balancer_controller" {
  name       = "aws-load-balancer-controller"
  repository = "https://aws.github.io/eks-charts"
  chart      = "aws-load-balancer-controller"
  namespace  = "kube-system"

  set {
    name  = "clusterName"
    value = module.eks.cluster_name
  }

  set {
    name  = "serviceAccount.create"
    value = "true"
  }

  set {
    name  = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
    value = module.load_balancer_controller_irsa.iam_role_arn
  }
}

Service Mesh (App Mesh)

┌────────────────────────────────────────────────────────────────────────┐
│                    App Mesh Architecture                                │
├────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐  │
│   │                        APP MESH                                  │  │
│   │                                                                  │  │
│   │                    ┌──────────────────┐                         │  │
│   │                    │  Virtual Gateway  │                         │  │
│   │                    │  (Ingress)        │                         │  │
│   │                    └────────┬─────────┘                         │  │
│   │                             │                                    │  │
│   │            ┌────────────────┼────────────────┐                  │  │
│   │            ▼                ▼                ▼                  │  │
│   │   ┌────────────────┐ ┌────────────────┐ ┌────────────────┐     │  │
│   │   │Virtual Service │ │Virtual Service │ │Virtual Service │     │  │
│   │   │   (frontend)   │ │   (api)        │ │   (database)   │     │  │
│   │   └───────┬────────┘ └───────┬────────┘ └───────┬────────┘     │  │
│   │           │                  │                  │               │  │
│   │           ▼                  ▼                  ▼               │  │
│   │   ┌────────────────┐ ┌────────────────┐ ┌────────────────┐     │  │
│   │   │ Virtual Node   │ │ Virtual Node   │ │ Virtual Node   │     │  │
│   │   │  ┌──────────┐  │ │  ┌──────────┐  │ │  ┌──────────┐  │     │  │
│   │   │  │  Envoy   │  │ │  │  Envoy   │  │ │  │  Envoy   │  │     │  │
│   │   │  └────┬─────┘  │ │  └────┬─────┘  │ │  └────┬─────┘  │     │  │
│   │   │       │        │ │       │        │ │       │        │     │  │
│   │   │  ┌────▼─────┐  │ │  ┌────▼─────┐  │ │  ┌────▼─────┐  │     │  │
│   │   │  │   App    │  │ │  │   App    │  │ │  │   App    │  │     │  │
│   │   │  └──────────┘  │ │  └──────────┘  │ │  └──────────┘  │     │  │
│   │   └────────────────┘ └────────────────┘ └────────────────┘     │  │
│   │                                                                  │  │
│   │   FEATURES:                                                      │  │
│   │   • Traffic routing (canary, blue/green)                        │  │
│   │   • mTLS encryption                                              │  │
│   │   • Retries, timeouts, circuit breakers                         │  │
│   │   • Observability (metrics, tracing)                             │  │
│   │                                                                  │  │
│   └─────────────────────────────────────────────────────────────────┘  │
│                                                                         │
└────────────────────────────────────────────────────────────────────────┘

Container Security

ECR Security Best Practices

# ECR Repository with security features
resource "aws_ecr_repository" "app" {
  name                 = "my-app"
  image_tag_mutability = "IMMUTABLE"  # Prevent tag overwriting

  image_scanning_configuration {
    scan_on_push = true
  }

  encryption_configuration {
    encryption_type = "KMS"
    kms_key         = aws_kms_key.ecr.arn
  }
}

# Lifecycle policy - keep last 10 images
resource "aws_ecr_lifecycle_policy" "app" {
  repository = aws_ecr_repository.app.name

  policy = jsonencode({
    rules = [
      {
        rulePriority = 1
        description  = "Keep last 10 tagged images"
        selection = {
          tagStatus     = "tagged"
          tagPrefixList = ["v"]
          countType     = "imageCountMoreThan"
          countNumber   = 10
        }
        action = {
          type = "expire"
        }
      },
      {
        rulePriority = 2
        description  = "Delete untagged images older than 1 day"
        selection = {
          tagStatus   = "untagged"
          countType   = "sinceImagePushed"
          countUnit   = "days"
          countNumber = 1
        }
        action = {
          type = "expire"
        }
      }
    ]
  })
}

# Repository policy - cross-account access
resource "aws_ecr_repository_policy" "app" {
  repository = aws_ecr_repository.app.name

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "AllowCrossAccountPull"
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::222222222222:root"
        }
        Action = [
          "ecr:GetDownloadUrlForLayer",
          "ecr:BatchGetImage",
          "ecr:BatchCheckLayerAvailability"
        ]
      }
    ]
  })
}

Dockerfile Best Practices

# Build stage
FROM node:18-alpine AS builder

# Non-root user
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

WORKDIR /app

# Install dependencies first (cache layer)
COPY package*.json ./
RUN npm ci --only=production

# Copy source
COPY --chown=nodejs:nodejs . .

# Build
RUN npm run build

# Production stage - minimal image
FROM gcr.io/distroless/nodejs18-debian11

WORKDIR /app

# Copy only necessary files
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./

# Run as non-root
USER 1001

EXPOSE 8080

CMD ["dist/index.js"]

# Labels for metadata
LABEL org.opencontainers.image.source="https://github.com/org/repo"
LABEL org.opencontainers.image.version="${VERSION}"

🎯 Interview Questions

Choose ECS when:
  • Team is new to containers
  • Simple orchestration needs
  • Deep AWS integration required
  • Faster time to production
  • Less operational overhead
Choose EKS when:
  • Team has Kubernetes experience
  • Need multi-cloud portability
  • Complex scheduling requirements
  • Rich Kubernetes ecosystem needed
  • Already have K8s manifests
Key differences:
  • ECS: Task definitions, services
  • EKS: Pods, deployments, services
  • ECS: AWS-native, simpler
  • EKS: CNCF standard, portable
Fargate:
  • No infrastructure management
  • Per-task pricing
  • Faster scaling
  • Better for variable workloads
  • Higher per-unit cost
EC2:
  • Full control over instances
  • Lower cost at scale
  • GPU support
  • Spot instances
  • Host networking
Cost comparison (10 vCPU, 20GB RAM, 730 hrs):
  • Fargate: ~$450/month
  • EC2 (m5.xlarge): ~$280/month
  • EC2 Spot: ~$120/month
Options:
  1. Secrets Manager (recommended):
    • Rotation support
    • Fine-grained IAM
    • $0.40/secret/month
  2. Parameter Store:
    • Cost-effective
    • Hierarchical
    • No rotation
  3. Task Definition secrets:
    "secrets": [
      {
        "name": "DB_PASSWORD",
        "valueFrom": "arn:aws:secretsmanager:..."
      }
    ]
    
Never:
  • Hardcode in images
  • Pass as env vars in task def
Sidecar pattern:
  • Helper container alongside main app
  • Share network namespace
  • Same lifecycle as main container
Common sidecars:
  • Envoy: Service mesh proxy
  • X-Ray daemon: Distributed tracing
  • Fluent Bit: Log aggregation
  • CloudWatch agent: Metrics
Example task definition:
{
  "containerDefinitions": [
    { "name": "app", "essential": true },
    { "name": "envoy", "essential": true },
    { "name": "xray", "essential": false }
  ]
}
ECS (CodeDeploy):
  • Blue/green with weighted target groups
  • Canary10Percent5Minutes config
  • CloudWatch alarms for rollback
EKS options:
  1. Native: Multiple deployments with ingress weights
  2. Flagger: Automated canary with Istio/App Mesh
  3. Argo Rollouts: Progressive delivery
Example (Argo Rollouts):
spec:
  strategy:
    canary:
      steps:
        - setWeight: 10
        - pause: {duration: 5m}
        - setWeight: 50
        - pause: {duration: 5m}
        - setWeight: 100

🧪 Hands-On Lab: Deploy Microservices on ECS

1

Create ECR Repositories

Create repositories for frontend, backend, and worker services
2

Build and Push Images

Build Docker images with multi-stage Dockerfiles, push to ECR
3

Create ECS Cluster

Fargate cluster with Container Insights enabled
4

Define Task Definitions

Task definitions with health checks, secrets, and logging
5

Deploy Services

Services with ALB integration and auto-scaling
6

Configure Service Discovery

Cloud Map namespace for inter-service communication

What’s Next?