[인턴] ECS Fargate로 회귀: Source IP 기반 카나리 이전 전략
들어가며
이전 글에서는 EC2에서 ECS on EC2로의 이전 계획을 5단계 플레이북으로 정리했습니다.
그런데 계획을 구체화하는 과정에서 방향이 바뀌었습니다. ECS on EC2가 아니라 ECS Fargate로 가기로 결정했고, 카나리 이전 방식도 ALB Weighted Target Group이 아닌 Source IP 기반 라우팅으로 변경했습니다.
이번 글에서는 왜 다시 Fargate로 돌아갔는지, 그리고 Source IP 기반 카나리가 어떤 방식인지를 정리합니다.
왜 다시 Fargate인가
이전 글에서 ECS on EC2를 선택한 이유 세 가지를 적었습니다. 비용 예측 가능성, EC2 운영 경험 재활용, awsvpc 네트워크 모드. 그런데 실제로 인프라를 세팅하면서 생각이 달라졌습니다.
EC2 인스턴스 관리가 또 다른 운영 부채
ECS on EC2는 컨테이너 오케스트레이션의 이점을 가져가면서도 호스트를 직접 제어할 수 있다는 장점이 있습니다. 하지만 이건 뒤집으면 호스트를 직접 관리해야 한다는 뜻이기도 합니다.
- AMI 패치와 보안 업데이트를 주기적으로 챙겨야 합니다
- ASG의 인스턴스 교체(draining → launch) 과정에서 Task 재배치를 신경 써야 합니다
- ECS Agent 버전 관리, Docker 데몬 설정, 디스크 용량 모니터링 등 호스트 레벨 운영이 추가됩니다
현재 팀 규모에서 이 운영 부담을 감당하면서 얻는 이점이 크지 않다는 결론에 도달했습니다. 단일 EC2를 벗어나려고 ECS를 도입하는 건데, EC2 인스턴스를 여러 대 관리하게 되면 본말이 전도됩니다.
Fargate의 실질적 이점 재평가
다시 Fargate를 검토하면서 이전에 과소평가했던 부분이 보였습니다.
| 항목 | ECS on EC2 | ECS Fargate |
|---|---|---|
| 호스트 패치 | 직접 관리 | AWS 관리 |
| 용량 계획 | ASG 설정 필요 | Task 단위 자동 |
| 스케일링 속도 | 인스턴스 부팅 대기 | Task만 띄우면 됨 |
| 비용 모델 | 인스턴스 시간 과금 | vCPU/메모리 초 단위 과금 |
| 네트워크 모드 | awsvpc 선택 가능 |
awsvpc 기본 |
비용 예측 가능성은 ECS on EC2의 장점이었지만, Fargate도 Savings Plans를 활용하면 충분히 예측 가능합니다. 무엇보다 운영 인력이 제한적인 환경에서는 관리 포인트를 줄이는 것이 비용을 줄이는 것보다 우선입니다.
결정적 계기
최종적으로 마음을 바꾼 건 팀 내 논의에서 나온 한 마디였습니다.
“EC2 위에 올리는 거면, 지금이랑 뭐가 다른 건데?”
물론 기술적으로는 완전히 다릅니다. 컨테이너 오케스트레이션, 헬스체크, 오토스케일링 등 ECS가 제공하는 모든 이점이 있습니다. 하지만 팀원들의 인식에서 EC2 인스턴스가 존재한다는 것 자체가 “또 서버 관리해야 하는 거 아니야?”라는 심리적 부담을 만들었습니다. Fargate로 가면 호스트가 완전히 추상화되어, 팀이 애플리케이션 로직에만 집중할 수 있습니다.
카나리 전략 변경: ALB Weight에서 Source IP 기반으로
플랫폼만 바뀐 게 아닙니다. 카나리 이전 방식 자체도 재설계했습니다.
기존 방식의 문제점
이전 계획에서는 ALB Weighted Target Group으로 트래픽을 5% → 10% → 25% → 50% → 75% → 100%로 점진적으로 올리는 방식이었습니다. 이 방식에는 한 가지 불편한 점이 있었습니다.
동일 사용자의 요청이 EC2와 ECS에 랜덤하게 분산됩니다. 가중치 기반 라우팅은 요청 단위로 분배하기 때문에, 같은 사용자가 첫 번째 요청은 EC2에서, 두 번째 요청은 ECS에서 처리받을 수 있습니다. 대부분의 경우 문제가 없지만, 세션 상태나 WebSocket 연결이 관여하는 시나리오에서는 예측하기 어려운 동작이 발생할 수 있습니다.
또한 문제가 생겼을 때 영향 범위를 특정하기 어렵습니다. 5% 가중치라고 해서 특정 5%의 사용자가 영향을 받는 게 아니라, 모든 사용자의 요청 중 5%가 랜덤으로 ECS로 갑니다. 장애 발생 시 “어떤 사용자가 영향을 받았는가”를 추적하기 까다롭습니다.
Source IP 기반 라우팅이란
새로운 전략은 이렇습니다. 특정 지역에서 발생하는 API 요청만 ECS Fargate로 보내고, 나머지는 기존 EC2에서 처리합니다.
ALB의 리스너 규칙에서 Source IP 조건을 활용합니다.
ALB Listener Rules (우선순위 순):
Rule 1: IF source-ip IN [특정 지역 CIDR 블록]
THEN forward → ECS Fargate Target Group
Rule 2: DEFAULT
THEN forward → EC2 Target Group
특정 지역의 CIDR 블록을 리스너 규칙에 등록하면, 해당 지역에서 오는 요청만 ECS로 라우팅됩니다. 나머지 모든 트래픽은 기존 EC2로 갑니다.
왜 이 방식이 더 나은가
1. 영향 범위가 명확합니다.
가중치 기반에서는 “전체 사용자의 5%”가 랜덤으로 영향을 받지만, Source IP 기반에서는 “특정 지역의 사용자”만 영향을 받습니다. 문제가 생기면 누가 영향을 받는지 즉시 알 수 있고, 해당 지역의 사용자에게만 안내하면 됩니다.
2. 사용자 경험이 일관됩니다.
같은 지역의 사용자는 모든 요청이 ECS로 갑니다. EC2와 ECS를 왔다 갔다 하지 않으므로, 세션 일관성이나 WebSocket 안정성 문제가 발생하지 않습니다.
3. 점진적 확장이 자연스럽습니다.
검증이 완료되면 CIDR 블록을 추가하거나, 조건을 넓혀서 더 많은 지역을 ECS로 보냅니다. 최종적으로 Default 규칙 자체를 ECS Target Group으로 바꾸면 이전이 완료됩니다.
4. 롤백이 단순합니다.
리스너 규칙에서 Source IP 조건을 삭제하면, 즉시 모든 트래픽이 EC2로 돌아갑니다. 가중치 방식의 롤백과 동일하게 한 줄로 끝납니다.
이전 단계 재설계
플랫폼과 카나리 전략이 모두 바뀌었으므로, 이전 단계도 재설계했습니다.
Stage 0: Fargate 인프라 준비
기존 Stage 0과 크게 다르지 않지만, EC2 인스턴스 관련 설정(ASG, Launch Template, ECS Agent 등)이 빠지고 Fargate 설정이 들어갑니다.
- Fargate Task Definition 작성 (vCPU/메모리 사이징)
- ECR 리포지토리 및 CI/CD 파이프라인 구성
- 보안 그룹 설정 (ALB SG → Task ENI SG)
- Secrets Manager 연동
- IAM Task Role / Task Execution Role 설정
- ECS Service desired count = 0으로 배포 파이프라인만 검증
Stage 1: Fargate Task 기동 검증 (트래픽 0%)
Task를 실제로 띄우되, ALB 리스너 규칙에 Source IP 조건을 아직 추가하지 않습니다. 모든 트래픽은 여전히 EC2로 갑니다.
내부에서 ECS Task의 엔드포인트를 직접 호출하여 검증합니다.
- Task
RUNNING상태 확인 - RDS 연결 정상 여부
- GraphQL 쿼리/뮤테이션 응답 확인
- Datadog APM 트레이스 수집 확인
- 외부 API 통신 확인 (NAT 경유 시 IP 변동 이슈 포함)
Stage 2: 특정 지역 트래픽 전환
검증이 완료되면 ALB 리스너 규칙에 특정 지역의 CIDR 블록을 Source IP 조건으로 추가합니다.
ALB Listener Rules:
Rule 1 (신규): source-ip ∈ [지역 A CIDR] → ECS Fargate TG
Rule 2 (기존): DEFAULT → EC2 TG
이 단계에서 모니터링할 지표는 이전 계획과 동일합니다.
- 5xx 에러율
- p99 레이턴시
- DB 커넥션 합산
- WebSocket 연결 안정성
다만 모니터링 대상이 “전체 트래픽의 N%”가 아니라 “특정 지역의 100%”이므로, Datadog 대시보드에서 지역별 필터를 걸어 해당 지역의 지표만 분리해서 봐야 합니다.
롤백 트리거 조건도 동일하게 적용합니다.
- 5xx가 baseline 대비 2배 이상
- p99가 baseline 대비 50% 이상 증가
- DB 커넥션이
max_connections의 80% 초과 - OOM Kill 반복 발생
Stage 3: 지역 확장
Stage 2에서 안정성이 확인되면 CIDR 블록을 추가하여 더 많은 지역을 ECS로 보냅니다.
ALB Listener Rules:
Rule 1: source-ip ∈ [지역 A CIDR, 지역 B CIDR, ...] → ECS Fargate TG
Rule 2: DEFAULT → EC2 TG
단계별로 지역을 넓혀가면서 ECS Fargate가 전체 트래픽을 감당할 수 있는지 확인합니다. 각 지역 추가 시 최소 하루 이상 관찰 기간을 둡니다.
Stage 4: 전면 전환 및 EC2 퇴역
모든 지역이 ECS로 전환된 것이 확인되면, Default 규칙의 Target Group을 ECS Fargate TG로 변경합니다. Source IP 조건 규칙은 제거하고, 모든 트래픽이 ECS Fargate로 흐르게 합니다.
ALB Listener Rules:
Rule 1: DEFAULT → ECS Fargate TG
이후 EC2 퇴역 절차는 이전 계획과 동일합니다. 바로 Terminate하지 않고 Stop 상태로 1~2주 유지한 뒤, 이상이 없으면 그때 Terminate합니다.
달라진 것과 달라지지 않은 것
달라진 것
| 항목 | 이전 계획 | 변경 후 |
|---|---|---|
| 컴퓨팅 플랫폼 | ECS on EC2 | ECS Fargate |
| 카나리 방식 | ALB Weighted TG (비율 기반) | Source IP 기반 라우팅 (지역 기반) |
| 호스트 관리 | ASG + AMI 패치 필요 | 불필요 (Fargate 추상화) |
| 트래픽 분배 단위 | 요청 단위 랜덤 분배 | 사용자 지역 단위 분배 |
| 영향 범위 파악 | 어려움 (랜덤 분배) | 명확 (지역 단위) |
달라지지 않은 것
- 리스크 분리 원칙: 플랫폼 이전과 네트워크 재설계는 여전히 별개 프로젝트입니다
- 롤백 우선 설계: 리스너 규칙 삭제 한 줄로 즉시 원복 가능합니다
- DB 커넥션 안전 마진 검증: 병렬 운영 중 커넥션 합산을 숫자로 확인합니다
- 크론 전환 주의: 배치 잡 중복 실행 방지를 위한 순서 관리는 동일합니다
- Datadog 사이드카 패턴: Fargate에서도 Task 내 사이드카 컨테이너로 동일하게 적용됩니다
Source IP 기반 라우팅의 한계와 대응
이 방식이 완벽한 건 아닙니다. 몇 가지 한계를 인지하고 있습니다.
VPN/프록시 사용자
사용자가 VPN을 사용하면 실제 위치와 다른 지역의 IP로 요청이 들어옵니다. 하지만 이 서비스의 특성상 대부분의 API 요청은 서버 간 통신이거나 특정 클라이언트 앱에서 발생하므로, VPN으로 인한 라우팅 오류는 무시할 수준입니다.
CIDR 블록의 정확도
ISP의 IP 할당은 변경될 수 있으므로, 등록한 CIDR 블록이 정확히 의도한 지역만 커버한다는 보장은 없습니다. 다만 카나리 단계에서는 정확한 지역 구분보다 “전체가 아닌 일부 트래픽을 분리해서 보내는 것” 자체가 목적이므로, 약간의 오차는 허용 가능합니다.
ALB 리스너 규칙 수 제한
ALB는 리스너당 규칙 수에 제한이 있습니다 (기본 100개). CIDR 블록을 너무 잘게 쪼개면 규칙 수가 늘어날 수 있으므로, 가능한 한 큰 단위의 CIDR로 묶어서 관리합니다.
마치며
방향이 바뀐 것은 사실이지만, 바뀐 이유가 명확하다면 방향 전환은 후퇴가 아닙니다.
ECS on EC2에서 Fargate로 돌아간 건 “EC2가 나빠서”가 아니라, 현재 팀의 규모와 역량에서 관리 포인트를 최소화하는 것이 더 중요하다는 판단 때문입니다. Source IP 기반 카나리로 바꾼 건 “가중치 방식이 틀려서”가 아니라, 영향 범위를 명확히 특정할 수 있는 방식이 운영 안정성에 더 유리하다는 판단 때문입니다.
이전 글에서 강조했던 세 가지 원칙은 여전히 유효합니다.
- 리스크를 분리할 것 — 변경 사항을 한 번에 하나씩만 적용합니다
- 숫자로 검증할 것 — 감이 아니라 지표로 판단합니다
- 롤백 경로를 먼저 설계할 것 — 전진보다 후퇴가 더 중요합니다
다음 글에서는 실제로 Fargate Task를 띄우고 Stage 1 검증을 진행한 내용을 기록할 예정입니다.
Leave a comment