Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

88장. VPC Endpoint — VPC 안에서 외부 서비스 접근

이 장에서 말하고자 하는 것

VPC 안에서 운영하다 보면 다음과 같은 호출이 자주 일어난다.

ECS Task → S3 GetObject
ECS Task → DynamoDB Query
ECS Task → Secrets Manager
ECS Task → ECR pull image

이 호출들은 AWS 서비스 자체 를 향한다.
그런데 기본적으로 이 호출은 인터넷을 거쳐서 나간다.

ECS (프라이빗 서브넷) → NAT Gateway → 인터넷 → S3

이 구조의 문제:

  • NAT Gateway 데이터 처리 비용이 든다
  • 트래픽이 굳이 인터넷을 거친다 (성능 · 보안)
  • NAT Gateway 가용성에 묶인다

이걸 풀어주는 게

VPC Endpoint

다.


1. VPC Endpoint가 하는 일

VPC 안에서 AWS 서비스로 가는 사설 길 을 연다

ECS (프라이빗 서브넷) → [VPC Endpoint] → S3
                       (인터넷 안 거침)
  • NAT Gateway 비용 없음
  • 트래픽이 AWS 백본 안에서만 흐름
  • IAM과 결합한 추가 보안 통제 가능

2. 두 종류의 Endpoint

Gateway Endpoint

  • 라우팅 테이블에 항목을 추가하는 방식
  • S3, DynamoDB 만 지원
  • 무료
  • 서브넷에 ENI를 만드는 방식
  • 거의 모든 AWS 서비스 지원 (Secrets Manager, ECR, KMS, SQS, SNS, …)
  • 시간당 + 데이터 처리 비용 있음

S3 · DynamoDB → Gateway (무료)
그 외 → Interface


3. Gateway Endpoint 동작

라우팅 테이블에 추가:
  prefix list "com.amazonaws.region.s3"  →  vpce-xxxx

ECS Task가 S3 호출
  ↓ 라우팅 테이블 매칭
  ↓ 인터넷이 아닌 VPC Endpoint로
  ↓ S3
  • 별도 IP 변경 필요 없음 (도메인 그대로)
  • 같은 리전의 S3만 가능

4. Interface Endpoint 동작

서브넷에 ENI 생성 (사설 IP)
  ↓
"secretsmanager.ap-northeast-2.amazonaws.com" 도메인이
이 ENI를 가리키도록 사설 DNS 자동 설정

ECS Task → 도메인 호출 → 사설 IP → ENI → 서비스
  • 사설 DNS가 자동으로 작동 (enable_dns_hostnames = true 등)
  • AZ 별로 ENI를 둬야 가용성 보장

5. 보안 — Endpoint Policy

Endpoint에도 정책을 붙일 수 있다.

"이 VPC Endpoint를 통해서는 우리 버킷만 접근 가능"

S3의 경우 강력한 보안 패턴:

Bucket Policy:
  "특정 VPC Endpoint를 통해서만 접근 허용"

이러면 외부 인터넷이나 다른 VPC 에서는 그 버킷에 접근 불가.


같은 Interface Endpoint 메커니즘으로 내 서비스를 다른 VPC에 노출 할 수도 있다.

[Provider VPC]
  NLB → PrivateLink Service
                ↑
[Consumer VPC]
  Interface Endpoint → 내부망 통신
  • SaaS · 사내 서비스 공유에 자주 쓰는 패턴
  • 인터넷 노출 없이 안전한 다중 VPC 연결

7. 우리 서비스에서

Gateway Endpoint:
  ├─ S3        (NAT 비용 절감 큼)
  └─ DynamoDB  (NAT 비용 절감)

Interface Endpoint:
  ├─ ECR + ECR DKR (Task 시작 빠름, NAT 절감)
  ├─ Secrets Manager
  ├─ Logs (CloudWatch Logs)
  ├─ SSM
  ├─ KMS
  └─ STS

ECS Fargate 운영에서는 ECR · Logs · SSM Interface Endpoint 가 NAT 비용을 가장 크게 줄인다


8. NAT vs VPC Endpoint — 비용 비교

NAT Gateway: 시간당 + 처리 GB당 ($0.045/GB 수준)
S3 Gateway Endpoint: 무료
Interface Endpoint: 시간당 + 처리 GB당 (NAT의 약 60~70%)

S3 트래픽이 많다면 Gateway Endpoint 만 켜도 월 수십만 원 이상 절감되는 일이 흔하다.


