ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 쿠버네티스 네트워킹 : 포드 네트워킹(kubernetes pod networking)
    Kubernetes 2018. 8. 23. 09:00
    반응형
    쿠버네티스는 일반적인 도커 네트워크와는 다른 구조를 가지고 있습니다. 여러대의 노드를 사용해서 클러스터를 구성하는데 개별 노드에 뜬 포드들이 서로 IP를 통해서 통신을 할 수 있는 구조가 됩니다. 그리고 각 포드는 1개의 컨테이너로 구성되는게 아니라 여러개의 컨테이너로 구성됩니다. 여기서는 포드에 어떻게 IP가 할당되고 어떤 원리로 클러스터 내부에서 그 IP를 통해서 통신이 가능한지 살펴보도록 하겠습니다. 먼저 일반적인 도커 네트워크 구조를 살펴 보겠습니다. 다음 그림처럼 일반적인 도커네트워크는 호스트에 docker0이라는 브릿지가 추가되어서 컨테이너와 호스트간의 네트워크를 연결해 주도록 되어 있습니다. 컨테이너에는 가상의 veth0이라는 네트워크 디바이스가 추가되어서 docker0와 통신을 하게 됩니다. 이 때 별다른 설정을 해주지 않았다면 도커에서 기본으로 사용하는 네트워크 대역은 172.17.0.0 입니다. 아래 그림을 보면 관련 내용을 확인할 수 있습니다.

    일반적인 도커와는 다르게 쿠버네티스는 포드 단위로 컨테이너들을 관리합니다. 그래서 하나의 포드에 속한 컨테이너들은 동일한 IP를 가지게 됩니다. 다음 그림에 나오는 것처럼 포드에 속한 컨테이너들은 하나의 veth0을 공유하게 됩니다. 그래서 포드에 속한 컨테이너들은 모두 동일한 IP를 가지게 됩니다. 여기서 보이는 pause 컨테이너가 포드의 인프라 역할을 해주는 인프라 컨테이너 입니다. 그래서 실제로 포드의 veth0은 pause컨테이너의 장치입니다. 다른 컨테이너들은 이 pause컨테이너에서 제공해주는 veth0을 공유해서 사용하게 됩니다. 그래서 포드의 컨테이너중 pause컨테이너가 아닌 사용자 컨테이너들이 재시작을 하더라도 pause컨테이너가 있으면 veth0가 유지되기 때문에 포드의 IP는 변경되지 않고 그대로 유지됩니다. 반대로 pause컨테이너에 문제가 발생하면 다른 사용자 컨테이너가 정상이라고 하더라고 veth0에 문제가 발생하기 때문에 정상적인 네트워크 통신이 되지 않습니다.

    docker inspect를 통해서 포드에서 사용중인 컨테이너의 NetworkMode를 살펴보면 bridge나 host가 아닌 container로 되어 있는걸 볼 수 있습니다. ed9f1847236b... 문자열은 pause 컨테이너의 해시값입니다. 그래서 이 컨테이너가 저 pause컨테이너의 네트워크를 공유해서 사용하고 있다는걸 확인할 수 있습니다. 포드(pod)에 접근할때는 포드의 IP를 통해서 하고, 포드내부에서 컨테이너간의 구분은 포트(port)를 이용해서 할 수 있습니다.

    docker inspect cb54badae214 | grep Network
                "NetworkMode": "container:ed9f1847236bdc0c39eea5689cccd72be5e84688e033f97bc68c0847f0ea5c9a",
    여기까지는 하나의 노드에서의 포드 네트워크가 어떻게 구성되어 있는지 알아봤습니다. 이제 하나의 노드가 아닌 여러 노드에 나누어서 실행되고 있는 포드간에 어떻게 통신이 가능한지 알아 보도록 하겠습니다. 우선 여러대의 노드로 구성되어 있다고 생각했을때 단순히 노드가 늘어난다고 생각하면 아래 그림 같은 구조를 생각할 수 있습니다.


    위 그림에서는 호스트가 2대가 있고 서로 라우터/게이트웨이를 통해서 연결되어 있는걸 확인할 수 있습니다. 그리고 각 호스트의 IP는 서로 다릅니다. 하지만 여기서 봐야 할건 호스트 내부의 IP들입니다. 단순히 호스트가 여러대로 늘어난 구조라면 위 그림에서 본 것처럼 도커 브릿지인 docker0의 IP는 두 호스트 모두 172.17.0.1로 동일하고 각 호스트에 있는 포드의 IP도 172.17.0.2으로 같은걸 볼 수 있습니다. 쿠버네티스에서는 각 포드들이 모두 고유의 IP를 가지도록 구성되어 있다고 했는데 위와 같은 구조라면 호스트 내부의 포드들은 서로 다른 IP를 가질 수 있지만 서로 다른 호스트 사이에는 동일한 IP를 가진 포드가 올 수 있습니다. 그리고 포드 IP가 같기 때문에 172.17.0.2라는 IP로 요청이 오면 호스트01과 호스트02중 어떤 호스트에 있는 포드로 패킷이 가야할지 결정할 수 없습니다. 결국 제대로된 네트워크 구성이 아닙니다. 그럼 이걸 어떻게 해결 할 수 있을까요? 
    다음 그림을 보면 그 구조를 알 수 있습니다.

     
    이 그림에서는 각 개별 포드들이 앞서 봤던 것과는 다르게 각각의 IP를 가지고 있습니다. 그리고 호스트01에 있는 포드(192.168.20.2)에서 호스트02로 있는 포드(192.168.30.2)로 접속한다고 생각해 보겠습니다. 먼저 192.168.30.2 라는 IP가 있는지 확인을 하기 때문에 호스트01의 cbr0으로 갔다가 요청이 NAT를 거쳐서 다시 호스트01의 eth0까지 갔다가 적절한 경로를 찾기위해 다시 라우터/게이트웨이 쪽으로 가게 됩니다. 여기서 라우터/게이트웨이가 192.168.30.0/24 대역의 IP에 대한 요청이 오면 어디로 가야하는지에 대한 라우팅 정보를 가지고 있습니다. 그래서 라우터/게이트웨이는 이 대역의 IP를 가지고 있는 호스트02의 cbr0으로 패킷을 보내기 위해서 호스트02의 eth0으로 패킷을 보내게 되고 이건 호스트02의 NAT -> cbr0 을 거쳐서 veth0(192.168.30.2)까지 도착하게 됩니다. 이런 구조를 실제 호스트간의 네트워크 위에 별도의 네트워크가 존재한다고 해서 오버레이네트워크(overlay network)라고 부릅니다. 쿠버네티스에서는 이런 오버레이네트워크를 구성하는데 있어서 CNI(Container Network Interface)를 이용해서 다양한 플러그인들을 사용할 수 있습니다.

    참조 
    https://medium.com/google-cloud/understanding-kubernetes-networking-pods-7117dd28727
    https://cloudnativelabs.github.io/post/2017-04-18-kubernetes-networking/
    https://prefetch.net/blog/2018/02/09/understanding-the-network-plumbing-that-makes-kubernetes-pods-and-services-work/
    http://madorn.com/kubernetes-non-masquerade-cidr.html#.W3ycuZP7TUI
    https://kubernetes.io/docs/tasks/administer-cluster/ip-masq-agent/
    http://bluese05.tistory.com/36?category=559611


    반응형

    댓글

Designed by Tistory.