본문 바로가기
CLOUD/AWS

AWS API Gateway + NLB + Ingress NGINX 연동 시 주의할 점과 라우팅 구조

by Rainbound-IT 2025. 7. 29.
반응형

EKS 환경에서 API Gateway를 사용해 외부 요청을 처리하고, 이를 NLB와 Ingress Controller를 통해 Kubernetes 내부 서비스로 전달하려는 구조는 꽤 흔한 패턴입니다. 하지만 이 구조는 "L4(Network Load Balancer)와 L7(Ingress NGINX)의 개념적 차이" 때문에 몇 가지 헷갈리는 지점이 있습니다.

이번 글에서는 제가 직접 구성하며 겪었던 문제들과 이를 해결해나가며 얻은 인사이트를 정리합니다.


📌 아키텍처 구성

[Client]
   │
   ▼
[API Gateway (HTTP API)]
   │    (HTTP_PROXY)
   ▼
[VPC Link]
   │
   ▼
[NLB (TCP Listener, internal)]
   │
   ▼
[Ingress NGINX Controller]
   │
   ▼
[Kubernetes Service / Pod]
  • API Gateway: HTTP API, integration_type = HTTP_PROXY
  • NLB: Internal, TCP Listener (port 80)
  • Ingress Controller: NGINX, Kubernetes LoadBalancer 서비스 (externalTrafficPolicy: Local)

⚠️ 문제 상황

  1. API Gateway로 요청시 503 Service Unavailable
  2. NLB DNS로는 정상 응답
  3. 타겟 그룹에는 일부 노드만 Healthy
  4. Ingress Controller는 LoadBalancer 타입

✅ 원인과 원리

1. NLB는 L4 (TCP) 수준만 처리한다

  • service.beta.kubernetes.io/aws-load-balancer-type: "nlb"로 생성된 NLB는 L4 수준의 로드밸런서를 생성합니다.
  • 즉, 패킷 전달만 하지, HTTP 요청을 해석하진 않습니다.

2. 하지만 HTTP 요청 자체는 통째로 전달된다

  • NLB는 TCP 레벨로 요청을 Ingress Controller에게 그대로 전달합니다.
  • 중요한 건, API Gateway가 HTTP Proxy 방식으로 요청을 생성해준다는 점입니다.
GET /hello HTTP/1.1
Host: api.example.com

→ 이 요청이 NLB → Ingress Controller까지 쭉 전달되면,
→ NGINX는 path(/hello)를 해석해 정상적으로 서비스 라우팅이 가능합니다.

💡 핵심: Ingress Controller가 "HTTP 요청" 형태로 받아야 path 기반 라우팅이 가능하다!


3. 타겟 그룹의 Healthy 조건

  • NLB는 Ingress Controller가 설치된 노드들의 NodePort를 대상으로 상태 체크를 합니다.
  • 만약 Ingress Pod가 일부 노드에만 떠 있으면 → 그 노드만 Healthy
  • 나머지는 Health Check 실패 → Unhealthy
  • 이때 externalTrafficPolicy = Local이면 Pod 없는 노드엔 트래픽이 전달되지 않음 → 문제 없음

4. 정상적인 Path 라우팅을 위한 조건 정리


 

조건 충족  여부설명
API Gateway가 HTTP 요청 생성 integration_type = HTTP_PROXY
Ingress Controller가 HTTP 수신 targetPort = http
NLB가 HTTP를 TCP로 전달 Listener = TCP, 그러나 payload는 HTTP
Ingress가 HTTP를 인식 path-based 라우팅 가능
 

 흔히 하는 오해

❌ "NLB는 TCP라서 HTTP 요청 못 받는다"

NLB는 해석은 안 해도, 전달은 합니다.
→ 결국 Ingress Controller가 HTTP 요청 형태로 받기만 하면 OK


✅ 결론

💡 Ingress Controller는 반드시 HTTP 요청을 직접 받아야만 path 기반 라우팅이 가능합니다.
따라서, API Gateway와 연동 시에는 반드시 HTTP_PROXY 방식 + HTTP API + NLB DNS 직접 연결 구조를 사용해야 합니다.


 참고 설정 예시 (Terraform)

 
resource "aws_apigatewayv2_integration" "example" {
  api_id             = aws_apigatewayv2_api.http_api.id
  integration_type   = "HTTP_PROXY"
  integration_method = "ANY"
  integration_uri    = "http://${data.aws_lb.ingress_nlb.dns_name}"
  connection_type    = "VPC_LINK"
  connection_id      = aws_apigatewayv2_vpc_link.vpc_link.id
  payload_format_version = "1.0"
}

 마무리

구성하면서 생기는 헷갈림은 대부분 **계층(L4 vs L7)**과 요청 흐름에 대한 이해에서 비롯됩니다.
API Gateway → NLB → Ingress → Pod 구조에서는 HTTP 요청이 최종적으로 어떻게 전달되느냐만 확실히 이해하면
안정적인 path 기반 라우팅이 가능해집니다.

 

 

 

추가

그런데 왜 LoadBalancer 타입이 안되는가?

  • LoadBalancer 타입을 사용하면 AWS에서 자동으로 NLB or CLB를 직접 프로비저닝합니다.
  • 하지만 이 NLB는 외부 연결용(public)이기 때문에,
    • 내부용(private) NLB를 따로 만들고
    • 그걸 API Gateway와 연결하려는 경우에는 맞지 않습니다.
  • 따라서 NLB를 직접 만들고, Ingress Controller는 NodePort로 지정하여 NLB → Node 연결을 직접 구성해야 합니다.
반응형

댓글