이전 시리즈에서는 Cilium의 기본 개념과 Identity, Endpoint, IPAM 등을 쿠버네티스 환경에서 직접 실습했고, Socket LB(East-West Load Balancing)는 TCPDUMP를 기반으로 패킷을 하나하나 분석하며 이해를 진행했다. 다만 내용이 길어지면서 다음 주제인 North-South Load Balancing은 다루지 못했다. 이번 글에서는 North-South Load Balancing을 다루고자 한다. North-South Load Balancing 지금까지 다룬 내용은 In-Cluster 내 Pod to Pod 통신, 즉 East-West […] ||
이전 시리즈에서는 Cilium의 기본 개념과 Identity, Endpoint, IPAM 등을 쿠버네티스 환경에서 직접 실습했고, Socket LB(East-West Load Balancing)는 TCPDUMP를 기반으로 패킷을 하나하나 분석하며 이해를 진행했다. 다만 내용이 길어지면서 다음 주제인 North-South Load Balancing은 다루지 못했다. 이번 글에서는 North-South Load Balancing을 다루고자 한다.
North-South Load Balancing
지금까지 다룬 내용은 In-Cluster 내 Pod to Pod 통신, 즉 East-West 통신을 기반으로 진행했다. In-Cluster 통신의 경우 출발지 파드가 클러스터가 소유한 노드에 있기 때문에, 출발지 파드가 네트워크 연결을 요청할 때 connect() 함수를 eBPF로 후킹할 수 있었다. 하지만 North-South 통신의 경우 외부 클라이언트로부터 트래픽이 인입되기 때문에 connect() 함수를 후킹할 수 없다. 그렇기에 패킷이 도착하는 목적지 노드의 tc(tcx) 계층에서 DNAT을 수행해야 한다(cil_from_netdev@eth0). 그리고 백엔드가 다른 노드에 있다면 해당 노드로 패킷을 포워딩까지 해야 한다. 응답의 경우 처음 도착했던 노드를 통해서 최초의 외부 클라이언트에게 응답을 제공해야 한다(클라이언트는 요청했던 노드 IP:포트에서 응답을 기다리고 있기 때문이다).
North-South Load Balancing: 외부 트래픽을 쿠버네티스 노드 내 서비스로 전달
East-West Load Balancing: 내부 서비스 간 로드 밸런싱
North-South 로드밸런싱에는 3가지 모드가 존재한다.
SNAT 모드 (기본)
클러스터 외부 클라이언트에서 발생한 패킷이 노드 A에 도착했다고 가정하자. 이때 전송하려는 백엔드 파드가 노드 B에 있다면, 노드 A는 패킷의 소스를 자신의 IP로 변경(SNAT)한 뒤 노드 B로 전송한다. 응답받은 파드는 다시 노드 B로 전달하고 노드 B는 노드 A로 전달한다. 최종적으로 노드 A가 외부 클라이언트에게 응답한다.
ExternalTrafficPolicy가 local이라면 백엔드가 클라이언트의 IP를 볼 수 있지만, 그 외의 경우에는 소스 IP가 노드 A의 IP로 변경되어 있다. 또한 응답이 노드 A를 거치므로 네트워크 홉이 하나 더 생긴다.
DSR (Direct Server Return)
패킷이 노드 A에 도착했을 때 소스를 클라이언트 IP 그대로 유지한 채 노드 B로 전달한다. 전달받은 노드 B는 백엔드 파드에게 전달한다. 전달받은 백엔드 파드는 소스가 클라이언트 IP로 되어 있기 때문에 외부 클라이언트에게 직접 응답을 제공한다. 즉, 노드 A를 거치지 않는다.
장점이라면 클라이언트 IP를 보존할 수 있고, 응답 경로를 단축할 수 있다는 점이다. 다만, 최초 패킷을 받은 노드 A는 원래 목적지(클라이언트의 주소 정보)를 노드 B에게 어떻게든 전달해야 하는 과정이 필수적이다.
Hybrid
TCP는 DSR 방식으로, UDP는 SNAT 방식을 사용함을 의미한다.
kubectl -n kube-system exec ds/cilium -- cilium status --verbose | grep -iA 12 "KubeProxyReplacement Detail


