Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

44장. ECS의 구조 — Cluster · Task · Service

이 장에서 말하고자 하는 것

도커 이미지를 ECR에 올렸으니
이제 그 이미지를 실제로 돌리는 도구가 필요하다.

Amazon ECS (Elastic Container Service)

다.

이 장은 ECS가 무엇이고 어떤 구성 요소로 동작하는지 본다.


1. ECS는 무엇을 해주는가

ECS는 컨테이너 오케스트레이션 서비스다.

다음을 자동으로 한다.

  • 컨테이너 어디서 돌릴지 결정
  • 죽으면 다시 띄우기
  • 트래픽 분배(ALB 연동)
  • 로그/메트릭 수집
  • 배포 (Rolling / Blue-Green)

사람이 EC2에 SSH로 들어가 docker run 하지 않게 해준다.


2. ECS의 4개 핵심 개념

Task Definition  : 컨테이너 1대의 "설계도"
Task             : 실제로 돌고 있는 컨테이너 묶음
Service          : Task가 항상 N개 살아 있도록 관리하는 컨트롤러
Cluster          : 위 모든 것이 들어 있는 논리적 공간
[Cluster: msa]
 ├─ Service "orders"
 │   ├─ Task 1   (Task Definition: orders:7)
 │   └─ Task 2
 ├─ Service "users"
 │   └─ ...

3. Task Definition — 컨테이너 설계도

어떤 이미지를 / 어떤 자원으로 / 어떤 환경 변수로 돌릴지의 정의.

  • 이미지 URL
  • CPU · 메모리
  • 환경 변수
  • 포트
  • IAM Role
  • 로그 설정

자세한 건 45장.


4. Task — 살아 있는 컨테이너 묶음

Task는 하나 이상의 컨테이너 다.

Task A
 ├─ app 컨테이너
 └─ log-forwarder 컨테이너 (사이드카)

대부분 Task = 컨테이너 1개.
필요할 때만 사이드카를 추가한다.

Task는 일회용이다. 죽으면 끝, Service가 다시 띄운다.


5. Service — Task를 N개 유지하는 컨트롤러

desiredCount = 2
  ├─ Task 1 죽음 → Service가 새 Task 띄움
  └─ Task 2 정상

Service는 또한

  • ALB Target Group에 Task IP 자동 등록
  • 헬스 체크 실패 시 교체
  • 새 버전 배포 (Rolling)

까지 한다. 운영의 대부분은 Service 단위.


6. Cluster — 논리적 그룹

환경별로 나누는 게 일반적이다.

prod 클러스터   → 운영
stage 클러스터  → 스테이징
dev 클러스터    → 개발

7. Capacity Provider — 컨테이너를 어디서 돌릴까

  • Fargate — 서버리스, 노드 관리 없음
  • EC2 — 본인이 만든 EC2 클러스터

이 선택을 추상화한 게 Capacity Provider다. 자세한 비교는 46장.


8. 우리 서비스에서

[Cluster: msa]
 ├─ Service "orders"   (Fargate, desired=2)
 ├─ Service "users"    (Fargate, desired=2)
 ├─ Service "payments" (Fargate, desired=2)
 └─ Service "web"      (Fargate, desired=2)

9. 직접 확인해보기 — CLI

aws ecs create-cluster --cluster-name msa

aws ecs register-task-definition \
  --cli-input-json file://task-def.json

aws ecs create-service \
  --cluster msa \
  --service-name orders \
  --task-definition orders:1 \
  --desired-count 2 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[...],securityGroups=[...]}"

aws ecs list-tasks --cluster msa --service-name orders

10. 코드로는 이렇게 생겼다 — Terraform

resource "aws_ecs_cluster" "main" {
  name = "msa"

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

resource "aws_ecs_task_definition" "orders" {
  family                   = "orders"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = "512"
  memory                   = "1024"
  execution_role_arn       = aws_iam_role.task_execution.arn

  container_definitions = jsonencode([{
    name      = "app"
    image     = "${aws_ecr_repository.orders.repository_url}:v1"
    essential = true
    portMappings = [{ containerPort = 8080 }]
  }])
}

resource "aws_ecs_service" "orders" {
  name            = "orders"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.orders.arn
  desired_count   = 2
  launch_type     = "FARGATE"

  network_configuration {
    subnets         = [aws_subnet.private_a.id, aws_subnet.private_b.id]
    security_groups = [aws_security_group.task.id]
  }
}

11. 이렇게 쓰면 망한다 — 안티패턴

안티패턴 1. Container Insights를 안 켠다

ECS의 메트릭이 제대로 안 모인다.

안티패턴 2. 한 클러스터에 prod와 dev를 섞는다

권한 · 네트워크 · 비용이 다 섞인다.

안티패턴 3. Task에 외부 IP를 직접 노출한다

assign_public_ip = true 는 보안 위험. Task는 프라이빗 서브넷.

안티패턴 4. Service 없이 RunTask로만 띄운다

RunTask는 일회성. 운영 서비스는 무조건 Service.


12. 한 줄로 정리

ECS는 Cluster 안에서 Service가 Task Definition으로 Task를 N개 살아 있게 유지하는 구조다


13. 이 장의 핵심 정리

  1. ECS의 네 축은 Cluster · Service · Task Definition · Task 다.
  2. Task Definition은 설계도, Task는 실행 인스턴스다.
  3. Service가 Task 수와 배포를 책임진다.
  4. Capacity Provider는 Fargate/EC2 선택을 추상화한다.
  5. 환경별로 Cluster를 나누고 Container Insights를 켠다.
  6. 운영 서비스에 RunTask 단독은 쓰지 않는다.