- Published on
VPC NAT Gateway 비용 폭증 10분 진단·절감
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서버 비용은 대체로 서서히 오르지만, VPC NAT Gateway는 어느 날 갑자기 청구서가 ‘점프’하는 대표 항목입니다. 이유는 단순합니다. NAT는 시간당(게이트웨이 시간) 과 처리 데이터(GB당) 두 축으로 과금되는데, 애플리케이션 변경·배포·로그/메트릭 설정 변경·엔드포인트 경로 하나만 바뀌어도 대량의 아웃바운드가 한 지점(NAT)으로 몰리기 때문입니다.
이 글은 “원인 분석에 하루를 쓰지 않고” 10분 안에 폭증 원인을 특정하고, 바로 적용 가능한 **절감 레버(경로 변경/엔드포인트 추가/캐시/아키텍처 분리)**를 제시합니다.
0) NAT Gateway 과금 구조부터 30초 정리
NAT Gateway 비용은 보통 아래 3가지로 폭증합니다.
- NAT Gateway Hourly: NAT를 AZ별로 두면 AZ 수만큼 시간당 과금이 누적
- NAT Data Processing (GB): 사설 서브넷 인스턴스가 인터넷/공개 AWS 서비스로 나가는 바이트가 모두 과금
- 추가 전송 비용: AZ 크로스(다른 AZ의 NAT 사용) 또는 VPC 간 트래픽 구조에 따라 전송비가 붙을 수 있음
즉, “NAT가 많아졌거나(시간당)” 혹은 “NAT를 통과하는 바이트가 늘었거나(GB당)” 둘 중 하나입니다.
1) 10분 진단 플로우(가장 빠른 순서)
아래 순서대로 보면, 대부분 10분 내에 범인이 잡힙니다.
1-1. Cost Explorer에서 ‘NAT Data Processing’ 급증 여부 확인(2분)
- Cost Explorer → 서비스: Amazon VPC
- Usage type 그룹핑에서 다음 키워드를 찾습니다.
NatGateway-HoursNatGateway-Bytes/NATGateway-DataProcessing-Bytes(계정/리전 표기 차이 가능)
판단
Hours가 늘면: NAT 개수 증가, AZ별 NAT 추가, 테스트용 NAT 미삭제가 1순위Bytes가 늘면: 트래픽 경로/대상 서비스가 바뀐 것
1-2. CloudWatch NAT Gateway 지표로 ‘언제부터’와 ‘얼마나’(2분)
NAT Gateway는 CloudWatch에 핵심 지표를 제공합니다.
BytesOutToDestination,BytesInFromDestinationActiveConnectionCount,ConnectionAttemptCount
팁: 비용 폭증 시작 시각을 잡으면, 그 시각의 배포/배치/스케줄러/로그 설정 변경과 바로 매칭됩니다.
1-3. VPC Flow Logs로 “누가/어디로”를 1차 특정(4분)
NAT 비용의 실질 원인은 어떤 사설 리소스가 어떤 목적지로 나가느냐입니다. Flow Logs를 켜면 소스 ENI/서브넷/인스턴스까지 좁힐 수 있습니다.
- VPC 또는 서브넷 레벨 Flow Logs 활성화
- Destination(목적지) IP/포트, Source(소스) ENI/주소 기준으로 상위 트래픽을 집계
CloudWatch Logs 비용도 같이 튈 수 있으니(Flow Logs 자체가 로그) 로그 비용 급증도 함께 점검하는 게 좋습니다. 관련해서는 CloudWatch Logs 비용 폭증 원인과 절감 10가지도 같이 보세요.
1-4. “AWS 서비스인데 NAT를 타고 있나?”를 즉시 확인(2분)
가장 흔한 케이스는 이겁니다.
- S3, ECR, CloudWatch, STS, KMS, Secrets Manager 등 AWS 서비스 호출이 NAT를 경유
- 원래는 VPC Endpoint로 빠져야 하는데, 엔드포인트가 없거나 라우팅/DNS 설정이 어긋남
이 경우는 VPC Endpoint 추가만으로 NAT Data Processing을 크게 줄일 수 있습니다.
2) NAT 비용 폭증 ‘대표 원인’ 7가지와 즉시 대응
2-1. S3 다운로드/업로드가 NAT로 나감(가장 흔함)
증상
- 배치/ETL, 모델 다운로드, 아티팩트 업로드가 늘면서
NatGateway-Bytes급증
대응
- S3 Gateway Endpoint 추가(가장 강력)
- S3 접근이 특정 버킷 위주면 Endpoint policy로 범위 제한
2-2. ECR 이미지 풀/푸시가 NAT로 나감(ECS/EKS에서 자주 발생)
증상
- 배포 횟수 증가, 노드 스케일 아웃으로 이미지 풀 트래픽 폭발
대응
- ECR Interface Endpoint(api, dkr) + S3 Gateway Endpoint(레이어 전송이 S3를 쓰는 케이스가 많음)
- 노드 로컬 캐시/이미지 프리풀 전략
2-3. CloudWatch Logs/Metric/OTel Exporter가 NAT를 태움
증상
- 로깅 레벨 변경, 샘플링 해제, 디버그 로그 증가 직후 NAT 바이트 폭증
대응
- CloudWatch Logs/Monitoring 관련 Interface Endpoint 고려
- 애플리케이션 로그 샘플링/버퍼링/전송 주기 조정
2-4. 외부 API 호출(결제/지도/LLM 등) 폭증
증상
- 특정 마이크로서비스가 외부로 대량 호출 → NAT 집중
대응
- 캐시(CloudFront/ElastiCache) 또는 응답 재사용
- 동시성 제한, 재시도 정책 점검(무한 재시도는 NAT를 태웁니다)
- 타임아웃/재시도 설계는 Python httpx ReadTimeout·ConnectError 재시도 설계 같은 원칙을 적용해 “폭주형 재시도”를 제거
2-5. AZ 크로스 NAT(다른 AZ의 NAT로 라우팅)
증상
- NAT는 1개인데 서브넷은 여러 AZ → 일부는 다른 AZ NAT로 나감
- 전송비(크로스 AZ) + NAT 바이트가 함께 증가
대응
- AZ별 NAT Gateway를 두고 각 프라이빗 서브넷이 같은 AZ NAT를 사용하도록 라우트 테이블 분리
- 반대로 “시간당 비용”이 부담이면, 트래픽 패턴에 따라 단일 NAT + 크로스 비용을 비교(정답은 트래픽에 따라 다름)
2-6. IPv6 경로 미사용(IPv4 NAT 강제)
증상
- 외부 목적지가 IPv6 지원인데도 IPv4만 사용 → NAT 필수
대응
- 가능하면 Dual-stack(IPv4/IPv6) 로 전환하고, IPv6는 Egress-Only Internet Gateway 경로를 검토(워크로드/보안정책에 따라 적용)
2-7. 프록시/에이전트가 대량 업로드(로그/덤프/코어파일)
증상
- 장애 덤프 업로드, 대형 파일 업로드가 반복
대응
- 업로드 대상이 AWS라면 Endpoint로 전환
- 업로드 크기/주기 제한, 압축, 청크 업로드 적용
3) “원인 특정”을 위한 VPC Flow Logs 쿼리 예시(CloudWatch Logs Insights)
Flow Logs를 CloudWatch Logs로 보낸 경우, 아래처럼 상위 송신자를 빠르게 찾을 수 있습니다.
fields @timestamp, interfaceId, srcAddr, dstAddr, dstPort, bytes, action
| filter action = "ACCEPT"
| stats sum(bytes) as total_bytes by srcAddr, dstAddr, dstPort
| sort total_bytes desc
| limit 20
srcAddr가 특정 프라이빗 IP 대역/인스턴스로 좁혀지면 해당 워크로드의 아웃바운드 설정(배포 시각, 크론, 스케일링)을 바로 추적합니다.dstAddr가 AWS 퍼블릭 IP로 보이면(예: S3 퍼블릭 엔드포인트), 엔드포인트 미구성이 의심됩니다.
4) 즉시 절감 레버 6가지(효과 큰 순서)
4-1. VPC Endpoint를 먼저 깔아라(가장 ROI 큼)
- S3: Gateway Endpoint
- ECR/CloudWatch/STS/KMS/Secrets Manager 등: Interface Endpoint
Endpoint 적용 후에는 해당 서비스 트래픽이 NAT를 우회하는지(CloudWatch NAT Bytes 하락)로 검증합니다.
4-2. NAT를 ‘필요한 서브넷’에만 연결(라우트 테이블 최소화)
프라이빗 서브넷이라고 해서 모두 인터넷이 필요하지 않습니다.
- DB 서브넷, 내부 전용 워커는 NAT 경로 제거
- “기본 라우트(0.0.0.0/0)”가 NAT로 향하는 라우트 테이블이 과도하게 붙어 있는지 점검
4-3. 아웃바운드가 많은 워크로드를 퍼블릭 서브넷으로 옮길지 검토
보안팀 정책이 허용한다면,
- 외부 호출이 많은 배치/크롤러는 퍼블릭 서브넷 + 보안그룹 제한 + 고정 EIP로 운영하는 편이 더 쌀 수 있습니다.
- 단, 인바운드는 최소화하고, 아웃바운드만 필요할 때에 한합니다.
4-4. 캐시/미러링으로 “같은 다운로드”를 줄이기
- 모델/아티팩트/패키지 다운로드는 S3/CloudFront 캐시, 내부 아티팩트 리포지토리(예: CodeArtifact, Nexus)로 전환
- 컨테이너 이미지는 노드 풀에서 프리풀/캐시
4-5. 재시도/폴링/헬스체크 트래픽을 줄이기
NAT 바이트 폭증의 숨은 원인은 “정상 트래픽”이 아니라
- 과도한 폴링
- 실패 후 공격적인 재시도
- 짧은 타임아웃으로 인한 반복 연결
입니다. 외부 API/프록시 타임아웃이 흔들리면 트래픽이 기하급수로 늘 수 있으니, 애플리케이션 레벨에서 재시도 상한과 지수 백오프를 강제하세요.
4-6. NAT Gateway 수/AZ 전략 재검토
- 트래픽이 큰 서비스: AZ별 NAT로 크로스 AZ 전송비/지연 감소
- 트래픽이 작고 NAT 시간당이 부담: 단일 NAT(단, 장애 허용/리스크 고려)
정답은 “가용성과 비용”의 트레이드오프입니다.
5) Terraform 예시: S3 Gateway Endpoint로 NAT 우회
아래는 S3 트래픽을 NAT 대신 VPC 내부로 돌리는 가장 전형적인 구성입니다.
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.${var.region}.s3"
vpc_endpoint_type = "Gateway"
route_table_ids = [
aws_route_table.private_a.id,
aws_route_table.private_b.id
]
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = "*"
Action = ["s3:GetObject", "s3:PutObject", "s3:ListBucket"]
Resource = [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
}]
})
}
적용 후 검증:
- NAT Gateway
BytesOutToDestination가 유의미하게 감소 - S3 요청이 정상 동작(특히 버킷 정책/엔드포인트 정책 충돌 여부)
6) 운영 체크리스트(재발 방지)
6-1. 알람
- NAT
BytesOutToDestination가 평소 대비 N배 증가 시 알람 - Cost Anomaly Detection에서 Amazon VPC 비용 감시
6-2. 배포 파이프라인에 “엔드포인트/라우팅 변경 감지” 넣기
- 새 워크로드가 S3/ECR/CloudWatch를 쓰면 VPC Endpoint 유무를 자동 점검
- 프라이빗 서브넷에서 0.0.0.0/0 NAT 라우트가 추가되면 PR에서 경고
6-3. 로그/메트릭 폭주도 같이 본다
NAT 폭증과 CloudWatch Logs 폭증은 종종 같은 사건(로그 레벨 변경, exporter 설정 오류)에서 동시에 터집니다. 로그 비용 쪽도 함께 점검하면 원인 파악이 빨라집니다.
7) 10분 결론: 가장 많이 먹히는 ‘한 방’
- NAT Bytes 폭증이면: 1) Flow Logs로 상위 송신자/목적지 식별 → 2) 대상이 AWS 서비스면 VPC Endpoint로 우회 → 3) 외부 API면 캐시/재시도/폴링을 줄여 트래픽 자체를 깎기
- NAT Hours 폭증이면: NAT가 늘어난 이유(멀티 AZ, 테스트 리소스, 환경 분리)를 확인하고 불필요 NAT를 정리
NAT Gateway 비용은 “아키텍처가 잘못됐다”기보다, 대개 경로가 한 번 틀어진 결과입니다. 위 플로우대로 보면, 대부분은 라우팅/엔드포인트/로그 설정 중 하나에서 10분 안에 답이 나옵니다.