부제:
10.96.x.x에 붙은 프로세스는 없다. 커널의 NAT 룰이 목적지를 Pod로 바꿀 뿐
여기서부터는 시리즈 B(네트워킹과 격리의 안쪽) 다. 시리즈 A가 "이게 뭘
하는가"였다면, B는 "실제로 어떻게 그렇게 되는가" 의 기계를 연다.
시작은 A에서 계속 미뤄 둔 질문이다.
A4에서
나는 "ClusterIP는 주소만 보면 L3(IP)인데 :Port가 고정이고 kube-proxy가 포트
단위로 로드밸런싱해서 L4로 분류한다"고 정리했다. 그런데 그 kube-proxy가
정확히 어떻게 트래픽을 꽂는가? 이번 편은 그 답을 지금 이 클러스터의 실제
iptables 룰로 확인한다.
한 줄 정의부터
| 개념 | 한 줄 정의 |
|---|---|
| kube-proxy | Service 정의를 각 노드의 iptables 룰로 번역하는 데몬(DaemonSet) |
| KUBE-SERVICES | 목적지가 ClusterIP:Port면 서비스 체인으로 보내는 입구 룰 |
| KUBE-SVC-* | 엔드포인트들로 확률적으로 분기하는 체인 = L4 로드밸런싱 |
| KUBE-SEP-* | 최종 DNAT(목적지를 실제 Pod IP로 재작성)하는 체인 |
| KUBE-MARK-MASQ | 클러스터 밖에서 온 트래픽에 SNAT 표시(리턴 경로 보장) |
ClusterIP에는 아무도 살지 않는다
먼저 직관을 하나 깨야 한다. 10.96.177.199 같은 ClusterIP는 어떤 Pod의
주소도, 어떤 프로세스가 bind한 주소도 아니다. 그 IP로 ping을 쏴도 응답하는
실체가 없다. 그런데도 그 주소로 요청을 보내면 신기하게 Pod에 도착한다.
비밀은 커널의 iptables NAT 테이블에 있다. kube-proxy가 각 노드에서
"목적지가 이 ClusterIP면, 목적지를 실제 Pod IP로 몰래 바꿔치기(DNAT)하라"는
룰을 심어 둔 것이다. 즉 ClusterIP는 실체 있는 프록시가 아니라, 커널이 목적지를
재작성하도록 만든 규칙이다.

실제 룰을 그대로 떠 보기
말로만 하면 안 믿긴다. 그래서 이 클러스터의 kube-proxy 파드에서
iptables-save를 그대로 떴다. (kube-proxy는 iptables 바이너리를 갖고
hostNetwork로 도니, 파드에서 바로 노드의 룰을 볼 수 있다.)

세 단계로 읽힌다.
- ① 입구(KUBE-SERVICES) —
목적지 10.96.177.199 : 80인 TCP면
KUBE-SVC-RPZM…체인으로 보낸다. 서비스 하나당 이런 입구 룰이 하나씩 생긴다. - ② 서비스 체인(KUBE-SVC) — 여기가 로드밸런서다. 엔드포인트(Pod) 3개로
-m statistic --mode random --probability로 확률 분기한다. 이 확률 값이
묘하다 —0.333 → 0.5 → (나머지). - ③ 엔드포인트 체인(KUBE-SEP) — 고른 엔드포인트에서
DNAT --to-destination 10.244.0.21:80. 여기서 목적지가 ClusterIP → 실제 Pod IP로 바뀐다.
왜 확률이 0.333 → 0.5 → 나머지인가
균등하게 1/3씩 보내고 싶은데 왜 값이 제각각일까. iptables는 룰을 위에서부터
순차로 검사하기 때문이다.
- 첫 룰: 전체의 1/3(0.333)을 잡는다.
- 통과한 나머지 2/3 중 둘째 룰이 절반(0.5)을 잡는다 → 2/3 × 1/2 = 1/3.
- 마지막은 확률 조건 없이 남은 전부를 잡는다 → 1/3.
곱해 보면 정확히 균등한 1/3씩이다. 이 포트 단위 확률 분배가 바로 A4에서
"ClusterIP는 IP지만 L4 로드밸런서"라고 부른 것의 실체다. L3(IP)에서 한 일이
아니라, TCP 포트 레벨에서 트래픽을 나눈 L4 동작이다.
정리
- ClusterIP는 실체가 없다. 붙어 있는 프로세스가 아니라
KUBE-SERVICES ▸ KUBE-SVC(확률 분기) ▸ KUBE-SEP(DNAT) 이라는 커널 iptables
룰 뭉치다. - kube-proxy는 트래픽을 직접 나르지 않는다. Service 정의를 보고 iptables
룰을 심어 둘 뿐, 실제 패킷 처리는 커널이 한다. - A4의 "왜 L4인가"는 여기서 완결된다 — 포트 단위 확률 로드밸런싱 + DNAT.
그런데 이 방식에는 약점이 있다. 룰이 서비스 수에 비례해 선형으로 늘어난다.
서비스가 수천 개가 되면? 다음 편(B2)에서 iptables의 규모의 벽과, 그걸 넘는
IPVS·eBPF(Cilium) 로 이어 간다.
참고
- Kubernetes Docs — Virtual IPs and Service Proxies, kube-proxy
- 실제 룰 캡처:
docker-desktop클러스터(kube-proxy mode=iptables)에서iptables-save -t nat덤프
답글 남기기