51장. 통합 흐름 — 우리 서비스를 ECS 위로 올려보기
이 장에서 말하고자 하는 것
Part 8에서 우리는 컨테이너의 모든 부품을 다뤘다.
- 41장. 왜 컨테이너인가
- 42장. 도커 기초
- 43장. ECR
- 44장. ECS 구조
- 45장. Task Definition
- 46장. EC2 vs Fargate
- 47장. Service와 ALB 연결
- 48장. Service Discovery
- 49장. 배포 전략
- 50장. EKS
이번 장은 이 부품들이 한 묶음으로 어떻게 굴러가는지 정리한다.
작은 마이크로서비스 한 개를 처음부터 끝까지 띄워본다
1. 우리가 띄울 서비스
매우 단순한 orders 서비스다.
GET /health → 200
GET /api/orders → 주문 목록
POST /api/orders → 주문 생성
이 서비스를 컨테이너로 패키징해 ALB 뒤에 ECS Fargate로 띄운다.
2. 전체 구성도
[사용자]
↓ HTTPS
[CloudFront]
↓
[ALB] ── /api/orders/* ──→ TG-orders
↓
[ECS Service "orders"]
├─ Task 1 (Fargate)
└─ Task 2 (Fargate)
↓ 내부 호출
[RDS] ← (다음 단원에서 다룸)
이번 장에서는 ALB ~ ECS 까지 닫는다. DB는 다음 단원.
3. 단계 — 무엇을 어떤 순서로 만드는가
1. Dockerfile 작성 → 이미지 빌드
2. ECR 리포지토리 생성
3. 이미지 푸시 (orders:v1)
4. Task Definition 등록 (이미지 URL · CPU · 메모리)
5. ALB · Target Group 준비
6. ECS Cluster · Service 생성
- desiredCount = 2
- Target Group 연결
7. ALB Listener Rule에 /api/orders/* → TG-orders 추가
8. (있다면) Service Discovery 등록
9. ALB DNS로 호출 테스트 → 헬스 체크 통과 확인
4. 핵심 4개 파일
.
├─ Dockerfile ← 컨테이너 이미지 정의
├─ task-definition.json ← (또는 Terraform 리소스로 대체)
├─ buildspec / workflow ← 빌드/푸시 자동화
└─ terraform/ ← 인프라 정의
다음 단원(자동화)에서 한 번에 묶는 흐름을 다룬다.
5. 우리 서비스에서
[ALB]
└─ /api/orders/* → TG-orders
↑
[ECS Service "orders"]
├─ task v1
└─ task v1
이걸 그대로 users · payments 로 복제하면 마이크로서비스가 늘어 간다.
[ALB]
├─ /api/orders/* → ECS "orders"
├─ /api/users/* → ECS "users"
└─ /api/payments/* → ECS "payments"
이게 1~51장의 결과물이다.
6. 직접 확인해보기 — CLI 한 바퀴
# 1. ECR 로그인 & 이미지 푸시
aws ecr get-login-password --region ap-northeast-2 \
| docker login --username AWS --password-stdin <acct>.dkr.ecr.ap-northeast-2.amazonaws.com
docker build -t orders:v1 .
docker tag orders:v1 <acct>.dkr.ecr.ap-northeast-2.amazonaws.com/orders:v1
docker push <acct>.dkr.ecr.ap-northeast-2.amazonaws.com/orders:v1
# 2. Task Definition 등록
aws ecs register-task-definition --cli-input-json file://task-def.json
# 3. Service 만들기
aws ecs create-service \
--cluster my-cluster \
--service-name orders \
--task-definition orders:1 \
--desired-count 2 \
--launch-type FARGATE \
--load-balancers "targetGroupArn=<tg-arn>,containerName=app,containerPort=8080" \
--network-configuration "awsvpcConfiguration={subnets=[subnet-x,subnet-y],securityGroups=[sg-x]}"
# 4. 호출 테스트
curl https://api.example.com/api/orders
7. 코드로는 이렇게 생겼다 — Terraform 한 묶음
resource "aws_ecr_repository" "orders" {
name = "orders"
}
resource "aws_ecs_cluster" "main" {
name = "msa"
}
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
task_role_arn = aws_iam_role.task.arn
container_definitions = jsonencode([{
name = "app"
image = "${aws_ecr_repository.orders.repository_url}:v1"
essential = true
portMappings = [{ containerPort = 8080 }]
logConfiguration = {
logDriver = "awslogs"
options = {
awslogs-group = "/ecs/orders"
awslogs-region = "ap-northeast-2"
awslogs-stream-prefix = "app"
}
}
}])
}
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"
deployment_circuit_breaker {
enable = true
rollback = true
}
network_configuration {
subnets = [aws_subnet.private_a.id, aws_subnet.private_b.id]
security_groups = [aws_security_group.task.id]
}
load_balancer {
target_group_arn = aws_lb_target_group.orders.arn
container_name = "app"
container_port = 8080
}
}
이 한 묶음이 Part 8 전체 + 33~37장 + 19~28장 (VPC) 의 결과물이다.
8. 이렇게 쓰면 망한다 — 통합 단계의 흔한 함정
함정 1. Task의 보안 그룹이 ALB 보안 그룹과 안 맞다
ALB → Task 8080 포트가 막혀 있으면 헬스 체크 영원히 실패.
Task SG는 ALB SG에서 오는 8080을 허용해야 한다
함정 2. 서브넷이 외부 인터넷 접근이 안 된다
ECR · CloudWatch · Secrets Manager 호출이 막힌다.
프라이빗 서브넷이면 NAT Gateway 또는 VPC Endpoint 필요
함정 3. Execution Role 권한 부족
ECR pull · CloudWatch 쓰기 권한이 없으면 Task 시작 실패.
AmazonECSTaskExecutionRolePolicy 부터 붙인다
함정 4. ALB Listener Rule을 까먹는다
Service · TG는 만들었는데 ALB 규칙이 없으면 트래픽이 안 들어온다.
9. 한 줄로 정리
컨테이너 한 개를 띄우는 일은 ECR · TaskDef · Service · ALB · VPC · IAM 이 한 묶음으로 맞물려야 한다
10. 이 장의 핵심 정리
- Part 8 부품들이 모이면 ALB → ECS → 컨테이너 흐름이 완성된다.
- 새 서비스를 추가하는 패턴은 “ECR 푸시 → TaskDef → Service → ALB 규칙” 의 반복이다.
- 실패의 80%는 보안 그룹 · 네트워크 · IAM에서 온다.
- 같은 패턴을 복제해 여러 마이크로서비스로 확장한다.
- 다음 단원은 이 서비스에 데이터 계층을 붙인다.