티스토리 뷰

CI&CD

Docker - Docker Network에 대한 이해

realizers 2022. 3. 12. 17:40
728x90
반응형

docker0와 Network의 구조


  • docker의 network 구조를 간단히 그리면 아래와 같은 형식으로 되어있습니다.
  • 여기서 우리가 먼저 알아야할 것은 docker0은 무엇이고, container network에 대해 알아보겠습니다.

Docker0 Interface
  • docker를 설치한 후 host의 network interface를 살펴보면 docker0이라는 virtual interface가 있는것을 확인할 수 있습니다.
ifconfig // 명령어 입력

Docker0 Interface의 특징
  • IP는 자동으로 172.17.0.1로 할당됩니다.
  • 이 IP는 DHCP를 통해 자동으로 할당받는 것이 아닌 docker 내부 로직에 의해 자동으로 할당받게 됩니다.
  • docker0 interface는 일반적인 interface가 아니며 virtual ethernet bridge 입니다.
  • 즉 docker0은 컨테이너가 통신하기 위한 virtual bridge이며, 하나의 컨테이너가 생성될 때 이 docker0 virtual bridge에 생성된 컨테이너의 interface가 히나씩 바인딩되는 형태입니다.
  • 또한 컨테이너가 실행될때마다 vethAAA라는 이름의 인터페이스가 붙어지게 되는 형태입니다.
  • 결론적으로 생성한 컨테이너가 외부로 통신을 할때는 무조건 docker0 interface를 지나가야합니다.
  • 또한 docker0의 IP는 172.17.0.1로 설정되고 subnet mask는 255.255.0.0(172.17.0.0/16)으로 설정이 됩니다. 이 subnet mask 정보는 컨테이너가 생성될때마다 컨테이너가 할당받게될 IP의 범위를 결정하게 됩니다. 그렇기 때문에 모든 컨테이너는 172.17.XX.XX 대역에서 IP를 하나씩 할당받게 됩니다.

 

brctl show docker0 명령어를 통해 알아보자
  • 현재 veth7d55e0b, veth810822f, veth9a58e0 의 컨테이너가 실행되고 있으며 해당 컨테이너들은 docker0 interface를 통하여 외부와 통신을 주고받고 있습니다.

Container와 Network의 구조


  • 컨테이너가 생성될때마다 network에는 어떠한 일이 발생하게되는지 알아보겠습니다.
  • 컨테이너는 각자만의 독립적인 network 공간을 할당받게 됩니다. 근데 각자만의 공간을 할당 받긴했는데 어떻게 외부(또는 또다른 컨테이너)와 통신을 주고받을 수 있을까요?
  • 먼저 컨테이너가 생성이되면 해당 컨테이너에는 pair(peer) interface라고 하는 한쌍의 인터페이스들이 생성되게 됩니다.
  • 컨테이너 생성시 pair interface의 한쪽은 컨테이너 내부에 eh0이라는 이름으로 할당되고, 다른 한쪽은 vethAAA라는 이름으로 할당이되며 이 두 interface가 한쌍으로 구성이되고 서로 정보를 주고 받습니다. 그리고 docker0 bridge에 바인딩될때에는 두 인터페이스중 vethAAA라는 이름으로 바인딩이 되게 됩니다.

 

Container 내부에 할당된 eh0 interface 확인 방법
  • 컨테이너 내부에 할당된 eho interface는 어떻게 확인을 해야할까? 이는 해당 namespace에서만 보이도록 격리되어 있으므로 실행중인 컨테이너에 접속하여 확인할 수 있습니다.
  • 컨테이너안에 외부 통신을 위한 eh0 interface가 있는것을 확인할 수 있습니다. 그리고 172.17.0.3이라는 IP를 할당받았으며 netmask도 255.255.0.0으로 설정되어 있는것을 확인할 수 있습니다.
# 1. 실행중인 컨테이너 접속

# 2. ifconfig -a 명령어 입력

 

