Computing

Pod 네트워크 (3) : kube-proxy와 CNI plugin 차이 본문

Cloud/Kubernetes

Pod 네트워크 (3) : kube-proxy와 CNI plugin 차이

jhson989 2023. 1. 27. 20:50

이전글

Pod 네트워크 (1) : Service 필요성과 개념, 종류 (ClusterIP, NodePort, LoadBalancer)

- Pod 네트워크 (2) : Service 내부 구현 분석 (kube-proxy와 iptables)

 

이전 글에서 쿠버네티스 클러스터 상에서 네트워킹을 지원하는 리소스인 Service(서비스), 그 서비스의 종류와 내부 구현에 대하여 정리하였다. 오늘은 서비스의 구현체인 Kube-proxy와, Container Network Interface (CNI)의 구현체인 CNI plugin의 차이에 대해서 정리해보고자 한다. 둘 다 쿠버네티스 운영 시 네트워크 관련된 개념이라는 것 때문에 혼동되는데 이번 기회에 정리를 한번 해보고자 한다.

 

 

 

kube-proxy VS. CNI Plugin

결론부터 말하자면, kube-proxy는 서비스의 IP를 Pod IP로 변환해주는 역할을 한다면, CNI Plugin은 Pod IP간에 통신을 가능하게 해주는 역할을 한다.

 

다음과 같은 상황이 있다고 하자. Pod A(10.0.0.2)와 Pod B(10.1.1.2)가 실행되고 있고, Service B는 Pod B(10.0.1.2)를 대표하는 서비스라고 하자. Pod A가 Service B를 접근하고 싶다. 이때 Pod A에게 Service B는 사실 Pod B라고 알려주는 것이 kube-proxy이다. 남은 것은  Pod A(10.0.0.2)에서 Pod B(10.1.1.2)로 데이터를 보내면 되는 것이다. 이 데이터를 보내는 과정을 가능하게 하는 것이 CNI Plugin이다.

 

 

 

kube-proxy의 역할

kube-proxy가 서비스의 IP를 Pod IP로 변환해주는 방법은 이전 포스터에서 정리하였다. kube-proxy는 iptables (ipvs모드도 있음)를 조작하여 NAT(Network Address Translation)을 수행한다. 

 

Fig 1. kube-proxy의 NAT [1]

 

Fig 1.은 kube-proxy가 ClusterIP에 대한 NAT를 수행하는 것을 보여주는 그림이다. Pod A가 Service 1의 주소로 네트워크 통신을 한다면, kube-proxy가 iptables을 조작하여 Service 1로 가는 패킷의 목적지 주소를 Pod B로 바꾼다. 

 

kube-porxy는 위 예제처럼 Service로의 데이터 통신을 실제 Pod로 변환하는 역할을 수행한다. 이를 위해 kube-proxy는 끊임없이 서비스와 엔드포인트 객체를 트랙킹하고, 이 변환이 제대로 수행되도록 iptables을 수정한다.

 

 

 

CNI Plugin의 역할

CNI Plugin은 실제 Pod간 통신이 가능하도록 한다. Pod A와 Pod B가 네트워크 통신을 하려고 한다고 하자. 그러면 다음 두가지를 만족해야 한다. 첫 번째, Pod A와 Pod B는 각각 유일한 IP 주소가 있어야 한다. 두 번째, Pod A의 입장에서 Pod B가 어디에 있는 지, 즉 routing이 가능해야 한다. (Routing은 어떤 네트워크 안에서 통신 데이터를 보낼 때 최적의 경로를 선택하는 과정) 

 

앞서 말했듯, 쿠버네티스 클러스터에 참여하는 모든 Pod들은 모두 유일한 IP를 가지고 있어야 한다. 당연한 말이지만, Pod들의 IP가 중복되면 누가 누구인지를 구별하지 못한다. Pod들은 쿠버네티스 클러스터의 모든 워커 노드에서 실행될 수 있는데, 이들에게 중복되지 않는 IP를 부여해줄 역할을 누군가는 해야 한다. 그게 CNI Plugin의 역할[2]이다. CNI Plugin은 모든 워커노드에게 중복되지 않는 subnet을 부여한다. 워커노드에서 실행되는 Pod는 해당 subnet에 포함된 IP를 부여받는다.

 

예를 들면, 쿠버네티스 클러스터에 워커 노드가 3개, 각각 노드 A, 노드 B, 노드 C가 있다고 하자. Pod들은 노드 A에서 혹은 노드 B, C에서 실행될 수 있다. CNI Plugin은 노드 A에 10.244.1.0/24 대역대를, 노드 B에 10.244.2.0/24 대역대를, 노드 C에 10.244.3.0/24 대역대를 부여할 수 있다. 그렇다면 노드 A에서 실행되는 모든 Pod들은 10.244.1.0/24 대역대에 속하는 IP를 부여받는다. 마찬가지로, 노드 C에서 실행되는 모든 Pod들은 10.244.3.0/24 대역대에 속하는 IP를 부여받는다. 

 

두 번째로, Pod간 네트워크 통신 시 routing이 가능해야 한다. 이 또한 CNI Plugin의 역할[3]이다. 라우팅이라는 것은 네트워크 통신 상의 경로를 찾는 것을 말한다. CNI Plugin은 라우팅 테이블 규칙을 설정하여 Pod간 혹은 쿠버네티스 요소들이 서로 통신할 수 있도록 한다.

 

Fig 2. CNI Plugin에 의해 수정된 routing table[3]

 

위의 예제에서 노드 A에서 실행 중인 Pod A(10.244.1.2)가 노드 B에서 실행 중인 Pod B(10.244.2.2)와 통신하고자 한다고 하자. (노드 A 자체 IP는 10.130.29.81, 노드 B 자체 IP는 10.130.29.82이라고 하자) [Pod A -> 노드 A -> 노드 B -> Pod B]로 트래픽이 전달될 것이라고 예상할 수 있는데, 문제는 노드 A가 Pod B가 어디에 있는 지 모르면 노드 B에게 트래픽을 전달할 수 없다.

 

이를 해결해주는 것이 routing table이다. Fig 2.의 마지막 줄을 보자. 이 줄의 의미는 다음과 같다: [10.244.2.0/24에 속하는 IP는 10.130.29.82로 전달함]. 위와 같은 routing rule에 의해 Pod A가 Pod B로 보내는 트래픽은 노드 A에 의해 노드 B로 전달된다. 노드 B는 자신 위에서 실행되는 Pod B에게 최종 데이터를 전달한다. 이러한 routing table을 관리하는 것이 CNI Plugin의 두 번째 기능이다.

 

 

 

Reference

[1] https://projectcalico.docs.tigera.io/about/about-kubernetes-services

[2] https://ronaknathani.com/blog/2020/08/how-a-kubernetes-pod-gets-an-ip-address/

[3] https://stackoverflow.com/questions/53534553/kubernetes-cni-vs-kube-proxy