Docker跨主機網絡配置方案之overlay

 

一、跨主機網絡概述

前面已經學習了 Docker 的幾種網絡方案:none、host、bridge 和 joined 容器,它們解決了單個 Docker Host 內容器通信的問題。本章的重點則是討論跨主機容器間通信的方案。

Docker 跨主機網絡 overlay(十六)

docker 原生的 overlay 和 macvlan。
第三方方案:常用的包括 flannel、weave 和 calico。

二、準備 overlay 環境

爲支持容器跨主機通信,Docker 提供了 overlay driver。Docerk overlay 網絡需要一個 key-value 數據庫用於保存網絡狀態信息,包括 Network、Endpoint、IP 等。Consul、Etcd 和 ZooKeeper 都是 Docker 支持的 key-vlaue 軟件,我們這裏使用 Consul。

1、環境描述

我們會直接使用上一節 docker-machine 創建的實驗環境。在 docker 主機 host1(192.168.1.201)和 host2(192.168.1.203)上實踐各種跨主機網絡方案,在 192.168.1.200 上部署支持的組件,比如 Consul。

2、創建 consul

在 192.168.1.200 這臺設備上面執行如下命令。

docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap

容器啓動後,可以通過 http://192.168.1.200:8500 訪問 Consul。

Docker 跨主機網絡 overlay(十六)

3、修改 docker 配置文件

接下來修改 host1 和 host2 的 docker daemon 的配置文件 /etc/systemd/system/docker.service.d/10-machine.conf。

Docker 跨主機網絡 overlay(十六)

--cluster-store 指定 consul 的地址。
--cluster-advertise 告知 consul 自己的連接地址。

重啓 docker daemon。

systemctl daemon-reload  
systemctl restart docker.service

host1 和 host2 將自動註冊到 Consul 數據庫中。

Docker 跨主機網絡 overlay(十六)

4、準備就緒

準備就緒,實驗環境如下圖:

Docker 跨主機網絡 overlay(十六)

三、創建 overlay 網絡

1、在 host1 中創建網絡

在 host1 中創建 overlay 網絡 ov_net1。

[root@ubuntu ~ [host1]]# docker network create -d overlay ov_net1
49a8ea9add6a80d44cbd6becf22d66af40072cf9c3a346d66f94a6e72d8042e5

-d overlay 指定 driver 爲 overlay。

docker network ls 查看當前網絡:

[root@ubuntu ~ [host1]]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
d0829fccb85c        bridge              bridge              local
f59af6b0b523        host                host                local
2613e0c2029e        none                null                local
49a8ea9add6a        ov_net1             overlay             global

2、host2 查看創建的網絡

注意到 ov_net1 的 SCOPE 爲 global,而其他網絡爲 local。在 host2 上查看存在的網絡:

[root@ubuntu ~ [host1]]# eval $(docker-machine env host2)
[root@ubuntu ~ [host2]]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
25f2e4a0bc16        bridge              bridge              local
bdab05c9c6b9        host                host                local
240f2dc93d43        none                null                local
49a8ea9add6a        ov_net1             overlay             global

host2 上也能看到 ov_net1。這是因爲創建 ov_net1 時 host1 將 overlay 網絡信息存入了 consul,host2 從 consul 讀取到了新網絡的數據。之後 ov_net 的任何變化都會同步到 host1 和 host2。

3、查看 ov_net1 詳細信息

