서비스의 ClusterIP 는 어느 인터페이스에도 없는 가짜 주소다.
패킷이 그 주소로 나가면 커널 규칙이 실제 파드 IP 로 바꿔치기한다 (DNAT) kube-proxy 는 그 규칙을 만들고 갱신하는 데몬이다
세 가지 모드
-
iptables — 규칙을 iptables 체인으로 만든다
- 서비스가 많아지면 규칙이 선형으로 늘어 갱신이 느려진다
- 수천 개 규모에서 반영 지연이 체감된다
-
IPVS — 커널의 로드밸런서를 쓴다. 해시 기반이라 규모에 유리하다
- 여러 분배 알고리즘 지원 (rr · lc · sh …)
-
nftables — 최신 대안. iptables 의 확장성 문제를 개선한다
L4 라는 사실이 만드는 한계
HTTP 경로·헤더를 못 본다
- 경로 기반 라우팅은 인그레스/게이트웨이의 일이다
연결 단위로 분배한다
-
gRPC · HTTP/2 처럼 한 연결을 오래 쓰면 한 파드로 쏠린다
-
파드를 늘려도 트래픽이 안 나뉜다
-
대응
- 클라이언트 측 로드밸런싱 (헤드리스 서비스 + gRPC 클라이언트 LB)
- 서비스 메시 (사이드카가 요청 단위로 분배)
- L7 프록시를 앞에 둔다
규칙을 직접 보기
# iptables 모드
iptables -t nat -L KUBE-SERVICES -n | head
# IPVS 모드
ipvsadm -Ln | head
서비스는 있는데 연결이 안 될 때
- 엔드포인트가 비었는지 (대개 여기서 끝난다)
- kube-proxy 파드가 살아 있는지
- kubectl -n kube-system get ds kube-proxy
- 규칙이 실제로 만들어졌는지
세션 어피니티
spec:
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP: { timeoutSeconds: 10800 }
같은 클라이언트 IP 를 같은 파드로 보낸다
한계 — 프록시·NAT 뒤에 있는 클라이언트는 IP 가 같아 한 파드로 몰린다
- 세션은 외부 저장소(Redis)에 두는 편이 낫다
서비스 수가 많아지면
iptables 모드는 서비스마다 규칙 체인을 만든다
- 서비스 5,000개 · 파드 20,000개 규모에서
- 규칙 갱신에 수 초~수십 초가 걸린다
- 파드가 바뀔 때마다 반영이 늦어진다
- 배포 중 일시적으로 죽은 파드로 트래픽이 간다
대응
- IPVS 또는 nftables 모드로 전환
- 서비스 수 자체를 줄인다 (헤드리스·게이트웨이로 통합)
- eBPF 기반 CNI 는 kube-proxy 를 대체하기도 한다 (Cilium)
kube-proxy 를 안 쓰는 구성
Cilium 같은 eBPF CNI 는 kube-proxy 없이 서비스를 처리한다
- iptables 규칙 대신 eBPF 프로그램
- 규모가 커져도 성능이 유지된다
- 원본 IP 보존·관측성에서 유리하다
클라우드 관리형에서도 선택지로 제공되는 경우가 늘고 있다
면접 함정
- ❌ "ClusterIP는 실제 IP다" → 어느 인터페이스에도 없다. 커널 규칙이 바꿔치기한다.
- ❌ "파드를 늘리면 gRPC도 분산된다" → 연결 단위라 기존 연결은 그대로 쏠린다.