12/08/2018, 13:48

Tìm hiểu và làm việc với docker container networks (P1)

Bài viết này xin đưa ra cái nhìn tổng quan về default networking bên trong Docker native. Mô tả các loại network trong docker, làm thế nào để tạo ra chúng, các tài nguyên cần thiết để tạo network trên single host hoặc cluster hosts. 1. Default Networks Khi bạn cài đặt xong Docker, sẽ có 3 ...

docker-turtles-felix-communication1.png

Bài viết này xin đưa ra cái nhìn tổng quan về default networking bên trong Docker native. Mô tả các loại network trong docker, làm thế nào để tạo ra chúng, các tài nguyên cần thiết để tạo network trên single host hoặc cluster hosts.

1. Default Networks

Khi bạn cài đặt xong Docker, sẽ có 3 loại networks được tự động tạo ra. Chúng ta có thể liệt kê tất cả bằng câu lệnh docker network ls:

$ docker network ls

NETWORK ID          NAME                DRIVER
7fca4eb8c647        bridge              bridge
9f904ee27bf5        none                null
cf03ee007fb4        host                host

Ở đây chúng ta có 3 loại networks mặc định của docker, Khi bạn run một container, bạn có thể sử dụng flag: --network để chỉ định loại network mà bạn muốn container chạy trên đó khi run. Vì mặc định được tao ra bởi docker, nên bạn có thể sử dụng nó bất cứ khi nào cần.

bridge network được thể hiện bởi docker0 network. Trù khi bạn chỉ định một option network khác bằng lệnh docker run --network=<NETWORK>, nếu ko Docker daemon sẽ tự động connect các containers tới loại network này. Bạn có thể thấy bridge như một phần của host’s network stack bằng cách sử dụng câu lệnh ifconfig trên host:

$ ifconfig

docker0   Link encap:Ethernet  HWaddr 02:42:47:bc:3a:eb
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:47ff:febc:3aeb/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1
          RX packets:17 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1100 (1.1 KB)  TX bytes:648 (648.0 B)

none network thêm một container vào container-specific network stack. Container này bị thiếu network interface. Thử attach một container và xem điều gì đã diễn ra :v

$ docker attach nonenetcontainer

root@0cb243cd1293:/# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
root@0cb243cd1293:/# ifconfig
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@0cb243cd1293:/#

host network thêm một container lên hosts network stack. Bạn có thể tìm thấy network configuration bên trong container đồng nhất với host.

Ngoại trừ bridge network, bạn ko thực sự cần tương tác với default networks. Khi bạn có thể list hoặc inspect chúng, tuy nhiên bạn không thể xóa chúng. Ngoài default network, ta có thể add thêm user-defined networks, có thể xóa khi ko muốn dùng. Trước khi học cách để tạo ra networks, chúng ta sẽ tìm hiểu một chút về default bridge network.

Bridge network

Default bridge network được hiện diện trên tất cả các Docker hosts. Câu lệnh docker network inspect trả lại các thông tin về network:

$ docker network inspect bridge

[
   {
       "Name": "bridge",
       "Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
       "Scope": "local",
       "Driver": "bridge",
       "IPAM": {
           "Driver": "default",
           "Config": [
               {
                   "Subnet": "172.17.0.1/16",
                   "Gateway": "172.17.0.1"
               }
           ]
       },
       "Containers": {},
       "Options": {
           "com.docker.network.bridge.default_bridge": "true",
           "com.docker.network.bridge.enable_icc": "true",
           "com.docker.network.bridge.enable_ip_masquerade": "true",
           "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
           "com.docker.network.bridge.name": "docker0",
           "com.docker.network.driver.mtu": "9001"
       }
   }
]

Docker Engine tự động tạo ra Subnet và Gateway tới network. Trong khi câu lệnh docker run tự động add container mới tạo vào chính network này:

$ docker run -itd --name=container1 busybox

3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c

$ docker run -itd --name=container2 busybox

94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c

Thử inspect bridge network lại, sau khi chạy 2 containers chúng ta sẽ thấy id của container hiển thị trên “Containers” section:

$ docker network inspect bridge

