AWS EKS에서 Kubernetes 서비스에 NLB(Network Load Balancer)를 연동할 때,
externalTrafficPolicy 설정에 따라 NLB의 타겟 헬스체크 상태가 다르게 표시되는 현상을 종종 마주하게 됩니다.
이 글에서는 특히 Ingress Controller를 사용할 때와 일반적인 서비스(e.g. echo-service)를 사용할 때
externalTrafficPolicy=Cluster일 때의 동작이 왜 다르게 보이는지를 기술적으로 분석합니다.
✅ externalTrafficPolicy 란?
Kubernetes 서비스에서 외부로부터 들어온 트래픽을 어떻게 Pod에 전달할 것인지를 결정하는 설정입니다.
| 설정 값 | 설명 |
| Cluster | 트래픽이 도달한 노드에 파드가 없어도 kube-proxy가 클러스터 내 다른 파드로 라우팅 |
| Local | 트래픽이 도달한 노드에 파드가 있어야만 응답. kube-proxy 우회, 소스 IP 보존 가능 |
🧪 테스트 사례
다음 두 가지 경우에 대해 NLB의 타겟 그룹 헬스체크 상태를 비교했습니다:
1. 일반 서비스 (echo-service)
apiVersion: v1
kind: Service
metadata:
name: echo-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
type: LoadBalancer
externalTrafficPolicy: Cluster
selector:
app: echo
ports:
- port: 80
targetPort: 5678
파드는 여러 노드 중 한 노드에만 배포했고,
externalTrafficPolicy=Cluster로 설정했습니다.
2. Ingress Controller (NGINX)
controller:
replicaCount: 1
nodeSelector:
kubernetes.io/hostname: ip-10-0-11-39
service:
type: LoadBalancer
externalTrafficPolicy: Cluster
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
Ingress Controller는 오직 하나의 노드에만 배치했습니다.
🔍 실험 결과 비교
| 항목 | echo-service | nginx-ingress (1노드만 배포) |
| NLB Target 상태 | 모든 노드가 Healthy | 일부 노드만 Healthy |
| 트래픽 전달 방식 | kube-proxy가 파드가 있는 노드로 라우팅 | NodePort를 통해 Ingress Pod에 직접 전달 |
| 실패 원인 가능성 | 거의 없음 (라우팅만 되면 OK) | Ingress Pod이 없으면 연결 자체 실패 |
🧠 왜 이런 차이가 날까?
✅ echo-service는 "클러스터 내의 파드 위치"만 알면 됨
- externalTrafficPolicy=Cluster일 때, kube-proxy는 NodePort로 받은 트래픽을 클러스터 내 어떤 노드에 있든 echo 파드로 라우팅 가능
- 즉, Node A → Node B (echo 있음) 이런 식으로 포워딩 가능
그래서 NLB는 모든 노드에서 헬스체크 응답을 받고 Healthy로 표시됩니다.
❗ 하지만 NGINX Ingress Controller는 다르다
Ingress Controller는 NodePort를 열고 있는 프록시 Pod 그 자체가 트래픽 진입 지점입니다.
- Node A에만 NGINX Pod가 있고,
- Node B에는 아무것도 없을 때,
NLB → Node B → NodePort로 들어간 요청은 라우팅할 Ingress Pod이 없으므로 connection refused 상태가 됩니다.
이건 kube-proxy가 "라우팅할 파드가 존재하지 않음"을 의미하며, 결과적으로 NLB는 해당 노드를 Unhealthy로 간주합니다.
📌 kube-proxy가 해주는 것과 못 해주는 것
| 항목 | echo-service | Ingress Controller |
| kube-proxy가 라우팅 가능한가? | ✅ 예 | ❌ 파드가 없으면 포트 자체가 없음 |
| NodePort 포트는 열려 있는가? | kube-proxy가 관리 → 포트 항상 열림 | Ingress Pod이 존재해야 포트가 열림 |
| 요청 도달 가능 여부 | 포워딩 가능 | 불가능 (Ingress Pod 직접 필요) |
🧩 결론
externalTrafficPolicy=Cluster는 단지 kube-proxy를 통해 라우팅을 허용할 뿐,
실제로 라우팅할 파드가 존재하지 않으면 아무것도 전달되지 않는다.
즉, 구조적으로:
- 일반 서비스는 어디든 파드가 있으면 되므로 Cluster 모드에서 안정적
- Ingress Controller는 NodePort를 열고 있는 Pod이 있어야만 정상 동작
✅ 해결 방법
1. Ingress Controller를 여러 노드에 배포
controller:
replicaCount: <노드 수>
또는
topologySpreadConstraints:
- maxSkew: 1
topologyKey: "kubernetes.io/hostname"
2. DaemonSet으로 각 노드에 하나씩 강제 배포
3. target-type=ip + externalTrafficPolicy=Local 구조로 전환
→ Pod IP를 직접 NLB 타겟으로 등록하여 kube-proxy 경유 우회 가능
🔚 마무리
externalTrafficPolicy=Cluster 설정만으로 모든 게 해결될 거라 생각하면 오산입니다.
서비스의 구조, 특히 Ingress Controller처럼 트래픽의 입구 역할을 하는 경우,
Pod의 실제 배치 위치가 NLB의 타겟 헬스체크에 직접적인 영향을 주는 것을 이해해야 합니다.
단순한 설정 하나에도 클러스터 내 구조적 이해가 필수인 이유,
이번 실험으로 확실히 체감하셨을 겁니다.
'CLOUD > AWS' 카테고리의 다른 글
| AWS Route 53 도메인에 SSL 인증서 발급 및 여러 리전 관리 방법 (0) | 2025.08.14 |
|---|---|
| AWS VPC에서 OpenVPN 스플릿 터널 구성 & 트러블슈팅 (2) | 2025.08.14 |
| AWS EKS NGINX Ingress Controller - hostNetwork에 따른 NLB 헬스체크 정상/비정상 분석 (0) | 2025.08.06 |
| api gateway 에서 root_method(/) 와 proxy_method({proxy+}) (1) | 2025.08.02 |
| [EKS + NLB 연동 시 Ingress Controller 구성 전략 비교] (0) | 2025.07.31 |
댓글