NodePort 나 LoadBalancer 서비스에서는 외부 트래픽이 노드로 도착하면, 노드에서 쿠버네티스 클러스터 내의 적절한 파드로 로드밸런싱을 해준다. 즉, 트래픽을 받은 노드에 속한 파드로 전송되는 것이 보장되지 않는 것이다. 만약 LoadBalancer 서비스에서 외부 로드밸러서가 1차적으로 각 노드로 로드 밸런싱 중이라면, 노드에서 불필요한 2차 로드밸런싱이 이루어지는 형태가 된다.(NAT 가 발생해 발신측 IP 주소가 유실되는 문제도 있다.)
일반적인 파드의 경우는 각 노드에 1개 이상이 존재하는 것을 보장하지는 않기 때문에, 이러한 노드에서 파드로의 로드 밸런싱이 필요하다. 하지만, 데몬셋 같이 하나의 노드에 하나의 파드가 보장되는 경우에는 굳이 다른 노드의 파드로 로드 밸런싱 할 필요가 없어진다. 그런 경우에는 spec.externalTrafficPolicy 항목을 사용하여 외부 트래픽을 노드 내에서만 처리할지를 설정할 수 있다.
1. 노드 내에서만 로드 밸런싱 하도록 설정
아래의 매니페스트와 같이 spec.externalTrafficPolicy: Local 으로 생성한다. 외부로부터의 트래픽을 어떻게 로드밸런싱 할지에 대한 정책이기 때문에 당연히 NodePort, LoadBalancer 서비스에서 사용 가능하다.(ClusterIP 는 내부 트래픽이기 때문에 설정 불가능)
apiVersion: v1
kind: Service
metadata:
name: nodeport-local
spec:
type: NodePort
externalTrafficPolicy: Local
ports:
- name: "http-port"
protocol: "TCP"
port: 8080
targetPort: 80
nodePort: 30081
selector:
app: sample-app
| spec.externalTrafficPolicy 설정값 | 설명 |
| Cluster | 노드에 도착한 트래픽을 클러스터 내에 존재하는 다른 노드에 속한 파드까지 대상으로 하여 다시 로드밸런싱한다.(기본값) |
| Local | 노드에 도착한 트래픽을 해당 노드 내의 파드 대상으로만 로드밸런싱한다. |
이제 아래 커맨드로 파드가 1개 존재하는 desktop-worker 노드를 호출하면, 여러번 호출해도 동일한 파드로 요청이 가는 것을 볼 수 있다. client IP 주소도 유지된다.
# 서비스 IP, Port 확인
$ kubectl get svc nodeport-local
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
sample-nodeport-local NodePort 10.96.25.136 <none> 8080:30081/TCP 76m
# 파드 확인
$ kubectl get pods -o custom-columns="NAME:{metadata.name},Node:{spec.nodeName},NodeIP:{status.hostIP}"
NAME Node NodeIP
sample-deployment-75c768d5fb-2lkwp desktop-worker2 172.18.0.3
sample-deployment-75c768d5fb-9qdjm desktop-worker 172.18.0.4
sample-deployment-75c768d5fb-g5vkv desktop-worker2 172.18.0.3
# 아래 커맨드를 여러번 실행해본다.
$ curl -s http://172.18.0.4:30081
2. LoadBalancer 에서 노드 health check 하기
NodePort 서비스에서 spec.externalTrafficPolicy: Local 로 지정한 경우, 노드 내에 대상 파드가 하나도 없는 경우에는 TCP 수준의 Connection refused 에러가 발생한다. 목적지 포트를 Listen 하는 프로세스(파드)가 아예 없기 때문이다. 반면에 LoadBalancer 서비스에서는 spec.externalTrafficPolicy: Local, spec.healthCheckNodePort 를 지정하여(미지정시 랜덤 포트가 자동 지정됨) 외부 로드 밸런서가 해당 노드가 타겟 파드를 가지고 있는지 확인할 수 있게 한다.(헬스 체크) 해당 노드에 파드가 존재하지 않으면 http status 503 이 반환되고, 로드 밸런싱 대상에서 제외된다.
아래와 같은 매니페스트로 LoadBalancer 에 헬스 체크용 노드포트를 지정한다.(30086)
apiVersion: v1
kind: Service
metadata:
name: lb-local
spec:
type: LoadBalancer
externalTrafficPolicy: Local
healthCheckNodePort: 30086
ports:
- name: "http-port"
protocol: "TCP"
port: 8080
targetPort: 80
nodePort: 30085
selector:
app: sample-app
spec.healthCheckNodePort 는 LoadBalancer 서비스 이면서 spec.externalTrafficPolicy: Local 인 경우만 지정할 수 있는 항목이다. 아래는 헬스 체크 엔드포인트가 응답하는 예시이다.
$ curl -s http://172.18.0.4:30086
{
"service": {
"namespace": "default",
"name": "lb-local"
},
"localEndpoints": 1
}
'Kubernetes' 카테고리의 다른 글
| [Kubernetes] Multi Region 서비스에서 최소한의 latency 를 위한 Topology Aware Hint (0) | 2025.11.23 |
|---|---|
| [Kubernetes] 서비스 Session Affinity 설정 (0) | 2025.11.22 |
| [Kubernetes] LoadBalancer 서비스 이해 (0) | 2025.11.15 |
| [Kubernetes] NodePort 서비스 이해 (0) | 2025.11.15 |
| [Kubernetes] ClusterIP - externalIPs 서비스 이해 (0) | 2025.10.19 |
