기준: DOP-C02 시험 가이드오류 제보
ECS의 배포 컨트롤러는 세 종류다. 기본 ECS 컨트롤러는 Rolling Update를 한다. CODE_DEPLOY 컨트롤러는 Blue/Green을 한다. EXTERNAL은 App Mesh나 Argo Rollouts 같은 외부 시스템이 제어한다. 시험에서 "ECS Blue/Green"이 나오면 반드시 CODE_DEPLOY 컨트롤러다. 이 구분을 틀리면 다음 보기 전체가 틀린다.
ECS Blue/Green의 물리적 구현은 "두 Target Group + ALB Listener"다. Blue Target Group에 현재 Task Set, Green Target Group에 새 Task Set이 등록된다. ALB Listener의 가중치 변경으로 트래픽이 전환된다. Lambda Alias의 가중치 시프트와 개념은 같지만, 레이어가 한 단계 더 깊다 — ALB, Target Group, Task Set이라는 추가 구성 요소들이 있고, 이들의 관계가 배포의 흐름을 만든다.
오늘은 컨트롤러 선택 → 배포 흐름 → AppSpec Hook → CodePipeline 통합 → IMAGE1_NAME 치환 → Fargate/EC2 차이까지 ECS 배포의 전 과정을 다룬다.
Day 4의 핵심 프레임: ECS Blue/Green 문제에서 "어떤 구성 요소가 어떤 역할을 하는가"를 모르면 보기가 모두 그럴듯해 보인다. Production Listener가 트래픽을 제어하고, Test Listener가 사전 검증을 허용하고, AppSpec Hook Lambda가 각 단계에서 게이트 역할을 한다. 이 세 레이어의 역할 구분이 시험의 핵심이다.
| 컨트롤러 | 배포 방식 | 트래픽 제어 레이어 | 자동 롤백 메커니즘 |
|---|---|---|---|
ECS (기본) | Rolling Update | ECS 내부 (MinHealthy/MaxPercent) | Deployment Circuit Breaker |
CODE_DEPLOY | Blue/Green | ALB Listener + 두 Target Group | CodeDeploy Alarm 기반 |
EXTERNAL | 사용자 정의 | App Mesh, Argo Rollouts 등 | 사용자 정의 |
절대 규칙: ECS Service 생성 시 컨트롤러를 지정하면 이후 변경 불가능. Rolling → Blue/Green으로 바꾸려면 Service를 삭제하고 재생성해야 한다. 시험에서 "기존 ECS Service를 Rolling에서 Blue/Green으로 전환하는 방법"이 나오면 "Service 재생성 필요"가 정답이다.
EXTERNAL컨트롤러는 AWS가 트래픽 제어에 전혀 개입하지 않는 모드다. Task Set 생성/삭제는 사용자가 직접 API로 수행하고, 트래픽은 App Mesh의 가상 라우터나 Argo Rollouts가 제어한다. 멀티클러스터 서비스 메시 환경이나 고급 Canary(헤더 기반, 사용자 세그먼트 기반)가 필요할 때 사용한다. DOP-C02 시험에서는 주로ECS와CODE_DEPLOY차이를 묻는다.
CodeDeploy 없이도 ECS 자체의 Rolling Update에서 자동 롤백이 가능하다.
aws ecs update-service \
--cluster prod \
--service myapp \
--task-definition myapp:43 \
--deployment-configuration \
"minimumHealthyPercent=100,maximumPercent=200,
deploymentCircuitBreaker={enable=true,rollback=true}"파라미터 의미:
minimumHealthyPercent=100: 배포 중에도 최소 100% Task가 Healthy 유지 (다운타임 없음)maximumPercent=200: 최대 200%까지 Task 수 증가 허용 (새 Task 먼저 띄움)deploymentCircuitBreaker.enable=true: 새 Task가 연속 Health Check 실패 시 배포 실패 처리deploymentCircuitBreaker.rollback=true: 배포 실패 시 이전 Task Definition으로 자동 롤백Surge 패턴 (minimumHealthyPercent=100, maximumPercent=200):
초기: Task 4개 (구 버전) [100%]
↓
단계 1: Task 8개 (구 4 + 신 4) [200%] — 신 Task Health Check 대기
↓
단계 2: Task 4개 (신 버전) [100%] — 구 Task 종료
다운타임 없지만 일시적으로 EC2(또는 Fargate) 비용이 2배 발생한다.
Circuit Breaker는 전기 회로 차단기에서 유래한 소프트웨어 패턴이다. Netflix의 Hystrix가 2012년 대중화했고, Martin Fowler가 정의한 세 상태(Closed/Open/Half-Open)가 표준이다. ECS Deployment Circuit Breaker는 이 패턴을 배포 수준에 적용한다. "새 버전이 반복적으로 실패(Open) → 배포 중단 → 이전 버전으로 복원(Closed)"이다. Half-Open 상태는 CloudWatch Alarm 해제 후 다시 시도하는 경우에 해당한다.
ECS Blue/Green with CodeDeploy
==================================================
초기 상태:
ALB Production Listener (443) → TG-Blue (Task Set 1, 현재 버전) [100%]
ALB Test Listener (8443, 선택) → TG-Green (미연결)
Step 1: CreateDeployment (CodeDeploy가 Green Task Set 생성)
→ 새 Task Definition 기반으로 Green Task Set 생성
→ Task들이 TG-Green에 등록
→ Health Check 통과 대기 (실패 시 즉시 실패 처리)
Step 2: BeforeInstall Hook (선택)
→ Green Task Set 생성 전 사전 준비
Step 3: AfterAllowTestTraffic Hook (Test Listener 연결 후)
→ ALB Test Listener (8443) → TG-Green 연결
→ Hook Lambda가 8443 포트로 새 버전 직접 테스트
→ 성공/실패 보고
Step 4: BeforeAllowTraffic Hook
→ Production 트래픽 시프트 직전 최종 검증
Step 5: Production 트래픽 시프트
→ ALB Production Listener: TG-Blue(90%) + TG-Green(10%) [Canary]
→ 알람 모니터링 → TG-Green(100%)
Step 6: AfterAllowTraffic Hook
→ 시프트 완료 후 통합 검증
Step 7: Termination Wait Time (기본 1시간)
→ Blue Task Set 보존 → 이 기간 내 즉시 롤백 가능
Step 8: Blue Task Set 종료
Test Listener의 정확한 역할:
AfterAllowTestTraffic Hook이 사용 가능해짐⚠️ 함정: "Test Listener는 Blue/Green 배포에 필수"라는 보기는 틀리다. Test Listener는 선택 사항이다. 있으면
AfterAllowTestTrafficHook을 쓸 수 있어서 프로덕션 노출 전 별도 검증이 가능해지지만, 없어도 Blue/Green 배포 자체는 정상 동작한다. DOP-C02는 이 구분을 묻는다.
2022년 Lyft 공개 사례: 기존 ECS Rolling Update에서 CODE_DEPLOY Blue/Green으로 전환 후, 배포 롤백 시간이 평균 8분에서 45초로 단축됐다. 핵심은 Termination Wait Time 1시간 설정으로 Blue Task Set이 보존되어 있어, 문제 발견 즉시 CodeDeploy 콘솔에서 Stop+Rollback 한 번으로 복원이 가능했다는 것이다. Rolling Update의 롤백은 이전 Task Definition으로 새 배포를 시작하는 것이라 시간이 걸렸다.
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: "arn:aws:ecs:ap-northeast-2:123456789:task-definition/myapp:42"
LoadBalancerInfo:
ContainerName: "web" # 컨테이너 이름 (taskdef의 containerDefinitions[].name과 일치)
ContainerPort: 80 # 컨테이너 포트
PlatformVersion: "LATEST"
NetworkConfiguration:
AwsvpcConfiguration:
Subnets: ["subnet-a", "subnet-b"]
SecurityGroups: ["sg-xyz"]
AssignPublicIp: "DISABLED"
CapacityProviderStrategy:
- CapacityProvider: FARGATE_SPOT
Weight: 1
Hooks:
- BeforeInstall: "arn:aws:lambda:...:function:BeforeInstallHook"
- AfterInstall: "arn:aws:lambda:...:function:AfterInstallHook"
- AfterAllowTestTraffic: "arn:aws:lambda:...:function:TestHook"
- BeforeAllowTraffic: "arn:aws:lambda:...:function:BeforeProdHook"
- AfterAllowTraffic: "arn:aws:lambda:...:function:AfterProdHook"ECS AppSpec Hook 특징:
PutLifecycleEventHookExecutionStatus로 결과를 보고해야 함각 Hook의 역할:
| Hook | 시점 | 일반적 용도 |
|---|---|---|
BeforeInstall | Green Task Set 생성 전 | 사전 준비 (거의 사용 안 함) |
AfterInstall | Green Task Set 생성 후, Test Listener 연결 전 | Task 상태 검증 |
AfterAllowTestTraffic | Test Listener → TG-Green 연결 후 | 8443 포트로 통합 테스트 |
BeforeAllowTraffic | Production 트래픽 시프트 직전 | 최종 검증, 캐시 워밍 |
AfterAllowTraffic | Production 트래픽 시프트 완료 후 | 스모크 테스트, 모니터링 확인 |
ECS AppSpec의 Hook Lambda는 EC2 AppSpec의 Shell 스크립트와 동일한 역할을 하지만, Lambda의 특성상 타임아웃이 최대 15분으로 제한된다. 15분이 넘는 통합 테스트(예: 데이터베이스 마이그레이션 검증)는 Hook Lambda에서 Step Functions을 트리거하고, 완료 신호를 받아 CodeDeploy에 보고하는 비동기 패턴을 사용한다. 또는 Hook Timeout을 3600초(1시간)로 설정하고 Lambda에서 외부 시스템 완료를 polling하는 방법도 있다.
[Source: ECR Push 이벤트]
│
▼
[CodeBuild]
1. 이미지 빌드 및 ECR push
2. 아티팩트 생성:
- taskdef.json (IMAGE1_NAME 플레이스홀더 포함)
- appspec.yaml
- imagedefinitions.json
│
▼
[ECS (Blue/Green) Deploy Action]
- TaskDefinitionTemplateArtifact: taskdef.json
- AppSpecTemplateArtifact: appspec.yaml
- Image1ArtifactName: BuildArtifact
- Image1ContainerName: web
│
Pipeline이 imagedefinitions.json의 imageUri를
taskdef.json의 <IMAGE1_NAME> 위치에 자동 치환
│
▼
새 Task Definition Revision 등록
│
▼
CodeDeploy Blue/Green 배포 시작
taskdef.json (플레이스홀더 포함):
{
"family": "myapp",
"executionRoleArn": "arn:aws:iam::123456789:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789:role/myappTaskRole",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"containerDefinitions": [{
"name": "web",
"image": "<IMAGE1_NAME>",
"portMappings": [{"containerPort": 80, "protocol": "tcp"}],
"environment": [
{"name": "ENV", "value": "prod"}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/myapp",
"awslogs-region": "ap-northeast-2",
"awslogs-stream-prefix": "ecs"
}
}
}]
}imagedefinitions.json (CodeBuild가 생성):
[{
"name": "web",
"imageUri": "123456789.dkr.ecr.ap-northeast-2.amazonaws.com/myapp:abc1234f"
}]Pipeline이 imagedefinitions.json의 imageUri를 taskdef.json의 <IMAGE1_NAME> 자리에 치환하고, 새 Task Definition Revision을 등록한 후 CodeDeploy 배포를 시작한다.
CodeBuild의 이미지 빌드 및 아티팩트 생성 buildspec 예:
version: 0.2
phases:
pre_build:
commands:
- export IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c1-8)
- aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_URI
build:
commands:
- docker build -t $ECR_URI/myapp:$IMAGE_TAG .
post_build:
commands:
- docker push $ECR_URI/myapp:$IMAGE_TAG
- printf '[{"name":"web","imageUri":"%s"}]' "$ECR_URI/myapp:$IMAGE_TAG" > imagedefinitions.json
artifacts:
files:
- imagedefinitions.json
- taskdef.json
- appspec.yamlECS는 Task Definition의
image필드에 항상 구체적인 이미지 URI(태그 포함)를 써야 한다.latest태그는 ECS가 새 이미지를 자동으로 pull하지 않기 때문에 사실상 의미가 없다 — 새 배포가 새 이미지를 쓰려면 반드시 새 Task Definition Revision을 등록해야 한다. CodePipeline의<IMAGE1_NAME>치환 패턴이 이 문제를 자동화한다. 빌드마다 고유한 git SHA 기반 태그가 새 Task Definition에 반영된다.
⚠️ 함정:
taskdef.json에서 플레이스홀더는 반드시<IMAGE1_NAME>형식이어야 한다 (꺾쇠 괄호 포함). 다른 형식(예:${IMAGE_NAME},IMAGE_PLACEHOLDER)은 Pipeline Action이 인식하지 못해 치환이 발생하지 않는다. 시험에서 "IMAGE1_NAME이 치환되지 않는 이유"가 나오면 플레이스홀더 형식을 확인하는 것이 첫 번째 체크 항목이다.
Lambda와 달리 ECS에서도 Canary/Linear Deployment Configuration이 지원된다.
ECS 지원 Deployment Configurations:
# Canary 패턴 (ECS용)
CodeDeployDefault.ECSCanary10Percent5Minutes
CodeDeployDefault.ECSCanary10Percent15Minutes
# Linear 패턴 (ECS용)
CodeDeployDefault.ECSLinear10PercentEvery1Minutes
CodeDeployDefault.ECSLinear10PercentEvery3Minutes
# All at once
CodeDeployDefault.ECSAllAtOnceECS Canary의 동작:
aws deploy create-deployment-group \
--application-name MyApp-ECS \
--deployment-group-name prod \
--deployment-config-name CodeDeployDefault.ECSCanary10Percent5Minutes \
--service-role-arn arn:aws:iam::...:role/CodeDeployECSRole \
--ecs-services "clusterName=prod,serviceName=myapp" \
--load-balancer-info "targetGroupPairInfoList=[{
targetGroups=[{name=TG-Blue},{name=TG-Green}],
prodTrafficRoute={listenerArns=[arn:...prodListener]},
testTrafficRoute={listenerArns=[arn:...testListener]}
}]" \
--blue-green-deployment-configuration \
"terminateBlueInstancesOnDeploymentSuccess={action=TERMINATE,terminationWaitTimeInMinutes=60}" \
--auto-rollback-configuration "enabled=true,events=DEPLOYMENT_FAILURE,DEPLOYMENT_STOP_ON_ALARM" \
--alarm-configuration "enabled=true,alarms=[{name=Prod5xx}]"ECS Blue/Green에서의 트래픽 시프트는 ALB의 가중 Target Group 라우팅으로 구현된다. ALB Listener Rule의
forwardaction에 두 Target Group의 가중치를 지정한다. CodeDeploy가 이 가중치를 Canary/Linear 스케줄에 따라 자동으로 업데이트한다. Lambda Alias의 weighted routing과 개념은 같지만, 구현 레이어가 ALB → TG → Task Set으로 한 단계 더 깊다.
| 항목 | Fargate | EC2 (Container Instance) |
|---|---|---|
| 인스턴스 관리 | 없음 (AWS 관리) | ASG + Capacity Provider 필요 |
| Task 격리 | 강함 (별도 VM 기반) | 약함 (같은 호스트 공유 가능) |
| Spot 지원 | FARGATE_SPOT | EC2 Spot Instance |
| Blue/Green 지원 | CODE_DEPLOY 동일 | CODE_DEPLOY 동일 |
| 콜드 스타트 | 더 김 (이미지 pull 포함) | 더 짧음 (레이어 캐시 활용) |
| 배포 방식 | Task Definition Revision 갱신 | Task Definition Revision 갱신 |
배포 관점에서 Fargate와 EC2 Container Instance는 동일하게 동작한다 — 두 경우 모두 Task Definition Revision 변경으로 배포가 트리거되고, CodeDeploy가 두 경우 모두 동일하게 Blue/Green을 수행한다.
FARGATE_SPOT + Blue/Green 주의사항:
# AppSpec에서 Capacity Provider 지정 가능
CapacityProviderStrategy:
- CapacityProvider: FARGATE_SPOT
Weight: 3
- CapacityProvider: FARGATE
Weight: 1
Base: 1 # 최소 1개는 FARGATE로 보장FARGATE_SPOT은 Spot 중단이 발생할 수 있으므로, 배포 중 Green Task Set이 Spot 중단으로 갑자기 줄어들면 Health Check 실패로 이어질 수 있다. Blue/Green에서 중요한 배포라면 Base: 1로 최소 1개의 안정적인 FARGATE Task를 보장한다.
어떤 팀이 비용 절감을 위해 FARGATE_SPOT만으로 Blue/Green 배포를 구성했다. Canary 10% 시프트 중 Spot 중단이 발생해 Green Task Set이 Health Check 실패로 배포가 자동 롤백됐다. 실제 새 버전에는 문제가 없었지만 인프라 이슈로 배포가 실패한 것이다. 해결책:
Base: 1로 최소 FARGATE Task를 보장하거나, 중요한 배포에서는 FARGATE_SPOT 비율을 줄인다.
| 상황 | Termination Wait 진행 중 | Wait 완료 후 |
|---|---|---|
| 배포 직후 버그 발견 | CodeDeploy Stop+Rollback (즉시, Blue Task Set 활용) | 이전 Task Definition으로 새 배포 (시간 소요) |
| Canary 알람 발동 | 자동 롤백 (CodeDeploy) | 자동 롤백 없음 (이미 100% 전환) |
| Blue Task Set 없음 | 롤백 불가 (재배포 필요) | — |
Termination Wait Time이 끝나기 전에 문제를 발견하면 즉각 롤백이 가능하다. 이것이 Wait Time을 적절히 설정하는 이유다.
즉시 롤백 CLI:
# 배포 중단 + 롤백
aws deploy stop-deployment \
--deployment-id d-XXXXXXXXX \
--auto-rollback-enabled🎯 시나리오: 한 팀이 ECS Blue/Green 배포 후 30분이 지났다. Termination Wait Time은 60분으로 설정되어 있다. 새 버전에서 메모리 누수가 발견됐다. 지금 가장 빠른 복원 방법은? 정답은 CodeDeploy Stop+Rollback — Blue Task Set이 아직 살아있으므로 ALB 트래픽을 Blue로 즉시 전환할 수 있다. 60분 이후라면 Blue Task Set이 종료되어 있으므로, 이전 Task Definition 번호로 새 CodeDeploy 배포를 시작해야 한다 (수분 소요).
ECS 배포 전략 선택
====================
빠른 롤백이 필요한가?
└─ YES → CODE_DEPLOY 컨트롤러 (Blue/Green)
├─ Canary: 소수 트래픽 먼저 검증
├─ Linear: 점진적 전환
└─ AllAtOnce: 개발/테스트 환경만
자동 롤백으로 충분한가?
└─ YES → ECS 컨트롤러 (Rolling) + Circuit Breaker
├─ minimumHealthyPercent/maximumPercent 설정
└─ deploymentCircuitBreaker.rollback=true
사전 검증 채널이 필요한가?
└─ YES → Test Listener (8443) + AfterAllowTestTraffic Hook
└─ NO → Test Listener 없어도 Blue/Green 동작
CODE_DEPLOY vs ECS 컨트롤러 선택 기준:
CODE_DEPLOY: 즉각 롤백, 트래픽 시프트 제어, Hook 검증
ECS(Rolling): 단순성, CodeDeploy 불필요, Circuit Breaker로 충분
선택지를 클릭하면 정답·해설이 펼쳐집니다.
문제 1
ECS Service에서 Blue/Green 배포를 사용하려면 어떤 deployment controller를 설정해야 하는가?
문제 2
ECS Rolling Update에서 자동 롤백을 구현하는 방법은?
문제 3
ECS Blue/Green 배포에서 Test Listener의 역할은?
문제 4
CodePipeline의 ECS(Blue/Green) Action에서 <IMAGE1_NAME> 플레이스홀더의 역할은?
문제 5
ECS Blue/Green 배포에서 Termination Wait Time 60분 중 45분이 지났다. 새 버전에서 심각한 버그가 발견됐다. 가장 빠른 복원 방법은?
문제 6
ECS Rolling Update에서 minimumHealthyPercent=100, maximumPercent=200의 동작은?
문제 7
ECS Blue/Green Deployment Group 설정에서 필수가 아닌 것은?