Container의 Gateway 확인
  • 실행중인 컨테이너의 게이트웨이를 확인해보면 docker0에 설정된 IP인 172.17.0.1로 설정되어 있는것을 확인할 수 있습니다.

 

Container Network가 외부와 통신하는 구조


  • 컨테이너가 외부와 연결되기 위해서는 어떤 구조로 동작을 할까?

 

Container port를 외부로 노출
  • 컨테이너 생성시 각 컨테이너는 격리된 공간을 할당받게 됩니다. 그리고 각 컨테이너는 docker host와 통신을 위해 bridge 방식으로 바인딩되어져 있는 상태입니다. 따라서 docker host내에 컨테이너들은 자신이 할당받은 private ip를 통해 통신이 가능합니다.
  • 아래 명령어를 보면 -p 3306 : 3306으로 포트를 지정할 수 있는데 docker host의 3306 포트로 어떠한 요청이 들어오게 된다면 실행중인 컨테이너의 3306 포트로 forwarding 하겠다는 의미입니다. 
docker run -d -p 3306:3306 --name mysql-container mysql:8.0.28

 

docker-proxy
  • docker host로 들어온 요청을 실행중인 컨테이너로 넘겨줍니다.
  • host가 받은 패킷을 그대로 컨테이너의 포트로 넘기는 역할을 합니다. 컨테이너 실행 시 포트를 외부에 노출시키면 docker host에는 docker-proxy라는 process가 생성됩니다.
  • 예를들어 두개의 port를 외부에 노출시키면 두개의 docker-proxy process가 생성되는것입니다. 하지만 docker-proxy와 관계없이 docker host의 iptables에 의해 컨테이너로 패킷이 전달됩니다. 따라서 docker-proxy process를 kill하여도 패킷은 정상적으로 컨테이너로 전달됩니다.
    • 이게 무슨소리지? 이부분에 대해서는 iptables를 이용한 포트 포워딩 설정을 살펴보겠습니다.

 

iptables를 이용한 DNAT
  • DNAT란?
    • 외부에서 내부로 접근할때 Destination IP주소를 변경하여 내부에 접근할 수 있도록 패킷을 변경합니다.
    • 대표적으로는 Load Balancer가 있습니다.
// 명령어 입력
iptables -t nat -L -n

  • iptables 내역을 보면 먼저 docker host에 들어온 패킷(80포트)이 PREROUTING Chain을 통해 DOCKER Chain으로 전달하고 DOCKER Chain에서는 DNAT로 80 포트로 들어온 요청을 172.17.0.4 IP를 가진 컨테이너의 80 포트로 포트포워딩이 되는것을 알 수 있습니다.
  • 반대로 컨테이너 내부에서 외부로 나갈때는 POSTROUTING을 거쳐 MASQUERADE 되어 외부로 나갑니다.

 

Docker-proxy를 사용하는 이유는?


  • docker host에서 컨테이너로 패킷을 전달하는 방법이 iptables를 이용한 DNAT 방식이라면 위에서 언급한 docker-proxy process는 어떻한 역할을 하는걸까?

 

docker-proxy를 사용하는 이유는?
  • docker-proxy가 존재하는 가장 큰 이유는 docker host가 iptables의 NAT를 사용하지 못하는 상황에 대한 처리입니다. 만약 어떠한 정책상의 이유로 docker host의 iptables나 ip_forword를 활성화하지 못하는 경우에는 docker-proxy process가 패킷을 포워딩하는 역할을 대신 수행하게 됩니다.
  • NAT란?
    • 모든 IP 패킷에는 Source IP와 Destination IP가 있습니다.
    • NAT란 Network Address Translation, 즉 IP 패킷 헤더의 IP주소를 변경하는 기능 혹은 절차를 의미합니다. 1:1 NAT 혹은
      1:N의 NAT가 있습니다.
    • PREROUTING : DNAT을 이용하여 패킷이 생길 때 사용됨
    • POSTROUTING : SNAT을 이용하여 패킷이 나갈 때 사용됨

 

 

 

 

 



728x90
반응형