{[
    {
        "Name": "bridge",
        "Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Config": [
                {
                    "Subnet": "172.17.0.1/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Containers": {
            "3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c": {
                "EndpointID": "647c12443e91faf0fd508b6edfe59c30b642abb60dfab890b4bdccee38750bc1",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c": {
                "EndpointID": "b047d090f446ac49747d3c37d63e4307be745876db7f0ceef7b311cbba615f48",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "9001"
        }
    }
]

Câu lệnh docker network inspect hiển thị toàn bộ các container được kết nối và network resources của loại network được truyền vào. Containers trong default network có thể giao tiếp với nhau bằng IP addresses. Docker không hỗ trợ tự động quét service trên default bridge network. Nếu bạn muốn giao tiếp thông qua container names trong default bridge network, bạn phải kết nối các containers với nhau thông qua docker run --link option.

Bạn có thể attach & chạy một container, và xem thông tin về configuration:

$ docker attach container1

root@0cb243cd1293:/# ifconfig
ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02
          inet addr:172.17.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1
          RX packets:16 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1296 (1.2 KiB)  TX bytes:648 (648.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

Hãy thử sử dụng ping để gửi 3 ICMP requests, và test kết nối của các containers trên bridge network.

root@0cb243cd1293:/# ping -w3 172.17.0.3

PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.096 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.074 ms

--- 172.17.0.3 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.074/0.083/0.096 ms

Cuối cùng, hãy sử dụng câu lệnh cat để kiểm tra cấu hình network container1:

root@0cb243cd1293:/# cat /etc/hosts

172.17.0.2	3386a527aa08
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters

Để detach ra khỏi container1 nhưng vẫn muốn chúng tiếp tục running, ta sử dụng CTRL-p CTRL-q. Sau đó attach container2 và lặp lại 3 câu lệnh: ifconfig, ping, cat.

$ docker attach container2

root@0cb243cd1293:/# ifconfig

eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:03
          inet addr:172.17.0.3  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1
          RX packets:15 errors:0 dropped:0 overruns:0 frame:0
          TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1166 (1.1 KiB)  TX bytes:1026 (1.0 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@0cb243cd1293:/# ping -w3 172.17.0.2

PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.067 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.075 ms
64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.072 ms

--- 172.17.0.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.067/0.071/0.075 ms
/ # cat /etc/hosts
172.17.0.3	94447ca47985
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters

Mặc định docker0 bridge network hỗ trợ sử dụng port mapping và docker run --link cho phép các containers giao tiếp với nhau qua docker0 network.

2. User-defined networks

Bạn có thể tạo ra user-defined networks, Docker cung cấp một vài default network drivers cho việc create networks. Bạn có thể tạo ra 1 bridge network mới hoàn toàn hoặc overlay network hoặc MACVLAN network. Bạn cũng có thể tạo ra network plugin hoặc remote network.

Docker cho phép ta tạo nhiều network, Một network có thể có nhiều containers, các containers chỉ có thể communicate với nhau bên trong network, một container được attached vào 2 network.

A bridge network

user-defined network dễ dàng tạo ra nhất là bridge network. Network này tương tự default docker0 network.

$ docker network create --driver bridge isolated_nw
1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b

$ docker network inspect isolated_nw

[
    {
        "Name": "isolated_nw",
        "Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Config": [
                {
                    "Subnet": "172.21.0.0/16",
                    "Gateway": "172.21.0.1/16"
                }
            ]
        },
        "Containers": {},
        "Options": {}
    }
]

$ docker network ls

NETWORK ID          NAME                DRIVER
9f904ee27bf5        none                null
cf03ee007fb4        host                host
7fca4eb8c647        bridge              bridge
c5ee82f76de3        isolated_nw         bridge

Sau khi tạo ra network, bạn có thể chạy containers trên đó bằng cách sử dụng docker run --network=<NETWORK> option.

$ docker run --network=isolated_nw -itd --name=container3 busybox

8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c

$ docker network inspect isolated_nw
[
    {
        "Name": "isolated_nw",
        "Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Config": [
                {}
            ]
        },
        "Containers": {
            "8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c": {
                "EndpointID": "93b2db4a9b9a997beb912d28bcfc117f7b0eb924ff91d48cfa251d473e6a9b08",
                "MacAddress": "02:42:ac:15:00:02",
                "IPv4Address": "172.21.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {}
    }
]

Container mà bạn chạy trên network này đều phải thuộc về cùng một Docker host. Mỗi container trong network có thể communicate với các containers khác trong cùng network.

bridge_network.png

linking không được hỗ trợ bên trong một user-defined bridge network. Bạn có thể expose và publish container ports trên các containers trong network này. Điều này rất hữu ích nếu bạn muốn tạo ra 1 phầm của bridge network available với một outside network.

network_access.png

bridge network rất hữu ích trong các trường hợp mà ở đó ta muốn chạy một relatively small network trên single host. Tuy nhiên chúng ta có thể tạo ra các networks lớn hơn bằng cách tạo một overlay network.

An overlay network with Docker Engine swarm mode

Bạn có thể tạo ra một overlay network trên một manager node running trong swarm mode mà không cần tới một external key-value store. Swarm tạo ra overlay network chỉ available với các nodes bên trong swarm. Khi bạn tạo ra một service sử dụng overlay network, manager node sẽ tự động kế thừa overlay network tới các nodes chạy các service tasks.

Ví dụ sau sẽ hướng dẫn cách tạo ra một network và sử dụng nó cho một service từ một manager node bên trong swarm:

# Create an overlay network `my-multi-host-network`.
$ docker network create 
  --driver overlay 
  --subnet 10.0.9.0/24 
  my-multi-host-network

400g6bwzd68jizzdx5pgyoe95

# Create an nginx service and extend the my-multi-host-network to nodes where
# the service's tasks run.
$ $ docker service create --replicas 2 --network my-multi-host-network --name my-web nginx

716thylsndqma81j6kkkb5aus

An overlay network with an external key-value store

Nếu bạn không sử dụng Docker Engine trong swarm mode, thì overlay network yêu cầu phải có một valid key-value store service. Hỗ trợ key-value stores gồm có Consul, Etcd, và ZooKeeper (Distributed store).

Chú ý: Docker Engine chạy trong swarm mode không tương thích với networking sử dụng external key-value store.

key_value.png

Mỗi host trong network phải run một Docker Engine instance. Cách dễ dàng nhất để tạo ra các host là sử dụng Docker Machine.

engine_on_net.png

Bạn nên open các ports của mỗi hosts.

Protocol Port Description
udp 4789 Data plane (VXLAN)
tcp/udp 7946 Control plane

key-value store service có thể yêu cầu thêm một vài port khác. Check vendor’s documentation và open bất kỳ required port nào cần thêm.

3.

0