Use Cases

Claude Code × AWS ECS/Fargate Panduan Lengkap | Otomatisasi Deployment Container

Otomatisasi deployment AWS ECS/Fargate dengan Claude Code. Dari task definition, konfigurasi service, Blue/Green deployment, hingga infrastruktur CDK — berdasarkan pengalaman nyata Masa.

“Saya ingin menjalankan container di AWS, tapi konfigurasi ECS terlalu rumit” — ini adalah tembok yang banyak developer temui pertama kali. Task definition, service, cluster, load balancer, auto scaling… pengaturannya sangat banyak sehingga tidak tahu harus mulai dari mana.

Saya membangun lingkungan container serverless dengan ECS/Fargate di tempat kerja, dan sejak saya mulai menggunakan Claude Code untuk mendeskripsikan arsitektur dan menghasilkan semuanya dari task definition hingga kode CDK, proses deployment menjadi jauh lebih mudah. Artikel ini menjelaskan langkah-langkah praktisnya.


Dasar-Dasar ECS/Fargate dalam 3 Menit

Cluster:         "Kotak" tempat container ECS berjalan
Task Definition: Spesifikasi container (image, CPU, memory, env vars)
Service:         Menentukan berapa banyak task yang berjalan (termasuk auto scaling)
Fargate:         Engine eksekusi container serverless — tanpa manajemen server

Berbeda dengan EC2, Fargate tidak memerlukan provisioning server atau manajemen patch. Anda bisa fokus sepenuhnya pada konfigurasi container.


Langkah 1: Generate Task Definition Secara Otomatis

claude -p "
Generate task definition ECS dalam format JSON dengan persyaratan berikut:

- App: Node.js API (port 3000)
- CPU: 512 (0.5 vCPU)
- Memory: 1024 MB
- Environment variables: DATABASE_URL (diambil dari Secrets Manager), NODE_ENV=production
- Logging: CloudWatch Logs (log group /ecs/myapp)
- Health check: endpoint /health, interval 30 detik
- Container image: 123456789.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:latest
- Execution role: ecsTaskExecutionRole
- Task role: myapp-task-role (akses ke DynamoDB dan S3)
"

Task definition yang dihasilkan:

