Pod의 네트워크를 담담한다.
Pod를 만들게 되면 내가 생성한 Container가 있지만 Pause Container라고 해서 Networking을 담당하는 Container가 자동으로 생성된다.
이 컨테이너에 Interface가 달려있고 IP가 생기는데 쿠버네티스가 Pause Container에 Network Namespace를 이 Pod내에 모든 Container들한테 같이 쓰도록 구성해준다.
그렇게 되면 이 IP에 대한 네트워크를 같이 공유하게 되고 Container간의 구분은 Port를 통해서 하게 된다.
한편 이 Worker Node에 Host Network Namespace가 있고 여기에 Host IP Inteface가 있는데 Pause Container가 생기면 이 Host Network Namespace에 가상 Interface가 하나 생기면서 Pause Container의 Interface와 연결이 된다.
Pod를 만들 때 마다 이렇게 가상의 Interface가 생겨서 1대1로 매칭이 된다.
Worker Node에 Pause Container의 IP:Container의 Port를 날려보면 트래픽이 흐르게 된다.
이렇게 외부에서 Pod로 들어오는 트래픽을 받는 것과 특정 Container로 트래픽을 전달 하는 역할을 Pause Container가 Linux의 Network Namespace를 별도로 생성해서 가상의 Interface를 만들고 그걸 관련 Container들에게 공유하고 있기 때문에 가능한 것이다.
Pod의 Pause Container의 Interface와 통신하는 Host Network Namespace의 Host IP Interface들을 Bridge에 포함시킨다.
그리고 이 Bridge Network의 대역은 Pod 네트워크 대역을 참고해서 이 보다 낮은 단계의 대역으로 세팅이 된다.
Bidge 내에서 생성되는 Pod IP는 이 Bridge CIDR 범위 내에서 만들어진다.
Bridge에 세팅된 CIDR을 보면 총 255개의 Pod IP를 할당할 수 있다고 보면 되고 한 Node에 그 이상은 만들어지지 않는다. (kubelet을 사용했을 때의 단점 중 하나)
이렇게 Bridge를 통해서 Pod간에 통신이 가능해지게 된다.
그리고 Network Plugin에 Router의 역할도 있는데 NAT를 통해서 기능이 제공이 되고 하는 일은 IP가 Pod IP 대역이면 해당 트래픽은 Bridge쪽으로 내려주고 그 외 IP에 대해서는 위로 올려준다.
Calico Plugin은 Host Network에 생성된 가상 Interface가 바로 Router에 연결되어 있는 구조다.
그렇기 때문에 Pod간에 통신은 Router가 담당해주고 여기에 CIDR는 kubelet보다 더 큰 범위를 가지고 있어서 한 Node에서 Pod에게 더 많은 IP를 부여할 수 있다.
또한 Calico Plugin에서 제공되는 보안적인 요소도 많다.
Router 윗단에는 Overlay Network를 제공해주는 층이 있다.
Overlay Network를 제공해주는 종류에는 IPIP, VXLAN이 있다.
이 Overaly Network가 하는 일은 Node 위에 있는 Pod가 타 Node 위에 있는 Pod와 통신을 할 수 있게 해준다.
Pod D에서 Pod B의 IP인 20.111.156.7로 호출을 하면 이게 그대로 Router에 있는 가상 Interface를 지나 해당 IP는 이 Router내에 없기 때문에 Overlay Network층 까지 올라가게 된다.
그리고 Calico는 이 Pod의 IP대역이 어느 Node에 있는지 알고 있기 때문에 Overlay Network층에서 패킷을 해당 Node의 IP로 변경해주고 실제 Pod의 IP는 안에 숨겨놓는다. (InCapsulation)
그래서 이 트래픽은 22번 Host Interface로 가게 되고 타 Node로 들어온 트래픽이 Overlay Network층에서 Decapsulation 되면서 원래의 Pod IP로 변환이 된다.
그리고 이 IP대역이 있는 Router로 트래픽이 전해지고 Router안에서 해당 IP에 맞는 가상 Interface를 지나 최종적으로 요청한 Pod까지 도착을 하게 된다.
쿠버네티스가 제공하는 Service Network의 ProxyMode에는 3가지가 있고 이 3가지 모들을 사용하기 위한 전제상황으로 Pod를 만들고 Service를 연결하는데 Pod가 정상적으로 기동된 상태라면 중간에 EndPoint라는 Object가 생성이 되서 실제 연결 상태를 담당한다.
Service의 IP는 Service Network CIDR 네트워크 범위 내에서 생성된다.
이 때 API 서버는 EndPoint를 감시하고 있다가 모든 Node에 설치되는 DaemonSet인 kube-proxy한테 Service IP는 Pod의 IP로 포워딩 된다는 정보를 준다.
Linux Worker Node에 기본적으로 설치되어 있는 iptables에 Service CIDR로 들어오는 트래픽은 모두 kube-proxy 한테 주도록 설정이 되어있는 상태여서 Pod에서 Service IP를 호출할 경우 이 트래픽은 iptables를 거쳐 kube-proxy로 가게 된다.
kube-proxy는 자신이 가지고 있는 매핑 정보를 보고 이 트래픽을 Pod IP로 바꿔준다.
이렇게 Pod IP로 변경된 트래픽은 다음부터 Pod Network 영역으로 통신이 되서 트래픽이 전달된다. (kube-proxy를 항상 통과해야 되서 잘 쓰이지 않는다.)
kube-proxy가 IP 매핑 정보를 iptable에 직접 등록하는 방식이라 Pod에서 보내는Service IP는 iptables에서 Pod IP로 변환이 된다.
이 방식이 쿠버네티스를 설치했을 때 기본 모드이고 성능이나 안정성이 우수하다.
Linux에서는 IPVS라고 해서 L4 LoadBalancer를 제공하는데 Service Mode를 IPVS Mode로 설정을 하면 iptables와 같은 역할을 해준다.
낮은 트래픽에서는 iptables와 성능이 비슷하지만 부하가 많을 수록 IPVS가 성능이 더 우수하다.
Router부분에서 Service IP를 Pod IP로 변환해주는 NAT역할을 해주는 기능이 있다.
만약 Pod D에서 PodB로 트래픽을 날린다고 했을 때 먼저 Pod B의 ClusterIP Type에 Service를 연결한다. 그리고 Pod D에서 Service IP로 트래픽을 보내면 NAT에서 해당 ServiceIP와 매칭되는 Pod IP로 변환이 된다.
그런 다음 Overlay Network에서 IP가 캡슐화되고 Pod Network 단에 통신을 하게 된다.
모든 Node에 있는 kube-proxy가 자신의 Node에 30000번 대의 NodePort를 열어주고 외부에서 Host IP:nodePort로 트래픽이 오면 iptables에서 이 트래픽을 Calico Plugin에 보내준다.
그리고 여기서부터 ClusterIP와 같이 NAT기능을 통해 해당 IP로 변환이 되면서 Pod Network 영역으로 넘어가게 된다.