9. 직접 확인해보기 — CLI

Gateway Endpoint (S3)

aws ec2 create-vpc-endpoint \
  --vpc-id <vpc-id> \
  --service-name com.amazonaws.ap-northeast-2.s3 \
  --vpc-endpoint-type Gateway \
  --route-table-ids <rtb-id-1> <rtb-id-2>

Interface Endpoint (Secrets Manager)

aws ec2 create-vpc-endpoint \
  --vpc-id <vpc-id> \
  --service-name com.amazonaws.ap-northeast-2.secretsmanager \
  --vpc-endpoint-type Interface \
  --subnet-ids <subnet-a> <subnet-b> \
  --security-group-ids <sg-endpoint>

동작 확인

# Task 안에서
dig secretsmanager.ap-northeast-2.amazonaws.com
# → 사설 IP (10.0.x.x) 가 응답되어야 함

10. 코드로는 이렇게 생겼다 — Terraform

# Gateway Endpoint
resource "aws_vpc_endpoint" "s3" {
  vpc_id            = aws_vpc.main.id
  service_name      = "com.amazonaws.ap-northeast-2.s3"
  vpc_endpoint_type = "Gateway"
  route_table_ids   = [aws_route_table.private.id]
}

resource "aws_vpc_endpoint" "dynamodb" {
  vpc_id            = aws_vpc.main.id
  service_name      = "com.amazonaws.ap-northeast-2.dynamodb"
  vpc_endpoint_type = "Gateway"
  route_table_ids   = [aws_route_table.private.id]
}

# Interface Endpoint (보안 그룹은 443 인바운드 허용)
resource "aws_security_group" "endpoints" {
  name   = "vpc-endpoints"
  vpc_id = aws_vpc.main.id

  ingress {
    from_port       = 443
    to_port         = 443
    protocol        = "tcp"
    security_groups = [aws_security_group.task.id]
  }
}

locals {
  interface_endpoints = [
    "ecr.api", "ecr.dkr", "secretsmanager",
    "logs", "ssm", "kms", "sts"
  ]
}

resource "aws_vpc_endpoint" "interface" {
  for_each            = toset(local.interface_endpoints)
  vpc_id              = aws_vpc.main.id
  service_name        = "com.amazonaws.ap-northeast-2.${each.value}"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = [aws_subnet.private_a.id, aws_subnet.private_b.id]
  security_group_ids  = [aws_security_group.endpoints.id]
  private_dns_enabled = true
}

private_dns_enabled = true 가 핵심 — 도메인이 자동으로 사설 IP를 가리킨다.


11. 이렇게 쓰면 망한다 — 안티패턴

안티패턴 1. NAT Gateway만 두고 모든 트래픽을 인터넷으로

S3 · ECR 트래픽이 누적되면 NAT 비용이 폭증한다.

가장 먼저 S3 Gateway Endpoint를 켠다

안티패턴 2. Interface Endpoint를 한 AZ에만 둔다

그 AZ가 죽으면 그 서비스 호출이 전부 실패.

사용하는 AZ 모두에 ENI

안티패턴 3. Endpoint 보안 그룹을 잘못 잡는다

Task SG에서 오는 443이 막혀 있으면 호출이 안 된다.

안티패턴 4. Bucket Policy로 Endpoint 제한을 걸고 다른 길도 열어둔다

한 길은 막고 다른 길로는 풀려 있으면 무의미.

S3 버킷 정책에서 “오직 이 VPC Endpoint” 만 허용


12. 한 줄로 정리

VPC Endpoint는 VPC 안에서 AWS 서비스로 가는 사설 길이며,
NAT 비용 절감과 보안 강화를 동시에 푼다


13. 이 장의 핵심 정리

  1. VPC Endpoint는 Gateway (S3 · DynamoDB) 와 Interface (그 외) 두 종류다.
  2. Gateway는 무료, Interface는 시간/GB 비용이 있지만 NAT보다 싸다.
  3. ECS Fargate는 ECR · Logs · SSM · Secrets Manager Interface Endpoint가 큰 차이를 만든다.
  4. Bucket Policy + Endpoint Policy로 S3 접근을 VPC 안으로 한정할 수 있다.
  5. Interface Endpoint는 사용하는 모든 AZ에 ENI를 둔다.
  6. NAT만 두지 않는다 — 가장 먼저 S3 Gateway Endpoint를 켠다.