{
  "family": "myapp-task",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "512",
  "memory": "1024",
  "executionRoleArn": "arn:aws:iam::123456789:role/ecsTaskExecutionRole",
  "taskRoleArn": "arn:aws:iam::123456789:role/myapp-task-role",
  "containerDefinitions": [
    {
      "name": "myapp",
      "image": "123456789.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:latest",
      "portMappings": [{ "containerPort": 3000, "protocol": "tcp" }],
      "environment": [{ "name": "NODE_ENV", "value": "production" }],
      "secrets": [
        {
          "name": "DATABASE_URL",
          "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789:secret:prod/database-url"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/myapp",
          "awslogs-region": "ap-northeast-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "healthCheck": {
        "command": ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
        "interval": 30,
        "timeout": 5,
        "retries": 3,
        "startPeriod": 60
      }
    }
  ]
}

Langkah 2: Membangun Infrastruktur ECS/Fargate dengan CDK

Bukan hanya task definition, kita generate cluster, service, dan ALB sekaligus menggunakan CDK.

claude -p "
Implementasikan lingkungan ECS/Fargate berikut dalam CDK TypeScript di lib/ecs-stack.ts:

- VPC: Import VPC yang sudah ada (ambil vpcId dari environment variable)
- ECS Cluster: Hanya Fargate
- Task Definition: Spesifikasi sama seperti yang dihasilkan di atas
- ALB: HTTPS (ambil ARN sertifikat ACM dari environment variable), HTTP redirect dengan 301
- Service: Auto scaling dengan minimum 2, maksimum 10 task
  - Scale out pada 70% penggunaan CPU
  - Target tracking scaling
- Dukungan Blue/Green deployment (integrasi CodeDeploy)
- Tampilkan status service di CloudWatch dashboard
"
// lib/ecs-stack.ts
import * as cdk from "aws-cdk-lib";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as ecs from "aws-cdk-lib/aws-ecs";
import * as ecsp from "aws-cdk-lib/aws-ecs-patterns";
import * as acm from "aws-cdk-lib/aws-certificatemanager";

export class EcsStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Import VPC yang sudah ada
    const vpc = ec2.Vpc.fromLookup(this, "Vpc", {
      vpcId: process.env.VPC_ID!,
    });

    // ECS Cluster
    const cluster = new ecs.Cluster(this, "Cluster", {
      vpc,
      clusterName: "myapp-cluster",
      containerInsights: true,  // Aktifkan CloudWatch Container Insights
    });

    // Sertifikat ACM
    const certificate = acm.Certificate.fromCertificateArn(
      this, "Certificate",
      process.env.CERTIFICATE_ARN!
    );

    // Task Definition
    const taskDef = new ecs.FargateTaskDefinition(this, "TaskDef", {
      cpu: 512,
      memoryLimitMiB: 1024,
    });

    const container = taskDef.addContainer("app", {
      image: ecs.ContainerImage.fromEcrRepository(
        ecr.Repository.fromRepositoryName(this, "Repo", "myapp")
      ),
      environment: { NODE_ENV: "production" },
      logging: ecs.LogDrivers.awsLogs({ streamPrefix: "ecs" }),
      healthCheck: {
        command: ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
        interval: cdk.Duration.seconds(30),
        timeout: cdk.Duration.seconds(5),
        retries: 3,
        startPeriod: cdk.Duration.seconds(60),
      },
    });
    container.addPortMappings({ containerPort: 3000 });

    // ALB + Fargate Service (ringkas menggunakan patterns)
    const service = new ecsp.ApplicationLoadBalancedFargateService(
      this, "Service", {
        cluster,
        taskDefinition: taskDef,
        desiredCount: 2,
        certificate,
        redirectHTTP: true,
        publicLoadBalancer: true,
      }
    );

    // Konfigurasi Auto Scaling
    const scaling = service.service.autoScaleTaskCount({
      minCapacity: 2,
      maxCapacity: 10,
    });
    scaling.scaleOnCpuUtilization("CpuScaling", {
      targetUtilizationPercent: 70,
      scaleInCooldown: cdk.Duration.seconds(60),
      scaleOutCooldown: cdk.Duration.seconds(60),
    });

    // Output
    new cdk.CfnOutput(this, "LoadBalancerDns", {
      value: service.loadBalancer.loadBalancerDnsName,
    });
  }
}

Langkah 3: Membangun Pipeline CI/CD dengan GitHub Actions

claude -p "
Buat pipeline CI/CD berikut dengan GitHub Actions:

1. Trigger saat push ke branch main
2. Build Docker image dan push ke ECR
3. Update image tag di task definition ECS dengan SHA baru
4. Deploy task definition baru ke service ECS
5. Notifikasi Slack saat deployment selesai

Environment: ap-northeast-1, nama repositori ECR: myapp
"
name: Deploy to ECS

on:
  push:
    branches: [main]

env:
  AWS_REGION: ap-northeast-1
  ECR_REPOSITORY: myapp
  ECS_CLUSTER: myapp-cluster
  ECS_SERVICE: myapp-service
  CONTAINER_NAME: app

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_REGION }}

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      - name: Build, tag, and push image to ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

      - name: Download task definition
        run: |
          aws ecs describe-task-definition --task-definition myapp-task \
            --query taskDefinition > task-definition.json

      - name: Update ECS task definition with new image
        id: task-def
        uses: aws-actions/amazon-ecs-render-task-definition@v1
        with:
          task-definition: task-definition.json
          container-name: ${{ env.CONTAINER_NAME }}
          image: ${{ steps.build-image.outputs.image }}

      - name: Deploy to ECS
        uses: aws-actions/amazon-ecs-deploy-task-definition@v1
        with:
          task-definition: ${{ steps.task-def.outputs.task-definition }}
          service: ${{ env.ECS_SERVICE }}
          cluster: ${{ env.ECS_CLUSTER }}
          wait-for-service-stability: true

      - name: Notify Slack on success
        if: success()
        uses: slackapi/slack-github-action@v1
        with:
          webhook: ${{ secrets.SLACK_WEBHOOK }}
          payload: |
            {"text": "✅ Deployed to ECS: ${{ github.sha }}"}

