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)
⚠️ 문제 상황
- API Gateway로 요청시 503 Service Unavailable
- NLB DNS로는 정상 응답
- 타겟 그룹에는 일부 노드만 Healthy
- 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 연결을 직접 구성해야 합니다.
'CLOUD > AWS' 카테고리의 다른 글
| [EKS + NLB 연동 시 Ingress Controller 구성 전략 비교] (0) | 2025.07.31 |
|---|---|
| EKS에서 ALB 상태검사와 target-type: ip 이슈 정리EKS에서 ALB (1) | 2025.07.30 |
| AWS EKS 의 OIDC와 IRSA 란? (1) | 2025.07.28 |
| [AWS EKS] aws-auth와 iam role 확인 (0) | 2025.07.24 |
| AWS EKS의 version을 Terraform으로 업그레이드 (0) | 2025.06.14 |
댓글