[root@ubuntu ~ [host2]]# docker network inspect ov_net1
[
    {
        "Name": "ov_net1",
        "Id": "49a8ea9add6a80d44cbd6becf22d66af40072cf9c3a346d66f94a6e72d8042e5",
        "Created": "2018-05-03T11:29:11.802222991+08:00",
        "Scope": "global",
        "Driver": "overlay",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "10.0.0.0/24",
                    "Gateway": "10.0.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

IPAM 是指 IP Address Management,docker 自動爲 ov_net1 分配的 IP 空間爲 10.0.0.0/24。

四、在 overlay 中運行容器

1、創建容器 bbox1

在 host1 運行一個 busybox 容器並連接到 ov_net1。

[root@ubuntu ~ [host1]]# docker run -itd --name bbox1 --network ov_net1 busybox 
5246d782fc8fd30890bcf2bb34374c54db3ee277cae585572f4b20129b68e3fe

2、查看 bbox1 網絡配置

[root@ubuntu ~ [host1]]# docker exec bbox1 ip r
default via 172.18.0.1 dev eth1 
10.0.0.0/24 dev eth0 scope link  src 10.0.0.2 
172.18.0.0/16 dev eth1 scope link  src 172.18.0.2 

bbox1 有兩個網絡接口 eth0 和 eth1。
eth0 IP 爲 10.0.0.2,連接的是 overlay 網絡 ov_net1。eth1 IP 172.18.0.2,容器的默認路由是走 eth1,其實,docker 會創建一個 bridge 網絡 “docker_gwbridge”,爲所有連接到 overlay 網絡的容器提供訪問外網的能力。

[root@ubuntu ~ [host1]]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
74bdaebd8ae5        bridge              bridge              local
604a0b967e13        docker_gwbridge     bridge              local
f59af6b0b523        host                host                local
2613e0c2029e        none                null                local
49a8ea9add6a        ov_net1             overlay             global

從 docker network inspect docker_gwbridge 輸出可確認 docker_gwbridge 的 IP 地址範圍是 172.18.0.0/16,當前連接的容器就是 bbox1(172.18.0.2)。

[root@ubuntu ~ [host1]]# docker network inspect docker_gwbridge
[
    {
        "Name": "docker_gwbridge",
        "Id": "604a0b967e135d41c605547b65853a7a1315fceefe99c051d7a001e4e1207c1c",
        "Created": "2018-05-03T11:40:44.426460442+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "eba09cf91fa34e3a7eb1ab20047ce08ed8fb0ac4d8f2dc9ddf9a08116575eba2": {
                "Name": "gateway_eba09cf91fa3",
                "EndpointID": "3dd836e9db9ec3250cfa3bc1662ab8822918a7ea3a30b9e24e2ee7151f5f75b0",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.enable_icc": "false",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.name": "docker_gwbridge"
        },
        "Labels": {}
    }
]

而且此網絡的網關就是網橋 docker_gwbridge 的 IP 172.18.0.1,在 host1 上面查看。

root@host1:~# ifconfig docker_gwbridge
docker_gwbridge Link encap:Ethernet  HWaddr 02:42:95:80:cf:70  
          inet addr:172.18.0.1  Bcast:172.18.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:95ff:fe80:cf70/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 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:0 (0.0 B)  TX bytes:648 (648.0 B)

這樣容器 bbox1 就可以通過 docker_gwbridge 訪問外網。

Docker 跨主機網絡 overlay(十六)

五、overlay 網絡連通性

1、host2 中運行 bbox2

[root@ubuntu ~ [host2]]# docker run -itd --name bbox2 --network ov_net1 busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
f70adabe43c0: Pull complete 
Digest: sha256:58ac43b2cc92c687a32c8be6278e50a063579655fe3090125dcb2af0ff9e1a64
Status: Downloaded newer image for busybox:latest
457e0e4363216d3fe70ea471f3c671863f166bf6d64edf1a92232d0cb585bd85

2、查看 bbox2 路由情況

[root@ubuntu ~ [host2]]# docker exec bbox2 ip r 
default via 172.18.0.1 dev eth1 
10.0.0.0/24 dev eth0 scope link  src 10.0.0.3 
172.18.0.0/16 dev eth1 scope link  src 172.18.0.2 

3、互通測試

bbox2 IP 爲 10.0.0.3,可以直接 ping bbox1:

[root@ubuntu ~ [host2]]# docker exec bbox2 ping -c 2 bbox1
PING bbox1 (10.0.0.2): 56 data bytes
64 bytes from 10.0.0.2: seq=0 ttl=64 time=24.710 ms
64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.524 ms

--- bbox1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.524/12.617/24.710 ms

可見 overlay 網絡中的容器可以直接通信,同時 docker 也實現了 DNS 服務。

4、實現原理

docker 會爲每個 overlay 網絡創建一個獨立的 network namespace,其中會有一個 linux bridge br0, veth pair 一端連接到容器中(即 eth0),另一端連接到 namespace 的 br0 上。

br0 除了連接所有的 veth pair,還會連接一個 vxlan 設備,用於與其他 host 建立 vxlan tunnel。容器之間的數據就是通過這個 tunnel 通信的。邏輯網絡拓撲結構如圖所示:

root@host1:~# brctl show              
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242cf3d50df       no
docker_gwbridge         8000.02429580cf70       no              vethb08d6be
root@host2:~# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242303d222f       no
docker_gwbridge         8000.02423eb55e58       no              vethdb98439

Docker 跨主機網絡 overlay(十六)

要查看 overlay 網絡的 namespace 可以在 host1 和 host2 上執行 ip netns(請確保在此之前執行過 ln -s /var/run/docker/netns /var/run/netns),可以看到兩個 host 上有一個相同的 namespace "1-49a8ea9add":

root@host1:~# ip netns
c0052da621d7 (id: 1)
1-49a8ea9add (id: 0)
root@host2:~# ip netns
e486246b39d9 (id: 1)
1-49a8ea9add (id: 0)

"1-49a8ea9add" 這就是 ov_net1 的 namespace,查看 namespace 中的 br0 上的設備。

root@host1:~# ip netns exec 1-49a8ea9add brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.767c8828d7b0       no              veth0
                                                        vxlan0

六、overlay 網絡隔離

1、創建網絡 ov_net2

不同的 overlay 網絡是相互隔離的。我們創建第二個 overlay 網絡 ov_net2 並運行容器 bbox3。

root@host1:~# docker network create -d overlay ov_net2
7c2ac9ec1a0ec477aa9230bcfffd91b1b79bee6ea7007a7a5de20ccae0b3d91c

2、啓動容器 bbox3

root@host1:~# docker run -itd --name bbox3 --network ov_net2 busybox
1a3d81915a57b195a8b0baa2d1444bbeb5c947e7e203752ed975d6a900dbb141

3、查看 bbox3 網絡

bbox3 分配到的 IP 是 10.0.1.2,嘗試 ping bbox1(10.0.0.2)。

root@host1:~# docker exec -it bbox3 ip r
default via 172.18.0.1 dev eth1 
10.0.1.0/24 dev eth0 scope link  src 10.0.1.2 
172.18.0.0/16 dev eth1 scope link  src 172.18.0.3 

Docker 跨主機網絡 overlay(十六)

ping 失敗,可見不同 overlay 網絡之間是隔離的。即便是通過 docker_gwbridge 也不能通信。

Docker 跨主機網絡 overlay(十六)

如果要實現 bbox3 與 bbox1 通信,可以將 bbox3 也連接到 ov_net1。

docker network connect ov_net1 bbox3

Docker 跨主機網絡 overlay(十六)

docker 默認爲 overlay 網絡分配 24 位掩碼的子網(10.0.X.0/24),所有主機共享這個 subnet,容器啓動時會順序從此空間分配 IP。當然我們也可以通過 --subnet 指定 IP 空間。

docker network create -d overlay --subnet 10.22.1.0/24 ov_net3
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章