기본적으로 도커 컨테이너를 하나 생성하면, 해당 컨테이너를 namespace로 격리한 뒤 eth0 interface를 생성하고, 노드에 veth interface를 생성해서 연결시키는 구조로 동작한다
하지만 위의 그림은 보다시피, 컨테이너별로 각기 다른 veth interface에 연결된 것이 아닌, 공통된 하나의 veth interface에 연결되어 있음을 볼 수 있다
이는 쿠버네티스가 Pod 내에서 컨테이너를 생성할 때 도커 컨테이너를 bridge 모드(default)가 아닌 container 모드로 띄웠기 때문이다
container 모드는 아래와 같이 다른 컨테이너를 지정함으로써 띄울 수 있는데, 이렇게 생성함으로써 생성된 도커 컨테이너는 지정한 도커 컨테이너와 네트워크를 공유하는 형태로 생성될 수 있게 된다
$ docker run --net=container:{container_id} -d {image_name}
이렇게 생성된 컨테이너들을 각각 들어가서 ip 정보를 확인해보면, 모두 ip가 같음을 볼 수 있을 것이다
즉 결론은, Pod 내의 도커 컨테이너들은 모두 위처럼 container 모드로 실행되었기 때문에 아래와 같은 특성이 만족되는 것이다
외부에서 같은 IP로 접근할 수 있다(각 컨테이너들의 IP가 같음)
컨테이너간 localhost 로 통신할 수 있다
같은 port는 사용 불가능
그림에는 있지만 언급하지 않은 pause 컨테이너가 있는데, 이는 위에서 언급한 일련의 기능들을 수행하기 위해 Pod 내에 추가적으로 생성되는 컨테이너이다
Pod 이 실행될 때 마다 이 컨테이너가 먼저 실행되고, 이 컨테이너의 namespace를 다른 컨테이너들이 공유하고, 이 컨테이너가 다른 pod 들을 container 형태로 띄우는 건가?
노드가 다른 Pod 끼리의 통신
위의 모델의 경우 같은 docker0 브릿자 아래에서는 Pod 간의 통신이 전혀 문제될 것이 없지만,
쿠버네티스 클러스터의 경우 보통 1개 이상의 노드를 관리하며, Pod 는 매번 다른 노드에 배포되는 특성이 있다
docker0 브릿지는 각 노드마다 생성되는데, 중요한 점(문제되는 점)은 이 docker0 브릿지의 ip 대역대가 겹칠 수 있다는 것이다 docker0 아래의 컨테이너들은 전부 docker0 브릿지의 네트워크 대역을 따라가는데, 만약 docker0 브릿지의 네트워크 대역이 겹친다면 결국 Pod의 IP가 겹치는 문제가 발생한다
(docker에서 사용하는 docker0 브릿지로는 이 문제를 해결할 수 없기 때문에 이를 커스텀한 cbr 브릿지를 사용했다)
이제 Pod은 항상 라우팅 테이블을 거쳐 다른 Pod 이 존재하는 브릿지를 찾아갈 수 있기 때문에, 다른 노드에 있는 Pod 끼리도 원할하게 통신이 가능해진다!
Service Network
위에서 봤듯이 Pod 의 네트워크 메카니즘 때문에 다른 노드에 있는 Pod 끼리도 서로 통신이 가능하다
근데 문제는, Pod는 상황에 따라 늘어나거나 삭제되는 둥 변경이 많은 리소스라는 점이다
즉 새롭게 배치되면서 노드가 변경되고, 그에따라 IP가 변경되는 경우가 많다는 의미인데, 이런 상태에서는 Pod에서 다른 Pod로 통신하는 것이 사실상 불가능해진다
쿠버네티스는 이러한 문제를 해결하기 위해 서비스 라는 새로운 리소스를 등장시켰는데, 개념은 대충 아래와 같다
보다시피 scalable 한 Pod 들을 서비스 라는 리소스 하나로 묶었다(label을 이용하여 묶는다)
아래는 생성된 서비스의 모습이다
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo ClusterIP 10.3.241.152 <none> 8888/TCP 23s
보다시피 service 자체가 ClusterIP 라는 내부(가상) IP를 가지게 됨을 볼 수 있는데, 이로 인해 이제 내부 Pod 들은 이 ClusterIP를 입력하여 통신하므로써 서비스 내의 Pod 들과 통신할 수 있게 되는 것이다
이렇게 함으로써 Pod의 IP 변경에 대해 신경쓰지 않아도 되고, 서비스가 요청을 각 파드별로 적절히 로드밸런싱 해주는 효과까지 얻을 수 있게 된다
이것도 다들 아시곘지만 .. ㅎㅎ
Pod Network
Pod은 내부의 컨테이너들끼리 IP와 port를 공유한다는 특징이 있었는데, 어떻게 구성되어 있길래 그럴까?
아래는 Pod 의 네트워크를 잘 설명해주는 하나의 그림이다
기본적으로 도커 컨테이너를 하나 생성하면, 해당 컨테이너를 namespace로 격리한 뒤 eth0 interface를 생성하고, 노드에 veth interface를 생성해서 연결시키는 구조로 동작한다
하지만 위의 그림은 보다시피, 컨테이너별로 각기 다른 veth interface에 연결된 것이 아닌, 공통된 하나의 veth interface에 연결되어 있음을 볼 수 있다
이는 쿠버네티스가 Pod 내에서 컨테이너를 생성할 때 도커 컨테이너를 bridge 모드(default)가 아닌 container 모드로 띄웠기 때문이다
container 모드는 아래와 같이 다른 컨테이너를 지정함으로써 띄울 수 있는데, 이렇게 생성함으로써 생성된 도커 컨테이너는 지정한 도커 컨테이너와 네트워크를 공유하는 형태로 생성될 수 있게 된다
이렇게 생성된 컨테이너들을 각각 들어가서 ip 정보를 확인해보면, 모두 ip가 같음을 볼 수 있을 것이다
즉 결론은, Pod 내의 도커 컨테이너들은 모두 위처럼 container 모드로 실행되었기 때문에 아래와 같은 특성이 만족되는 것이다
노드가 다른 Pod 끼리의 통신
위의 모델의 경우 같은
docker0
브릿자 아래에서는 Pod 간의 통신이 전혀 문제될 것이 없지만,쿠버네티스 클러스터의 경우 보통 1개 이상의 노드를 관리하며, Pod 는 매번 다른 노드에 배포되는 특성이 있다
docker0
브릿지는 각 노드마다 생성되는데, 중요한 점(문제되는 점)은 이docker0
브릿지의 ip 대역대가 겹칠 수 있다는 것이다docker0
아래의 컨테이너들은 전부docker0
브릿지의 네트워크 대역을 따라가는데, 만약docker0
브릿지의 네트워크 대역이 겹친다면 결국 Pod의 IP가 겹치는 문제가 발생한다이런식으로 말이다
이 상태에서는 Pod 간에 서로 통신할 수가 없다. src와 dest의 IP가 같기 때문이다
노드 안에서 생성되는
doccker0
브릿지의 경우 default 네트워크 대역이 정해져있고,만약 default 값을 사용하지 않는다고 해도 다른 노드의
docker0
브릿지가 어떤 네트워크 대역을 사용하고 있는지 알지 못하기 때문에 문제가 해결되지는 않는다쿠버네티스는 이러한 문제점을 해결하기 위해 2가지 방법을 사용했다
docker0
브릿지들의 전체 네트워크 대역을 아우르는 주소 대역을 할당한다이를 적용하면 아래와 같은 모습이 된다
(docker에서 사용하는
docker0
브릿지로는 이 문제를 해결할 수 없기 때문에 이를 커스텀한cbr
브릿지를 사용했다)이제 Pod은 항상 라우팅 테이블을 거쳐 다른 Pod 이 존재하는 브릿지를 찾아갈 수 있기 때문에, 다른 노드에 있는 Pod 끼리도 원할하게 통신이 가능해진다!
Service Network
위에서 봤듯이 Pod 의 네트워크 메카니즘 때문에 다른 노드에 있는 Pod 끼리도 서로 통신이 가능하다
근데 문제는, Pod는 상황에 따라 늘어나거나 삭제되는 둥 변경이 많은 리소스라는 점이다
즉 새롭게 배치되면서 노드가 변경되고, 그에따라 IP가 변경되는 경우가 많다는 의미인데, 이런 상태에서는 Pod에서 다른 Pod로 통신하는 것이 사실상 불가능해진다
쿠버네티스는 이러한 문제를 해결하기 위해
서비스
라는 새로운 리소스를 등장시켰는데, 개념은 대충 아래와 같다보다시피 scalable 한 Pod 들을 서비스 라는 리소스 하나로 묶었다(label을 이용하여 묶는다)
아래는 생성된 서비스의 모습이다
보다시피 service 자체가 ClusterIP 라는 내부(가상) IP를 가지게 됨을 볼 수 있는데, 이로 인해 이제 내부 Pod 들은 이 ClusterIP를 입력하여 통신하므로써 서비스 내의 Pod 들과 통신할 수 있게 되는 것이다
이렇게 함으로써 Pod의 IP 변경에 대해 신경쓰지 않아도 되고, 서비스가 요청을 각 파드별로 적절히 로드밸런싱 해주는 효과까지 얻을 수 있게 된다