使用覆蓋網路聯網
本系列教程討論了針對 Swarm 服務的網路。有關獨立容器的網路,請參閱 獨立容器的網路。如果您需要了解有關 Docker 網路的更多資訊,請參閱 概述。
本頁包含以下教程。您可以在 Linux、Windows 或 Mac 上執行每個教程,但對於最後一個教程,您需要另一個在其他位置執行的 Docker 主機。
使用預設覆蓋網路 演示瞭如何使用 Docker 在您初始化或加入 Swarm 時自動為您設定的預設覆蓋網路。此網路不是生產系統的最佳選擇。
使用使用者定義的覆蓋網路 展示瞭如何建立和使用您自己的自定義覆蓋網路來連線服務。建議在生產環境中執行的服務使用此方法。
將覆蓋網路用於獨立容器 展示瞭如何使用覆蓋網路在不同 Docker 守護程式上的獨立容器之間進行通訊。
先決條件
這些教程要求您至少擁有單個節點 Swarm,這意味著您已啟動 Docker 並在主機上運行了 docker swarm init
。您也可以在多節點 Swarm 上執行這些示例。
使用預設覆蓋網路
在此示例中,您啟動 alpine
服務並從各個服務容器的角度檢查網路的特性。
本教程不會深入介紹有關覆蓋網路實現方式的作業系統特定細節,而是重點介紹覆蓋網路從服務角度的功能。
先決條件
本教程需要三個物理或虛擬 Docker 主機,這些主機可以彼此通訊。本教程假設這三個主機在同一個網路上執行,並且沒有涉及防火牆。
這些主機將分別稱為 manager
、worker-1
和 worker-2
。manager
主機將同時充當管理器和工作節點,這意味著它可以同時執行服務任務和管理 Swarm。worker-1
和 worker-2
將僅充當工作節點。
如果您沒有三個主機,一個簡單的解決方案是在像 Amazon EC2 這樣的雲提供商上設定三個 Ubuntu 主機,這些主機都在同一個網路上,並且所有主機之間都允許通訊(使用 EC2 安全組等機制),然後按照 Ubuntu 上 Docker Engine - Community 的安裝說明 進行操作。
演練
建立 Swarm
完成此過程後,所有三個 Docker 主機都將加入 Swarm,並將使用名為 ingress
的覆蓋網路連線在一起。
在
manager
上,初始化 Swarm。如果主機只有一個網路介面,則--advertise-addr
標誌是可選的。$ docker swarm init --advertise-addr=<IP-ADDRESS-OF-MANAGER>
記下列印的文字,因為其中包含用於將
worker-1
和worker-2
加入 Swarm 的令牌。建議將令牌儲存在密碼管理器中。在
worker-1
上,加入 Swarm。如果主機只有一個網路介面,則--advertise-addr
標誌是可選的。$ docker swarm join --token <TOKEN> \ --advertise-addr <IP-ADDRESS-OF-WORKER-1> \ <IP-ADDRESS-OF-MANAGER>:2377
在
worker-2
上,加入 Swarm。如果主機只有一個網路介面,則--advertise-addr
標誌是可選的。$ docker swarm join --token <TOKEN> \ --advertise-addr <IP-ADDRESS-OF-WORKER-2> \ <IP-ADDRESS-OF-MANAGER>:2377
在
manager
上,列出所有節點。此命令只能從管理器執行。$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS d68ace5iraw6whp7llvgjpu48 * ip-172-31-34-146 Ready Active Leader nvp5rwavvb8lhdggo8fcf7plg ip-172-31-35-151 Ready Active ouvx2l7qfcxisoyms8mtkgahw ip-172-31-36-89 Ready Active
您還可以使用
--filter
標誌按角色進行過濾$ docker node ls --filter role=manager ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS d68ace5iraw6whp7llvgjpu48 * ip-172-31-34-146 Ready Active Leader $ docker node ls --filter role=worker ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS nvp5rwavvb8lhdggo8fcf7plg ip-172-31-35-151 Ready Active ouvx2l7qfcxisoyms8mtkgahw ip-172-31-36-89 Ready Active
列出
manager
、worker-1
和worker-2
上的 Docker 網路,並注意它們現在都具有一個名為ingress
的覆蓋網路和一個名為docker_gwbridge
的橋接網路。這裡只顯示了manager
的列表$ docker network ls NETWORK ID NAME DRIVER SCOPE 495c570066be bridge bridge local 961c6cae9945 docker_gwbridge bridge local ff35ceda3643 host host local trtnl4tqnc3n ingress overlay swarm c8357deec9cb none null local
docker_gwbridge
將 ingress
網路連線到 Docker 主機的網路介面,以便流量可以流向和流出 Swarm 管理器和工作節點。如果您建立 Swarm 服務並且沒有指定網路,它們將連線到 ingress
網路。建議您為每個應用程式或將協同工作的應用程式組使用單獨的覆蓋網路。在下一個過程中,您將建立兩個覆蓋網路並將服務連線到每個網路。
建立服務
在
manager
上,建立一個名為nginx-net
的新覆蓋網路$ docker network create -d overlay nginx-net
您無需在其他節點上建立覆蓋網路,因為當其中一個節點開始執行需要它的服務任務時,它將自動建立。
在
manager
上,建立一個連線到nginx-net
的 5 個副本的 Nginx 服務。該服務將埠 80 釋出到外部世界。所有服務任務容器都可以相互通訊,而無需開啟任何埠。注意
服務只能在管理器上建立。
$ docker service create \ --name my-nginx \ --publish target=80,published=80 \ --replicas=5 \ --network nginx-net \ nginx
ingress
的預設釋出模式(在您未為--publish
標誌指定mode
時使用)意味著如果您瀏覽到manager
、worker-1
或worker-2
上的埠 80,您將連線到 5 個服務任務之一的埠 80,即使當前沒有任務在您瀏覽到的節點上執行。如果您想使用host
模式釋出埠,可以在--publish
輸出中新增mode=host
。但是,在這種情況下,您還應該使用--mode global
而不是--replicas=5
,因為在給定節點上,只有一個服務任務可以繫結給定埠。執行
docker service ls
以監控服務啟動的進度,這可能需要幾秒鐘。檢查
manager
、worker-1
和worker-2
上的nginx-net
網路。請記住,您無需在worker-1
和worker-2
上手動建立它,因為 Docker 會為您建立它。輸出將很長,但請注意Containers
和Peers
部分。Containers
列出了從該主機連線到覆蓋網路的所有服務任務(或獨立容器)。從
manager
,使用docker service inspect my-nginx
檢查服務,並注意有關服務使用的埠和端點的資訊。建立一個名為
nginx-net-2
的新網路,然後更新服務以使用此網路而不是nginx-net
$ docker network create -d overlay nginx-net-2
$ docker service update \ --network-add nginx-net-2 \ --network-rm nginx-net \ my-nginx
執行
docker service ls
以驗證服務是否已更新,並且所有任務是否已重新部署。執行docker network inspect nginx-net
以驗證沒有任何容器連線到它。對nginx-net-2
執行相同的命令,並注意所有服務任務容器都連線到它。注意
即使覆蓋網路在需要時會在 Swarm 工作節點上自動建立,但它們不會自動刪除。
清理服務和網路。從
manager
執行以下命令。管理器將指示工作節點自動刪除網路。$ docker service rm my-nginx $ docker network rm nginx-net nginx-net-2
使用使用者定義的覆蓋網路
先決條件
本教程假設 Swarm 已設定,並且您位於管理器上。
演練
建立使用者定義的覆蓋網路。
$ docker network create -d overlay my-overlay
使用覆蓋網路啟動服務,並將埠 80 釋出到 Docker 主機上的埠 8080。
$ docker service create \ --name my-nginx \ --network my-overlay \ --replicas 1 \ --publish published=8080,target=80 \ nginx:latest
執行
docker network inspect my-overlay
並驗證my-nginx
服務任務是否連線到它,方法是檢視Containers
部分。刪除服務和網路。
$ docker service rm my-nginx $ docker network rm my-overlay
將覆蓋網路用於獨立容器
此示例演示了 DNS 容器發現,具體來說,是如何使用覆蓋網路在不同 Docker 守護程式上的獨立容器之間進行通訊。步驟如下
- 在
host1
上,將節點初始化為 Swarm(管理器)。 - 在
host2
上,將節點加入 Swarm(工作節點)。 - 在
host1
上,建立一個可附加的覆蓋網路(test-net
)。 - 在
host1
上,執行一個互動式 alpine 容器(alpine1
)在test-net
上。 - 在
host2
上,執行一個互動式且分離的alpine 容器 (alpine2
) 在test-net
上。 - 在
host1
上,從alpine1
會話中,pingalpine2
。
先決條件
對於此測試,您需要兩個可以相互通訊的不同 Docker 主機。每個主機必須在兩個 Docker 主機之間開啟以下埠
- TCP 埠 2377
- TCP 和 UDP 埠 7946
- UDP 埠 4789
設定此操作的一種簡單方法是擁有兩臺虛擬機器(本地或在 AWS 等雲提供商上),每臺都安裝並執行 Docker。如果您使用 AWS 或類似的雲計算平臺,最簡單的配置是使用安全組,該組在兩個主機之間開啟所有傳入埠以及來自您客戶端 IP 地址的 SSH 埠。
此示例將我們 swarm 中的兩個節點稱為host1
和 host2
。此示例還使用 Linux 主機,但相同的命令在 Windows 上也能正常工作。
演練
設定 swarm。
a. 在
host1
上,初始化一個 swarm(如果提示,使用--advertise-addr
指定與 swarm 中其他主機通訊的介面的 IP 地址,例如,AWS 上的私有 IP 地址)$ docker swarm init Swarm initialized: current node (vz1mm9am11qcmo979tlrlox42) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-5g90q48weqrtqryq4kj6ow0e8xm9wmv9o6vgqc5j320ymybd5c-8ex8j0bc40s6hgvy5ui5gl4gy 172.31.47.252:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
b. 在
host2
上,按照上述說明加入 swarm$ docker swarm join --token <your_token> <your_ip_address>:2377 This node joined a swarm as a worker.
如果節點無法加入 swarm,則
docker swarm join
命令會超時。要解決此問題,請在host2
上執行docker swarm leave --force
,驗證您的網路和防火牆設定,然後重試。在
host1
上,建立一個名為test-net
的可附加覆蓋網路$ docker network create --driver=overlay --attachable test-net uqsof8phj3ak0rq9k86zta6ht
注意返回的 **NETWORK ID** -- 您將在從
host2
連線時再次看到它。在
host1
上,啟動一個互動式 (-it
) 容器 (alpine1
),該容器連線到test-net
$ docker run -it --name alpine1 --network test-net alpine / #
在
host2
上,列出可用的網路 -- 注意test-net
尚未存在$ docker network ls NETWORK ID NAME DRIVER SCOPE ec299350b504 bridge bridge local 66e77d0d0e9a docker_gwbridge bridge local 9f6ae26ccb82 host host local omvdxqrda80z ingress overlay swarm b65c952a4b2b none null local
在
host2
上,啟動一個分離的 (-d
) 和互動式的 (-it
) 容器 (alpine2
),該容器連線到test-net
$ docker run -dit --name alpine2 --network test-net alpine fb635f5ece59563e7b8b99556f816d24e6949a5f6a5b1fbd92ca244db17a4342
注意
自動 DNS 容器發現僅適用於具有唯一容器名稱的容器。
在
host2
上,驗證test-net
是否已建立(並且具有與host1
上的test-net
相同的 NETWORK ID)$ docker network ls NETWORK ID NAME DRIVER SCOPE ... uqsof8phj3ak test-net overlay swarm
在
host1
上,在alpine1
的互動式終端中 pingalpine2
/ # ping -c 2 alpine2 PING alpine2 (10.0.0.5): 56 data bytes 64 bytes from 10.0.0.5: seq=0 ttl=64 time=0.600 ms 64 bytes from 10.0.0.5: seq=1 ttl=64 time=0.555 ms --- alpine2 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.555/0.577/0.600 ms
兩個容器透過連線兩個主機的覆蓋網路進行通訊。如果您在
host2
上執行另一個非分離 的 alpine 容器,則可以從host2
pingalpine1
(並且在這裡我們添加了刪除選項,以便自動清理容器)$ docker run -it --rm --name alpine3 --network test-net alpine / # ping -c 2 alpine1 / # exit
在
host1
上,關閉alpine1
會話(這也將停止容器)/ # exit
清理您的容器和網路
您必須分別停止並刪除每個主機上的容器,因為 Docker 守護程式獨立執行,這些是獨立的容器。您只需要在
host1
上刪除網路,因為當您在host2
上停止alpine2
時,test-net
會消失。a. 在
host2
上,停止alpine2
,檢查test-net
是否已刪除,然後刪除alpine2
$ docker container stop alpine2 $ docker network ls $ docker container rm alpine2
a. 在
host1
上,刪除alpine1
和test-net
$ docker container rm alpine1 $ docker network rm test-net