Service의 PreferSameNode 트래픽 분산, 이거 모르는 분 꽤 많더라

크로스존 트래픽 비용 청구서를 보고 눈을 의심한 적이 있다. AZ 세 개에 노드가 흩어져 있는 EKS 클러스터에서, 결제 API가 유저 서비스를 호출하는데 세 번에 한 번은 다른 AZ로 넘어간다. NAT는 아니지만 AZ 간 트래픽은 GB당 $0.01. 요청 하나로는 티끌인데 P99 QPS로 곱해보면 월 결제서에 꽤 나온다.
Kubernetes 1.34에서 Service의 spec.trafficDistribution에 PreferSameNode가 GA로 붙었다. 원래 있던 PreferClose(구 PreferSameZone)에 이어서 나온건데, 같은 노드에 엔드포인트가 있으면 무조건 거기로 보낸다. 없을 때만 외부로 나간다. 아주 간단한데 효과가 크다.
어떻게 쓰나
apiVersion: v1
kind: Service
metadata:
name: user-svc
spec:
trafficDistribution: PreferSameNode
selector:
app: user
ports:
- port: 8080
끝이다. 필드 한 줄. PreferClose도 그렇지만 이건 힌트일 뿐이라 라우팅이 완벽하게 100% 로컬로만 가진 않는다. 로컬 파드가 없으면 어쩔 수 없이 다른 노드로 나간다. 근데 이게 오히려 좋다. 강제 로컬이면 파드 하나 죽으면 트래픽이 뚝 끊길 텐데, 힌트라서 자연스럽게 페일오버된다.
쓸 때 조심할 것
우리 팀에서 며칠 붙여보고 정리한 것들.
첫째, DaemonSet 스타일 사이드카에 특히 잘 맞는다. OpenTelemetry Collector나 Fluent Bit처럼 노드마다 한 개씩 뜨는 서비스면, 같은 노드의 파드가 항상 로컬 콜렉터로 붙어서 네트워크 홉이 사라진다. Otel Collector agent 모드 쓰는 팀은 이거 켜면 P50 latency가 눈에 띄게 떨어진다.
둘째, 워크로드 분산이 극단적으로 치우칠 수 있다. 노드 A에 파드가 3개, 노드 B에 1개면, A에서 오는 요청은 A의 파드가 다 받는다. 트래픽이 특정 노드에 몰리면 그 파드들만 CPU가 튄다. HPA는 잘 붙지만, PDB랑 topologySpreadConstraints를 같이 안 걸어두면 스케일 아웃 시에도 배치가 편향된다.
셋째, kube-proxy 버전 체크. 1.34 클러스터라도 kube-proxy가 예전 iptables 모드면 라우팅 힌트를 완전히 못 살린다. nftables 모드나 Cilium kube-proxy replacement 쓰면 훨씬 잘 붙는다. 우리는 nftables로 넘어가면서 겸사겸사 켰다.
결과
붙이기 전 대비 크로스존 트래픽이 대략 40% 정도 줄었다. AZ 밸런싱이 어떻게 되어있냐에 따라 편차가 크니까 이 숫자는 참고만 하자. 그리고 뭐 이 정도 트래픽 비용이 큰 팀이 얼마나 있겠냐만, 관측성 사이드카 홉을 줄이는 부수효과가 더 크더라.
혹시 이미 PreferClose로 zone-aware 라우팅만 쓰고 있다면, 노드 단위까지 좁혀보는 것도 시험해볼 만하다. 물론 배치 편향은 monitoring 잘 걸어놓고.
참고
- Kubernetes 1.34 릴리스 노트
- KEP-3015: Traffic Distribution PreferSameZone / PreferSameNode