iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 20
0
Cloud Native

30 天準備 LPI DevOps Tools Engineer 證照系列 第 20

[Day 20] Docker (6)

Docker 容器網路 (Docker Container Networking)

這一部分會包含應試能力目標中的三個項目:

  1. 將容器與 Docker 網路連接
  2. 瞭解 Docker 網路概念,包括 overlay 網路
  3. 建立並管理 Docker 網路

Docker 預設提供了多樣的網路功能,以用於不同的情境,例如本機與 Docker 溝通,或者是 Docker Swarm 模式的容器間彼此溝通,包含下列幾種模式:

  1. bridge:預設的網路模式,通常是應用程式運行於單獨容器 (standalone container) 時使用。
  2. host:也是於單獨容器的情況下使用,它移除了容器與本機間的網路隔離,直接使用本機的網路。只在 Docker 17.06 以上的 swarm 服務可用。
  3. overlay:連接多個 Docker daemon,並且讓處於 Docker Swarm 中的容器可以彼此溝通。當位於不同主機上的單獨容器間要互相溝通也可使用此模式。使用這個模式的好處在於用戶不需自行處理作業系統層的路由 (routing) 設定。
  4. macvlan:可指定 MAC 位址給 Docker 容器,讓 Docker 感覺像是網路中的實體設備。如果應用程式是原有網路中的一部分,並且已有自己的 IP,可使用這個模式,不需再透過執行 Docker 主機的網路堆疊。
  5. none:關閉 (disable) 網路設定,通常會配合自定的其他網路。無法在 Docker Swarm 中使用此模式。

上述各種型態的網路,我覺得比較常用的應該是 bridgeoverlay,接下來針對這幾種作進一步的說明,

橋接網路 (bridge network)

橋接網路是一個連接層 (link layer) 的硬體或軟體設備,用來在網路區段 (network segment) 中傳送流量 (traffic)。在 Docker 中,連接到同一個橋接網路的容器可以彼此溝通,並與外界或其他沒有連接到這個橋接網路的容器隔離。由同一個 Docker daemon host 所運行的容器才能連接到同一個橋接網路。Docker 的橋接網路有預設 (default) 及使用者自定 (user-defined) 兩種型式,當啟動 Docker 時會自動建立一個預設橋接網路,除非特別指定,否則新啟動的容器會連接至此預設網路。若指定容器連接到使用者自定網路,優先權會高於預設網路。

那麼預設橋接網路和使用者自定橋接網路有什麼差異呢?基本上使用者自定網路提供更好的隔離性及互動性。連接到同一個使用者定義網路的容器,彼此之間會揭露 (expose) 所有的 port,但對外是封閉的;而在預設網路中,容器需要用 -p 或 --publish 旗標來對外揭露指定的 port。此外使用者自定網路提供了自動 DNS 解析功能,容器間可以透過容器名稱或別名來互相指稱,在預設網路中則必須用 --link 旗標彼此連接,否則就只能用 IP 來指定其他容器。文件中提到 --link 這個旗標已經被認為是過時 (legacy) 的。使用者自定網路可讓容器於運行期間連接或離開 (disconnect),若是預設網路,容器必須先停止,並在重啟時指定其他網路選項。

接下來依文件教學進行操作,並測試這兩種橋接網路。

首先用 docker network ls 來看看目前 docker 上有那些網路可用

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
303e05a02517        bridge              bridge              local
ca06e284596c        host                host                local
b63ff7b8f326        none                null                local

可能還會看到其他的網路,但至少應有 bridgehostnone 三個網路。

接下來跑兩個執行 alpine 映像檔的容器,並在容器中執行 ash,它是 alpine 使用的 shell。此外指定以 detached 模式運行 (-d),以及使用互動模式 (-i) 並給予 tty (-t)。這裡同時使用 -d-it 的原因是如果只用 -d,當 ash 執行結束後,容器會立刻進入停止狀態。指令如下:

$ docker run -dit --name alpine1 alpine ash
$ docker run -dit --name alpine2 alpine ash

查看 bridge 網路的資訊,以及連接至該網路的容器訊息。

$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "303e05a025172f337a156536faa3a3f5814cd9eb5ad26f25a2415956c697b4e8",
        "Created": "2018-10-26T21:55:40.901431721Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "2a49bddfec030b0dc76c42039d4b32c0a267fb4708ad81a152933faf8df02a7c": {
                "Name": "alpine1",
                "EndpointID": "0ac828fa69f204e3d9ea8dc483a4cbc842f31f41530553f4debe89f0a921d0e7",
                "MacAddress": "02:42:ac:11:00:05",
                "IPv4Address": "172.17.0.5/16",
                "IPv6Address": ""
            },
            "e21e2a7d2641be7101fefbb84ac9eaf6439ba3f15d9717bd87c60c555e63f739": {
                "Name": "alpine2",
                "EndpointID": "9b7139bd99103d382f205788e9af569c9893241ed2c12f2fbd1cd3d6a4094a0a",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/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": "1500"
        },
        "Labels": {}
    }
]

一開始列出了 bridge 網路的設定,在 Containers 的區段,會看到 alpine1alpine2 兩個容器及它們在 bridge 網路中的 IP。

接下來以 docker container attach alpine1 連接到 alpine1,看到 root 的命令提式字元後用 ip addr show 顯示容器的網路介面。

$ docker container attach alpine1
/ # ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1
    link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN qlen 1
    link/tunnel6 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
147: eth0@if148: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ #

最後的 172.17.0.5 就是 alpine1bridge 網路的 IP。接下來確認與 alpine2 的網路連通狀況,使用 ping 指令並指定 alpine2bridge 網路上的 IP,指令為 ping 172.17.0.5,若使用 alpine1 容器名稱會找不到。若要離開 alpine1 容器,但讓容器維持在運作狀態,使用 ctrl - pctrl - q 來離開。

Overlay 網路

看完了 bridge,接下來來看一下 overlay 網路。overlay 中文是覆蓋的意思。overlay 網路是覆蓋 (on top of) 於多個 Docker daemon 主機之上的分散式網路 (distributed network),讓連接至該網路的容器(包含 swarm 服務容器)能彼此安全溝通。當初始化 swarm 或者將 Docker 主機加入一個 swarm 時,會在該主機上新建兩個網路,第一個是稱作 ingressoverlay 網路,負責處理 swarm service 的控制及資料流量,它是 swarm service 預設連接的 overlay 網路;第二個是稱作 docker_gwbridge,它連接了參與這個 swarm 的各個 Docker daemon。原則上要使用 overlay 網路的主機,防火牆設定需開放下列規則:

  1. TCP port 2377 彼此連通,用於叢集管理溝通
  2. TCPUDP port 7946 彼此連通,用於節點間的溝通
  3. UDP port 4789 彼此連通,用於 overlay 網路的流量

連接到同一個 overlay 網路的 swarm 服務,彼此間會揭露所有的 port,若服務外部想要存取某個 port,必須在服務建立或更新時加上 -p--publish 的旗標。除了預設的 ingress 網路,也可建立使用者自定網路,建立時若加上 --attachable 旗標,表示除了 swarm 服務外,單獨容器 (standalone container) 亦可連接至該網路。

網路的部分就先介紹到這裡,明天再來看看卷宗 (volume)。


上一篇
[Day 19] Docker (5)
下一篇
[Day 21] Docker (7)
系列文
30 天準備 LPI DevOps Tools Engineer 證照30

尚未有邦友留言

立即登入留言