본문 바로가기
CLOUD/AWS

AWS EKS에서 externalTrafficPolicy 설정에 따른 NLB 헬스체크 동작 차이: Ingress Controller vs 일반 서비스

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

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 ControllerNodePort를 열고 있는 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의 타겟 헬스체크에 직접적인 영향을 주는 것을 이해해야 합니다.

단순한 설정 하나에도 클러스터 내 구조적 이해가 필수인 이유,
이번 실험으로 확실히 체감하셨을 겁니다.

반응형

댓글