티스토리 뷰


도커 네트워크 Overview

도커 네트워크는 기본적으로 아래와 같은 기본 구성을 가지고 간다.
물리적 또는 가상화 기반의 이더넷 네트워크는 기본 리눅스 구성과 동일하다.


1. 물리적 이더넷 정보

일반적으로 운영체제에서 사용되는 NIC(Network Interface Card)를 사용하는 것은 동일하다.

[root@cent151 ~]# ifconfig ens192

ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.72.78.151  netmask 255.255.255.128  broadcast 10.72.78.255
        inet6 fe80::250:56ff:fe07:8151  prefixlen 64  scopeid 0x20<link>
        ether 00:50:56:07:81:51  txqueuelen 1000  (Ethernet)
        RX packets 43217427  bytes 4261207431 (3.9 GiB)
        RX errors 0  dropped 1193  overruns 0  frame 0
        TX packets 19452716  bytes 1583784858 (1.4 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

2. Iptables 

리눅스에 기본제공되고 있는 iptable은 Docker에서 외부 네트워크와 통신하는 데 중요한 역할을 한다.
특별하게 설정하지 않더라도,  Docker Pakage설치시 iptable에 자동으로 등록된다.
보통 iptable은 리눅스 방화벽의 역할을 수행하는 도구로, 주로 패킷 필터링과 NAT (Network Address Translate)의 역할을 수행한다.
아래는 리눅스의 iptable의 역할에 대한 3가지 주요 역할을 구분하였다.

실제 Packet은 아래와 같은 흐름으로 iptable을 통과하게 된다.
이러한 이유로 Packet filter와 NAT를 동작하게 되면, 트래픽 양이 많아 질수록 성능 저하를 야기 시킬 수도 있다.

아래 iptalbe을 통해 docker 의 NAT 외부 POST Routing의 규칙을 살펴 볼 수 있다.
아래 테이블을 참조해 보면, NAT Table 결과를 통해서 Post Routing 처리되는 규칙들을 확인한 결과 값이다.
Docker 구성이후에는 자동으로 설정되기 때문에 별도로 iptable을 수정할 필요는 없다.

[root@cent151 ~]# iptables -t nat -L | more

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.16.2.0/24        anywhere
MASQUERADE  all  --  172.16.1.0/24        anywhere
MASQUERADE  all  --  172.17.0.0/16        anywhere
POSTROUTING_direct  all  --  anywhere             anywhere
POSTROUTING_ZONES_SOURCE  all  --  anywhere             anywhere
POSTROUTING_ZONES  all  --  anywhere             anywhere

3. Bridge Table 
일반적으로 가상화에서는 소프트웨어 스위치가 구성이 되는데, 실제 역할은 Bridge 역할을 담당한다.
Bridge 별로 동일한 네트워크가 설정되고, Bridge가 다르게 되면 서로간의 통신은 별도의 구성이 없으면 제어된다.
Docker 설치후에 특별한 설정이 없다면, Docker0 Bridge에 모두 바인딩된다.
아래는 기본 Docker 설정 이후에 구성되는 Bridge Network의 모습이다.

[root@cent152 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
8e21616631d0        centos              "/bin/bash"         2 hours ago         Up 2 hours                              centos01

# docker “centos01”이 동작 중

root@cent152 ~]# brctl show
bridge name    bridge id        STP enabled    interfaces
docker0        8000.0242969ca394    no        veth51c5659

#centos01 container는 docker0 Bridge에 연결되어 사용 중이며, 논리적으로 interface vethernet 51c5659에 할당되어 있음.

[root@cent152 ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:96ff:fe9c:a394  prefixlen 64  scopeid 0x20<link>
        ether 02:42:96:9c:a3:94  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 656 (656.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

# docker0 bridge는 소프트웨어적인 스위치방식으로, 일반적인 스위치 컨셉과는 다르게 DHCP로 연결된 container에게 사전에 정의된 IP Pool을 할당함.

4. Container
도커 내부의 컨테이너는 일반적인 리눅스 운영체제와 유사한 네트워킹 환경을 가지게 된다.
컨테이너를 생성하게 되면, 기본 Docker Bridge0에 연결되고 가상 이더넷포트 (veth)에 연결되는 가상의 네트워크 카드가 바인딩된다.
컨테이너에서는 별도의 네트워크 카드를 생성하지 않고, Docker에서 컨테이너와 추가적인 브릿지 연결을 하게 되면 네트워크 카드가 자동으로 추가 된다.

[root@centos01 /]# read escape sequence
[root@cent152 ~]# docker exec -it centos01 bash
[root@centos01 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 9237  bytes 14384485 (13.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5216  bytes 346722 (338.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


도커 네트워크는 크게 5가지의 네트워크를 기본 제공한다.

1. None
2. Host
3. Bridge
4. MACVLAN
5. Overlay

동일 호스트를 사용할 경우에는 None,Host,Bridge Network, MACVLAN등을 사용이 가능하며, 서로 다른 호스트에서 네트워크 연결을 위해서는 MACVLAN, Overlay Network등을 구성할 수 있다.
None,Host 등은 동일 호스트내에서 간단한 테스트 정도에 주로 사용하며, 대부분 기본 제공되는  Bridge를 시작으로, 서로 다른 호스트를 연결할 때는 Overlay Network를 사용할 수 있다.
추가적으로 CNI Plugin을 통해 3rd Party 네트워크 구성을 할수도 있다.

먼저 Docker Bridge Network를 살펴본다.
명칭에서 언급되듯이 소프트웨어 기반의 Bridge Network를 생성하여, 컨테이너와 연결하는 방식이다.
마치 가상의 스위치를 구성하여, 서로 다른 컨테이너를 서로 다른 스위치에 연결하고, 서로 다른 스위치에 연결된 네트워크 간에는 통신을 제어 하는 모델이다.
실제 구성 예제는 아래와 같다.


먼저 Docker network bridge를 생성한다.

[root@cent151 ~]# docker network create --driver bridge --subnet 172.16.1.0/24 --ip-range 172.16.1.0/24 --gateway=172.16.1.1 vswitch01
e0592a7ece85ec4251f75f4471b19c6f64117b33e3fb89cb8bad5be9217aeb8b

# docker network 명령은 새로운 가상의 브릿지(가상 스위치)구성을 정의 할 수 있으며, 이 때 서브넷과 할당범위, Gateway를 지정할 수 있다.
# 컨테이너를 생성할 때 해당 네트워크 브릿지로 연결하게 되면,정의된 브릿지 네트워크에서 자동으로 DHCP로 정보를 할당 받게 된다.

[root@cent151 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
6eefb3d0d6b0        bridge              bridge              local
c25c81b6be34        host                host                local
3b48379378aa        none                null                local
e0592a7ece85        vswitch01           bridge              local

#vswitch01 이라는 신규생성된 브릿지를 확인 할 수 있다.

[root@cent151 ~]# brctl show
bridge name       bridge id            STP enabled    interfaces
br-e0592a7ece85   8000.0242ee20c0b7    no
docker0           8000.0242f80dad19    no

#brctl 명령을 통해 현재 생성된 브릿지 정보를 확인 할 수 있다.

[root@cent151 ~]# docker network inspect vswitch01
[
    {
        "Name": "vswitch01",
        "Id": "e0592a7ece85ec4251f75f4471b19c6f64117b33e3fb89cb8bad5be9217aeb8b",
        "Created": "2019-06-27T00:00:37.589912584+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.16.1.0/24",
                    "IPRange": "172.16.1.0/24",
                    "Gateway": "172.16.1.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

# 생성된 브릿지의 정보를 inspect 명령을 통해 확인 할 수 있다.
# 앞서 선언한 subnet 및 IP range, Gateway 구성을 확인 할 수 있다.

[root@cent151 ~]# docker network create --driver bridge --subnet 172.16.2.0/24 --ip-range 172.16.2.0/24 --gateway 172.16.2.1 vswitch02
7cdc541f23b31bc217a78a89e5022180dff6d9313f7b2abd33783648db9fe1ff

# 2개의 분리된 네트워크 구성을 위해 추가로 브릿지를 생성한다.

[root@cent151 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
6eefb3d0d6b0        bridge              bridge              local
c25c81b6be34        host                host                local
3b48379378aa        none                null                local
e0592a7ece85        vswitch01           bridge              local
7cdc541f23b3        vswitch02           bridge              local

[root@cent151 ~]# brctl show
bridge name            bridge id            STP enabled    interfaces
br-7cdc541f23b3        8000.02421e6d841a    no
br-e0592a7ece85        8000.0242ee20c0b7    no
docker0                8000.0242f80dad19    no

[root@cent151 ~]# docker network inspect vswitch02
[
    {
        "Name": "vswitch02",
        "Id": "7cdc541f23b31bc217a78a89e5022180dff6d9313f7b2abd33783648db9fe1ff",
        "Created": "2019-06-27T00:03:00.68823481+09:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.16.2.0/24",
                    "IPRange": "172.16.2.0/24",
                    "Gateway": "172.16.2.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

# 신규 생성된 브릿지의 상세 정보를 확인한다.

[root@cent151 ~]# docker run --name alnx01 --hostname alnx01 --network vswitch01 -itd whchoi_alpine:v1
8a7c2fdf5ce80d7f8a34abf58d8a19b632d0b3fdedf4b6b8b7e54ce010a2ecf7
[root@cent151 ~]# docker run --name alnx02 --hostname alnx02 --network vswitch01 -itd whchoi_alpine:v1
7ffb5526b9c67fe35e0ed84b6ab13b6b009e475b0d616c20c3238003b1a74268

# alnx01,02 컨테이너를 생성하고, 해당 컨테이너를 vswitch01에 연결한다.

[root@cent151 ~]# docker run --name alnx03 --hostname alnx03 --network vswitch02 -itd whchoi_alpine:v1
c7fb1e852bc6b07da5cae770f8487b02e0166aa4ee12bfd95ab037dc5480e9a9
[root@cent151 ~]# docker run --name alnx04 --hostname alnx04 --network vswitch02 -itd whchoi_alpine:v1
d9ee27525656e891b68d547e124c9bfdcbd0b5ce672a8fb31d20d40232c314ba

# alnx03,04 컨테이너를 생성하고, 해당 컨테이너를 vswitch01에 연결한다.

[root@cent151 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
d9ee27525656        whchoi_alpine:v1    "/bin/sh"           26 seconds ago       Up 25 seconds                           alnx04
c7fb1e852bc6        whchoi_alpine:v1    "/bin/sh"           45 seconds ago       Up 44 seconds                           alnx03
7ffb5526b9c6        whchoi_alpine:v1    "/bin/sh"           About a minute ago   Up About a minute                       alnx02
8a7c2fdf5ce8        whchoi_alpine:v1    "/bin/sh"           About a minute ago   Up About a minute                       alnx01

[root@cent151 ~]# docker attach alnx01
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
153: eth0@if154: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:10:01:02 brd ff:ff:ff:ff:ff:ff
    inet 172.16.1.2/24 brd 172.16.1.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping alnx02
PING alnx02 (172.16.1.3): 56 data bytes
64 bytes from 172.16.1.3: seq=0 ttl=64 time=0.312 ms
64 bytes from 172.16.1.3: seq=1 ttl=64 time=0.176 ms
64 bytes from 172.16.1.3: seq=2 ttl=64 time=0.130 ms
64 bytes from 172.16.1.3: seq=3 ttl=64 time=0.135 ms

/ # ping 172.16.2.2
PING 172.16.2.2 (172.16.2.2): 56 data bytes
^C
--- 172.16.2.2 ping statistics ---
8 packets transmitted, 0 packets received, 100% packet loss

# alnx01에서는 alnx02로 네트워크 트래픽 전송이 가능하지만, alnx03,04는 연결할 수 없다.
# Bridge에서 구성된 정보에 따라 자동으로 DHCP를 통해 IP를 할당 받는다.

[root@cent151 ~]# docker attach alnx03
/ # ping alnx04
PING alnx04 (172.16.2.3): 56 data bytes
64 bytes from 172.16.2.3: seq=0 ttl=64 time=0.188 ms
64 bytes from 172.16.2.3: seq=1 ttl=64 time=0.133 ms
64 bytes from 172.16.2.3: seq=2 ttl=64 time=0.141 ms
64 bytes from 172.16.2.3: seq=3 ttl=64 time=0.151 ms
^C
--- alnx04 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.133/0.153/0.188 ms
/ # ping alnx01
ping: bad address 'alnx01'
/ # ping 172.16.1.2
PING 172.16.1.2 (172.16.1.2): 56 data bytes
^C
--- 172.16.1.2 ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
149: eth0@if150: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:10:02:02 brd ff:ff:ff:ff:ff:ff
    inet 172.16.2.2/24 brd 172.16.2.255 scope global eth0
       valid_lft forever preferred_lft forever

# alnx03에서는 alnx04로 네트워크 트래픽 전송이 가능하지만, alnx01,02는 연결할 수 없다.
# Bridge에서 구성된 정보에 따라 자동으로 DHCP를 통해 IP를 할당 받는다.

[root@cent151 ~]# docker network disconnect vswitch02 alnx03
[root@cent151 ~]# docker network connect vswitch01 alnx03

# alnx03 컨테이너에서 Bridge 이름 “vswitch02” 연결을 제거하고, bridge “vswitch01”로 연결한다.

[root@cent151 ~]# docker attach alnx03
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
155: eth1@if156: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:10:01:04 brd ff:ff:ff:ff:ff:ff
    inet 172.16.1.4/24 brd 172.16.1.255 scope global eth1
       valid_lft forever preferred_lft forever
/ # ping alnx01
PING alnx01 (172.16.1.2): 56 data bytes
64 bytes from 172.16.1.2: seq=0 ttl=64 time=0.366 ms
64 bytes from 172.16.1.2: seq=1 ttl=64 time=0.134 ms
^C
--- alnx01 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.134/0.250/0.366 ms
/ # ping 172.16.2.3
PING 172.16.2.3 (172.16.2.3): 56 data bytes
^C
--- 172.16.2.3 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss

[root@cent151 ~]# brctl show
bridge name    bridge id        STP enabled    interfaces
br-7cdc541f23b3        8000.02421e6d841a    no        vethe4274ae
br-e0592a7ece85        8000.0242ee20c0b7    no        veth002b0c4
                            veth24ec799
                            veth851cf6c
docker0        8000.0242f80dad19    no

# alnx03 컨테이너에서는 이제 앞선 결과와 다르게 alnx01,02에 네트워크 연결이 가능하고, alnx04 연결이 불가능하다.
# bridge 연결을 변경하였기 때문에 새로운 DHCP 설정을 통해 IP를 할당 받는다.

[root@cent151 ~]# docker network connect vswitch02 alnx03

# 앞서 예제의 그림에서 처럼, alnx03에 2개의 인터페이스 할당을 위해 삭제 했던, vswitch02를 연결한다.
# 이제 alnx03은 두개의 Bridge “vswitch01” “vswitch02”에 연결할수 있고, 그에 따라서 가상의 네트워크 카드 2개를 바인딩한다.

[root@cent151 ~]# docker attach alnx03
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
155: eth1@if156: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:10:01:04 brd ff:ff:ff:ff:ff:ff
    inet 172.16.1.4/24 brd 172.16.1.255 scope global eth1
       valid_lft forever preferred_lft forever
157: eth2@if158: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:10:02:02 brd ff:ff:ff:ff:ff:ff
    inet 172.16.2.2/24 brd 172.16.2.255 scope global eth2
       valid_lft forever preferred_lft forever
/ # ping alnx01
PING alnx01 (172.16.1.2): 56 data bytes
64 bytes from 172.16.1.2: seq=0 ttl=64 time=0.249 ms
64 bytes from 172.16.1.2: seq=1 ttl=64 time=0.131 ms
64 bytes from 172.16.1.2: seq=2 ttl=64 time=0.133 ms
^C
--- alnx01 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.131/0.171/0.249 ms
/ # ping alnx02
PING alnx02 (172.16.1.3): 56 data bytes
64 bytes from 172.16.1.3: seq=0 ttl=64 time=0.253 ms
64 bytes from 172.16.1.3: seq=1 ttl=64 time=0.133 ms
^C
--- alnx02 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.133/0.193/0.253 ms
/ # ping alnx04
PING alnx04 (172.16.2.3): 56 data bytes
64 bytes from 172.16.2.3: seq=0 ttl=64 time=0.264 ms
64 bytes from 172.16.2.3: seq=1 ttl=64 time=0.133 ms
^C
--- alnx04 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.133/0.198/0.264 ms

/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.16.1.1      0.0.0.0         UG    0      0        0 eth1
172.16.1.0      0.0.0.0         255.255.255.0   U     0      0        0 eth1
172.16.2.0      0.0.0.0         255.255.255.0   U     0      0        0 eth2

# 이제 alnx03 컨테이너는 vswitch01에 연결된 alnx01,02와 vswitch02에 연결된 alnx04 컨테이너들 모두와 통신이 가능하다.
# 이때 먼저 연결된 네트워크를 통해서 디폴트 라우팅은 구성된다.

[root@cent151 ~]# brctl show
bridge name            bridge id        STP enabled    interfaces
br-7cdc541f23b3        8000.02421e6d841a    no         veth919541f
                                                       vethe4274ae
br-e0592a7ece85        8000.0242ee20c0b7    no         veth002b0c4
                                                       veth24ec799
                                                       veth851cf6c
docker0                8000.0242f80dad19    no

# 구성완료된 브릿지 네트워크 구성을 조회해 보면 , 기본 생성되어 있는 docker0 및 임의로 할당된 브릿지 vSwitch01,vSwitch02가 구성된 것을 확인 할 수 있다.
# 현재 docker0 브릿지에는 컨테이너가 연될되어 있지 않은 것을 확인 할 수 있다.



공지사항