
월말마다 AWS 비용 리포트 보다가 NAT Gateway 항목에서 한숨 쉬어본 적 있다면 이 글이 도움이 될지도 모르겠다. 우리 팀도 작년에 비슷한 상황이었고, VPC Endpoint 몇 개 깔아둔 것만으로 NAT 처리 비용이 한 달 기준 40% 가까이 빠졌다. 거창한 아키텍처 변경 없이.
이번 4월 AWS 비용 가이드들을 다시 훑어봤는데 NAT Gateway 단가는 여전히 시간당 $0.045, GB당 $0.045다. 게이트웨이 하나 띄워놓으면 가만히 있어도 월 $32. 거기에 처리량까지 붙으니 트래픽 많은 클러스터는 NAT 항목 하나가 인스턴스 비용을 추월하는 일도 흔하다. 이 글은 그 비용을 내리는 가장 확실한 방법인 VPC Endpoint 적용 가이드다.
어디부터 손대야 하나
VPC Endpoint는 두 종류다. Gateway Endpoint는 S3와 DynamoDB 두 서비스 전용이고 무료다. Interface Endpoint는 그 외 거의 모든 AWS 서비스용이고, 시간당 $0.01 + GB당 $0.01이 붙는다.
이게 핵심이다. S3와 DynamoDB는 무조건, 묻지도 따지지도 말고 Gateway Endpoint를 깔아라. 비용도 안 들고 NAT을 우회한다. 안 깔 이유가 없다.
Interface Endpoint는 손익분기를 따져야 한다. 서비스 1개당 시간당 $0.01이면 월 약 $7.2. 거기에 GB당 $0.01이 붙는데, NAT은 GB당 $0.045이니 GB당 $0.035가 절약된다. 즉 월 200GB 정도 처리량이 넘는 서비스부터 Interface Endpoint를 까는 게 이득이다. AZ가 3개면 endpoint도 AZ별로 깔리니 그만큼 시간 비용은 곱해진다. 이 부분에서 계산이 좀 애매한데, 우리 팀에서는 처음에 모든 서비스에 다 깔았다가 ECR/STS/Logs 빼면 트래픽이 미미한 게 많아서 결국 정리했다.
어떤 Endpoint가 효과 큰가
우리 팀 경험 기준으로 우선순위를 매기면 이렇다.
- S3 Gateway Endpoint — 컨테이너 이미지 레이어, 로그 백업, 아티팩트 다운로드까지 다 여기로 빠진다. 무료니까 그냥 깔아라
- ECR (api + dkr) — Pod 스케일 아웃 자주 발생하는 클러스터에서 효과 가장 크다. 둘 다 깔아야 한다. dkr만 깔면 매니페스트 조회가 NAT으로 빠진다
- Logs (CloudWatch Logs) — 컨테이너 로그를 CloudWatch로 보내고 있다면 이게 의외로 트래픽 많다
- STS — IRSA(IAM Roles for Service Accounts) 쓰면 Pod이 토큰 받을 때마다 STS를 친다. 트래픽 자체는 적은데 호출 빈도가 높아서 Latency 측면에서도 도움된다
- Secrets Manager / SSM — 시크릿 자주 가져오는 워크로드면 검토
DynamoDB Gateway Endpoint도 무료니까 DDB 쓰면 그냥 깔자.
Terraform으로 한방에
콘솔에서 끄적이지 말고 코드로 박아두자. AZ 추가될 때마다 골치 아파진다.
data "aws_region" "current" {}
data "aws_route_tables" "private" {
vpc_id = var.vpc_id
filter {
name = "tag:Tier"
values = ["private"]
}
}
# Gateway Endpoint (S3, DynamoDB) — 무료
resource "aws_vpc_endpoint" "s3" {
vpc_id = var.vpc_id
service_name = "com.amazonaws.${data.aws_region.current.name}.s3"
vpc_endpoint_type = "Gateway"
route_table_ids = data.aws_route_tables.private.ids
}
resource "aws_vpc_endpoint" "dynamodb" {
vpc_id = var.vpc_id
service_name = "com.amazonaws.${data.aws_region.current.name}.dynamodb"
vpc_endpoint_type = "Gateway"
route_table_ids = data.aws_route_tables.private.ids
}
# Interface Endpoint — 트래픽 많은 서비스에만
locals {
interface_services = [
"ecr.api",
"ecr.dkr",
"logs",
"sts",
]
}
resource "aws_vpc_endpoint" "interface" {
for_each = toset(local.interface_services)
vpc_id = var.vpc_id
service_name = "com.amazonaws.${data.aws_region.current.name}.${each.value}"
vpc_endpoint_type = "Interface"
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.vpce.id]
private_dns_enabled = true
}
resource "aws_security_group" "vpce" {
name = "vpce-shared"
description = "Allow HTTPS from VPC to Interface Endpoints"
vpc_id = var.vpc_id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [var.vpc_cidr]
}
}
private_dns_enabled = true가 중요하다. 이게 켜져 있어야 Pod이나 EC2 입장에서는 코드 한 줄 안 고쳐도 자동으로 Endpoint를 탄다. SDK가 도메인 그대로(logs.ap-northeast-2.amazonaws.com 등) 호출하면 VPC 내부 Route53 Resolver가 endpoint의 ENI IP로 답을 준다.
적용 후 검증
깔아놓고 끝이 아니다. 진짜 NAT 우회되고 있는지 확인해야 한다. 이거 안 하다가 "분명 깔았는데 비용이 안 빠지네?" 하는 경우가 꽤 있다.
가장 확실한 건 VPC Flow Logs를 켜고 NAT의 ENI 트래픽을 봐서 S3나 ECR 호출이 사라졌는지 보는 거다. Athena로 쿼리 한 방이면 끝난다.
SELECT
dstaddr,
SUM(bytes) / 1024 / 1024 / 1024 AS gb
FROM vpc_flow_logs
WHERE date = '2026-04-25'
AND srcaddr LIKE '10.%.%.%' -- private subnet 대역
AND dstaddr NOT LIKE '10.%' -- VPC 외부로 나가는 것만
GROUP BY dstaddr
ORDER BY gb DESC
LIMIT 50;
여기서 S3 prefix list IP나 ECR 도메인이 상위에 잡히면 endpoint가 동작 안 하고 있다는 뜻이다. 보통 원인은 두 가지: Gateway Endpoint를 라우트 테이블에 안 붙였거나, Interface Endpoint의 private_dns_enabled를 깜빡한 경우.
비용 측면 검증은 Cost Explorer에서 NAT Gateway → DataProcessing-Bytes 항목을 일주일 단위로 비교하면 된다. 우리 팀 케이스에선 적용 첫 주에 NAT 처리량이 60% 가까이 뚝 떨어졌고, Endpoint 비용이 그 자리를 일부 채웠지만 합산해서 월 $400 정도 줄었다. 단일 클러스터 기준이다.
흔히 빠지는 함정 몇 개
S3 Endpoint Policy 잠금 — 회사 정책으로 S3 Endpoint Policy를 빡빡하게 거는 경우가 있는데, 이게 잘못 걸리면 ECR이 S3로 레이어 받을 때 막혀서 Pod이 ImagePullBackOff로 굴러간다. ECR가 사용하는 S3 버킷(prod-{region}-starport-layer-bucket)은 항상 허용되어야 한다.
한 region에 같은 서비스 endpoint 중복 — 예전에 여러 VPC를 통합하다가 같은 region에 ECR Endpoint를 두 번 깔았다. private DNS가 켜져 있으면 충돌난다. 이건 에러 메시지로 잘 알려준다.
VPC peering 너머의 endpoint 공유 — 이게 좀 까다로운데, peering 너머의 VPC에서 우리 Endpoint를 쓰게 하려면 private DNS를 끄거나, 별도 Route53 inbound resolver를 두거나 해야 한다. VPC 수가 많은 조직이면 PrivateLink + Route53 Resolver 조합을 검토하는 게 낫다.
마무리
Gateway Endpoint(S3/DDB) 두 개는 진짜 그냥 다 깔아두는 게 정답이다. 안 깔 이유가 없다. Interface Endpoint는 처음부터 다 까는 것보다 Cost Explorer에서 NAT data processing이 큰 서비스 위주로 골라서 까는 게 효율적이다. 다 깔면 비용이 오히려 늘 수도 있다.
다음에는 트랜짓 게이트웨이 환경에서 Endpoint를 중앙화하는 패턴(공유 VPC에 endpoint를 두고 spoke VPC들이 Route53 Resolver로 끌어 쓰는)도 한번 정리해보려고 한다. 그쪽이 VPC 많은 조직에서는 진짜 비용이 빠진다.
혹시 다른 절감 포인트 노하우 있으면 댓글 남겨주세요.
'AWS' 카테고리의 다른 글
| AWS EC2 Spot 비용 확인하기 (2) | 2024.11.15 |
|---|