Langkah 4: Konfigurasi Blue/Green Deployment

claude -p "
Generate kode CDK dan file AppSpec untuk mengatur Blue/Green deployment (CodeDeploy) untuk service ECS.
Kondisi rollback: rollback otomatis jika CloudWatch alarm aktif dalam 5 menit setelah deployment.
"
# appspec.yaml (untuk CodeDeploy)
version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: <TASK_DEFINITION>
        LoadBalancerInfo:
          ContainerName: app
          ContainerPort: 3000
        PlatformVersion: LATEST
Hooks:
  - BeforeAllowTraffic: "arn:aws:lambda:ap-northeast-1:123456789:function:health-check"
  - AfterAllowTraffic: "arn:aws:lambda:ap-northeast-1:123456789:function:smoke-test"

5 Jebakan yang Sering Terjadi

1. Lupa startPeriod di health check

Container Fargate langsung menjalankan health check saat startup, tapi jika aplikasi lambat start, langsung ditandai UNHEALTHY. Set startPeriod: 60 (detik) untuk memberi waktu aplikasi melakukan inisialisasi.

2. Mencampuradukkan task role dan execution role

executionRole (ecsTaskExecutionRole): Permission yang dibutuhkan untuk menjalankan container
  → Pull image dari ECR, menulis ke CloudWatch Logs

taskRole (myapp-task-role): Permission yang digunakan aplikasi
  → Akses ke DynamoDB, S3, SQS, dll.

Sangat mudah menambahkan permission ke role yang salah.

3. Konfigurasi security group di mode jaringan awsvpc

Fargate mengharuskan mode jaringan awsvpc. Jika lupa membatasi security group container hanya untuk traffic dari ALB, container akan terekspos langsung ke internet.

4. Execution role diperlukan untuk mengambil dari Secrets Manager

Untuk mengambil nilai Secrets Manager melalui secrets, executionRole harus memiliki permission secretsmanager:GetSecretValue. Tidak adanya permission ini adalah alasan umum container gagal start.

5. Masalah desired_count: 0 saat deployment

Service dengan minimum 0 di auto scaling bisa mematikan semua container di malam hari, menyebabkan startup lambat di pagi hari. Set minimum ke setidaknya 2 di production.


Ringkasan

TugasKontribusi Claude Code
Generate task definitionJSON lengkap hanya dari persyaratan
Implementasi CDKCluster, service, ALB, auto scaling digenerate bersama
Setup CI/CDGenerate workflow GitHub Actions
Blue/Green deploymentAppSpec dan konfigurasi CodeDeploy digenerate otomatis
Pemecahan masalahIdentifikasi penyebab dan perbaikan dari error log

ECS memiliki banyak item konfigurasi, tapi dengan memberi tahu Claude Code “saya ingin setup seperti ini”, Anda mendapatkan konfigurasi lengkap yang mengikuti best practice. Memulai dengan CDK adalah pendekatan termudah dan paling direkomendasikan.

Artikel Terkait

Referensi

#claude-code #aws #ecs #fargate #container #devops

Tingkatkan alur kerja Claude Code kamu

50 template prompt yang sudah teruji, siap copy-paste ke Claude Code sekarang juga.

Gratis

PDF Gratis: Cheatsheet Claude Code dalam 5 Menit

Cukup masukkan emailmu dan kami akan langsung mengirim cheatsheet PDF A4 satu halaman.

Kami menjaga data pribadimu dengan aman dan tidak pernah mengirim spam.

Masa

Tentang Penulis

Masa

Engineer yang aktif menggunakan Claude Code. Mengelola claudecode-lab.com, media teknologi 10 bahasa dengan lebih dari 2.000 halaman.