ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Docker] Docker Network 와 Bridge Type Network Interface 알아보기 ( ip link )
    Docker 2024. 6. 21. 07:18
    반응형

    - 목차

     

    들어가며.

    이번 글에서는 Docker Network 와 Linux 의 Bridge Type 의 Network Interface 에 대해서 알아보도록 하겠습니다.

    흔히 사용되는 "docker network create XX" 와 같은 도커 명령어는 Bridge Type 의 Docker Network 를 생성합니다.

     

    docker network ls
    
    NETWORK ID     NAME      DRIVER    SCOPE
    54bd3df3a059   bridge    bridge    local
    8e98086700d8   host      host      local
    6235cc583642   none      null      local

     

    위의 명령어는 기본적으로 제공되는 Docker Network 의 목록입니다.

    위 3개의 Docker Network 중에서 Bridge Type 의 Docker Network 가 존재하며, 이 Network 가 이번 글의 주제인 Bridge Type 의 Network 에 해당합니다.

     

    그리고 docker network create n1 와 같은 형식으로 추가적인 Bridge Type Docker Network 를 추가할 수 있습니다.

     

    NETWORK ID     NAME      DRIVER    SCOPE
    54bd3df3a059   bridge    bridge    local
    8e98086700d8   host      host      local
    262c5d648902   n1        bridge    local
    f78732c4e81a   n2        bridge    local
    6235cc583642   none      null      local

     

    이러한 Docker Network 는 실제 Linux 내부에서 Bridge Type 의 Network Interface 를 생성하게 됩니다.

    그리고 Container 내부의 Virtual Ethernet Network Interface 와 연결됩니다.

    아래의 링크는 Docker Container 와 Virtual Ethernet Network Interface 의 관계를 정리한 글입니다.

     

    https://westlife0615.tistory.com/913

     

    [Docker] Docker Container 와 veth ( Virtual Ethernet Network Interface ) 알아보기

    - 목차 들어가며.이번 글에서는 Docker Container 와 Network Namespace 격리에 대해서 알아보려고 합니다.Docker Container 는 Linux 의 Network Namespace 를 활용하여 Network 를 격리합니다.그 외에 PID, UTS, MOUNT 등의

    westlife0615.tistory.com

     

    이번 글에서는 Docker Network 와 Bridge Type 의 Interface 에 대해서 상세히 알아보는 시간을 가지려고 합니다.

     

    Bridge Network Interface 란 ?

    Bridge Network Interface 에 대해서 알아보기 이전에 기본적인 Ethernet Network Interface 에 대해서 먼저 알아봅니다.

    외부 인터넷과 연결된 eth0 또는 wlan 과 같은 Network Interface.

    흔히 eth0 나 wlan 와 같이 Internet Gateway 와 연결된 Network Interface 가 존재합니다.

    그리고 일반적인 컴퓨터들은 이러한 Network Interface 와 연결됩니다.

    eth0 는 Ethernet Network Interface 그리고 wlan 은 Wireless LAN 통신을 위한 Network Interface 를 의미합니다.

    실제로 아래의 이미지와 같이 각 서버들은 자신의 Network Interface 를 통해서 외부 인터넷과 연결됩니다.

     

     

     

    Switch 가 연결된 서버들.

    그리고 Router 에 의해서 형성된 Private Network 내부에 Switch 장비를 둘 수 있습니다.

    아래의 이미지는 상당히 단순화된 모습이긴 하지만 핵심은 Switch 를 중심으로 여러 서버들을 배치할 수 있습니다.

    이렇게 함으로써 Switch 내부의 서버들은 라우터를 거치지 않는 효율적인 통신을 할 수 있습니다.

     

     

    여기서 Switch Network Device 를 설명드리는 이유는 Bridge Network Interface 가 마치 가상의 또는 소프트웨어적인 Switch 로 동작하기 때문입니다.

    아래의 이미지는 Docker Host 와 Container 내부에서 Network 관계를 설명하는 그림입니다.

    Container 의 Ethernet Interface 와 Host 의 Virtual Ethernet Interface 는 서로 연결됩니다.

    그리고 Bridge Type Interface 가 두 veth 를 연결합니다.

    만약 Bridge Type Interface 가 없다면 각 Container 는 네트워크적으로 고립될 가능성이 있습니다.

     

     

    Bridge Network 을 통한 Container 의 Network 전송.

    만약 Container 1 에서 Container 2 로 네트워크 트래픽을 전송한다면 그 경로는 아래와 같습니다.

    Container1 Eth --> Host Veth1 --> Host Bridge --> Host Veth2 --> Container2 Eth

     

    만약 Host 의 Bridge Network Interface 가 존재하지 않는다면, Container2 로 네트워크 트래픽을 전달할 수 없습니다.

    Container1 Eth --> Host Veth1 --> X (단절됨.)

     

     

    Docker Network 과 실제 Linux Bridge Network Interface 관계 파악하기.

     

    아래와 같이 5개의 Docker Network 가 존재합니다.

    그리고 Bridge Type 의 Docker Network 는 3개가 존재합니다.

    docker network ls
    NETWORK ID     NAME      DRIVER    SCOPE
    54bd3df3a059   bridge    bridge    local
    8e98086700d8   host      host      local
    262c5d648902   n1        bridge    local
    f78732c4e81a   n2        bridge    local
    6235cc583642   none      null      local

     

    그리고 ip addr show 명령어를 통해서 생성된 모든 Network Interface 목록을 확인할 수 있습니다.

    아래의 출력 결과는 Bridge Type 의 Network Interface 만 추려서 가져온 결과입니다.

    11번 Interface 인 docker0 는 기본적으로 제공되는 Bridge Type Docker Network 입니다.

    그리고 12번과 13번에 해당하는 br-XXXX 네트워크 인터페이스는 명시적으로 생성한 n1, n2 네트워크입니다.

     

    11: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
        link/ether 02:42:0a:e4:13:ca brd ff:ff:ff:ff:ff:ff
        inet 172.18.0.1/16 brd 172.18.255.255 scope global docker0
           valid_lft forever preferred_lft forever
    12: br-262c5d648902: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
        link/ether 02:42:4a:6b:93:50 brd ff:ff:ff:ff:ff:ff
        inet 172.19.0.1/16 brd 172.19.255.255 scope global br-262c5d648902
           valid_lft forever preferred_lft forever
    13: br-f78732c4e81a: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
        link/ether 02:42:0d:2f:ff:11 brd ff:ff:ff:ff:ff:ff
        inet 172.20.0.1/16 brd 172.20.255.255 scope global br-f78732c4e81a
           valid_lft forever preferred_lft forever

     

    각 인터페이스는 inet 172.X.0.1 와 같이 IPv4 수준의 IP 를 소유합니다.

     

    Docker Container 와 Network 연결하기.

    아래의 명령어를 통해서 아주 간단한 Docker Container 를 2개 실행하였습니다.

     

    docker run --network n1 -d busybox sleep 100000
    docker ps
    CONTAINER ID   IMAGE     COMMAND          CREATED          STATUS          PORTS     NAMES
    6e25e21b0f7f   busybox   "sleep 100000"   22 seconds ago   Up 22 seconds             quizzical_austin
    5e40782136df   busybox   "sleep 100000"   34 seconds ago   Up 34 seconds             agitated_cannon

     

    그리고 ps aux 명령어를 통해서 생성된 Process List 를 확인할 수 있습니다.

    dockerd, containerd, containerd-shim 등을 일단 제외하고, sleep 10000 인 Container Process 에 주목합니다.

    이 Container Process 가 바로 Linux Namespace Isolation 이 적용된 실제 Docker Container 에 해당합니다.

     

    PID   USER     TIME  COMMAND
        1 root      0:00 docker-init -- dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2376
       56 root      0:01 dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2376 --tlsverify --
       68 root      0:04 containerd --config /var/run/docker/containerd/containerd.toml
      254 root      0:00 sh
      424 root      0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace moby -id 5e40782136dfcb23bdc8ee9c
      445 root      0:00 sleep 100000
      496 root      0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace moby -id 6e25e21b0f7ff1306bd2d7d4
      515 root      0:00 sleep 100000
      560 root      0:00 ps aux

     

    첫번째 Container Process 의 PID 는 445 , 두번째 Container Process 의 PID 는 515 입니다.

    그리고 각 Docker Container 의 IP 정보를 찾아보도록 하겠습니다.

    개별적인 환경에 따라서 IP 정보나 Network Interface 의 ID 값이 반드시 다르겠지만,

    아래의 절차에 의해서 각 Container 의 IP 값을 획득할 수 있습니다.

     

    nsenter --net=/proc/445/ns/net ip addr show | grep eth0
    nsenter --net=/proc/515/ns/net ip addr show | grep eth0

     

    14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
        inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0
        
    16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
        inet 172.19.0.3/16 brd 172.19.255.255 scope global eth0

     

    위 내용을 잠시 정리해보면, nsenter 는 Network Namespace 내부로 진입할 수 있는 명령어입니다.

    각 Docker Container 는 Network Namespace 에 의해서 격리되어 있습니다.

    따라서 각 Process ID 를 기준으로 개별적인 Network Namespace 를 가지는데요.

    이 /proc/$$/ns/net 파일에 저장된 Network Namespace 정보를 기준으로 Network Namespace 내부에 격리된 인터페이스를 조회할 수 있습니다.

     

    이 상황에서 아래의 명령어를 통해서 Container 간의 통신이 가능합니다.

    515 PID 의 Process 는 172.19.0.3 이라는 IP 를 가집니다.

    그리고 445 PID 의 Process 는 172.19.0.2 IP 를 가집니다.

    아래의 명령어는 nsenter 를 통해서 각 Process 의 Network Namespace 에 진입한 후에 다른 Container Process 에게 ping 요청을 수행합니다.

     

    nsenter --net=/proc/515/ns/net ping 172.19.0.2
    nsenter --net=/proc/445/ns/net ping 172.19.0.3

     

     

    Bridge Network 제거해보기.

    2개의 Docker Container 는 하나의 Bridge Network Interface 에 연결되어 있습니다.

    아래는 각 Docker Container 의 veth Network Interface 정보입니다.

    이 출력값을 확인해보면, master br-262c5d648902 라고 표현된 결과가 보입니다.

     

    15: vethc24d9d3@if14: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master br-262c5d648902 state UP
    
    17: vethe7baad9@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master br-262c5d648902 state UP

     

    "master br-262c5d648902" 의 의미는 "master br-262c5d648902" 로 표시된 네트워크 인터페이스가 "br-262c5d648902 인터페이스" 의 하위의 Interface 라는 것을 뜻합니다.

     

    즉, 아래와 같이 veth Type 인터페이스는 동일한 Bridge Type Interface 에 계층적으로 속하게 됩니다.

    Bridge Type Interface / Veth Type Interface
    br-262c5d648902 -> vethc24d9d3@if14
    br-262c5d648902 -> vethe7baad9@if16

     

    Veth Network Interface 와 Bridge Network Interface 의 연결을 제거해봅니다.

    아래의 ip link set nomaster 명령어를 통해서 vethc24d9d3 인터페이스와 Bridge Network Interface 의 연결을 끊을 수 있습니다.

     

    ip link set vethc24d9d3 nomaster
    15: vethc24d9d3@if14: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP

     

     

    그리고나서 아래의 명령을 통해서 Ping 요청을 하게되면 Network 요청이 전달되지 않습니다.

    그 이유는 Bridge Connection 이 해제되었기 때문이죠.

     

    nsenter --net=/proc/515/ns/net ping -c 3 172.19.0.2
    nsenter --net=/proc/515/ns/net ping 172.19.0.2
    PING 172.19.0.2 (172.19.0.2): 56 data bytes
    ^C
    --- 172.19.0.2 ping statistics ---
    38 packets transmitted, 0 packets received, 100% packet loss

     

    다시 아래와 같이 Bridge 와 Veth 인터페이스들을 연결해주면 정상적으로 통신이 가능해집니다.

     

    ip link set vethc24d9d3 master br-262c5d648902
    nsenter --net=/proc/515/ns/net ping -c 3 172.19.0.2
    PING 172.19.0.2 (172.19.0.2): 56 data bytes
    64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.239 ms
    64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.394 ms
    64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.411 ms
    
    --- 172.19.0.2 ping statistics ---
    3 packets transmitted, 3 packets received, 0% packet loss
    round-trip min/avg/max = 0.239/0.348/0.411 ms

     

     

     

    반응형
Designed by Tistory.