Bạn có Docker image, muốn chạy trên AWS. EC2 thì phải quản lý node pool, auto-scaling group, AMI update. ECS Fargate: bạn chỉ cần task definition, AWS lo phần còn lại. Không EC2, không node pool, không cluster management.


  flowchart TB
    ECR["ECR image"] --> TaskDef["Task Definition<br/>cpu/memory/image/secrets/logging"]
    TaskDef --> Service["ECS Service<br/>desired=3 · deployment rolling"]
    Service --> T1["Task (ENI)"]
    Service --> T2["Task (ENI)"]
    Service --> T3["Task (ENI)"]
    ALB["ALB"] --> Service
    CW["CloudWatch: CPU > 60%"] -->|"scale-out"| Service

Execution role (ECS agent pull image, stream log, get secrets) ≠ Task role (code trong container gọi AWS API). Tách biệt để app compromised không có quyền infrastructure.

{
  "family": "myapp-api",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "512",
  "memory": "1024",
  "containerDefinitions": [
    {
      "name": "api",
      "image": "123456789012.dkr.ecr.ap-southeast-1.amazonaws.com/myapp-api:v1",
      "portMappings": [{ "containerPort": 3000 }],
      "secrets": [
        {
          "name": "DB_PASSWORD",
          "valueFrom": "arn:aws:secretsmanager:...:secret:/prod/db:password::"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/myapp-api",
          "awslogs-region": "ap-southeast-1",
          "awslogs-stream-prefix": "api"
        }
      }
    }
  ]
}

Execution role khác task role. Execution role cho ECS agent pull image và log; task role cho code trong container gọi AWS API. App compromised không có quyền infrastructure.

Auto-scaling: CPU > 60% scale-out, CDK 3 dòng code

aws application-autoscaling register-scalable-target --service-namespace ecs \
  --resource-id service/myapp-cluster/api-service --min-capacity 2 --max-capacity 20
aws application-autoscaling put-scaling-policy --policy-name cpu60 \
  --policy-type TargetTrackingScaling --target-tracking-scaling-policy-configuration '{
    "PredefinedMetricSpecification": {"PredefinedMetricType": "ECSServiceAverageCPUUtilization"},
    "TargetValue": 60
  }'
const service = new ecsPatterns.ApplicationLoadBalancedFargateService(
  this,
  "Api",
  {
    cluster,
    cpu: 512,
    memoryLimitMiB: 1024,
    desiredCount: 3,
    taskImageOptions: {
      image: ecs.ContainerImage.fromEcrRepository(ecrRepo),
      containerPort: 3000,
      secrets: { DB_PASSWORD: ecs.Secret.fromSecretsManager(dbSecret) },
    },
  }
);
service.service
  .autoScaleTaskCount({ minCapacity: 2, maxCapacity: 20 })
  .scaleOnCpuUtilization("CpuScaling", { targetUtilizationPercent: 60 });

Bài sau: Phần 22: IaC với CDK TypeScript