使用覆蓋網路進行網路連線
本系列教學課程處理 Swarm 服務的網路連線。若要瞭解獨立容器的網路連線,請參閱使用獨立容器進行網路連線。如果您需要進一步瞭解 Docker 網路,請參閱概觀。
本頁面包含以下教學課程。您可以在 Linux、Windows 或 Mac 上執行每個教學課程,但對於最後一個教學課程,您需要在其他地方執行第二個 Docker 主機。
使用預設覆蓋網路示範如何在初始化或加入 Swarm 時使用 Docker 自動為您設定的預設覆蓋網路。此網路並非生產系統的最佳選擇。
使用使用者定義的覆蓋網路示範如何建立和使用您自己的自訂覆蓋網路來連接服務。建議用於在生產環境中執行的服務。
將覆蓋網路用於獨立容器示範如何使用覆蓋網路在不同 Docker 惡魔上的獨立容器之間進行通訊。
先決條件
這些都需要您至少擁有一個單節點 Swarm,這表示您已在主機上啟動 Docker 並執行 docker swarm init
。
使用預設覆蓋網路
在此範例中,您將啟動 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
模式發佈埠,您可以將mode=host
添加到--publish
輸出中。但是,在此情況下,您也應該使用--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
使用覆蓋網路啟動服務,並將 Docker 主機上的 80 埠發佈到 8080 埠。
$ docker service create \ --name my-nginx \ --network my-overlay \ --replicas 1 \ --publish published=8080,target=80 \ nginx:latest
執行
docker network inspect my-overlay
並透過查看Containers
區段來驗證my-nginx
服務任務已連接到它。移除服務和網路。
$ docker service rm my-nginx $ docker network rm my-overlay
將覆蓋網路用於獨立容器
此範例示範了 DNS 容器發現 - specifically, 如何使用覆蓋網路在不同 Docker 守護行程式上獨立容器之間進行通訊。步驟如下:
- 在
host1
上,將節點初始化為 Swarm(管理節點)。 - 在
host2
上,將節點加入 Swarm(工作節點)。 - 在
host1
上,建立一個可附加的覆蓋網路(test-net
)。 - 在
host1
上,在test-net
上執行一個互動式 alpine 容器(alpine1
)。 - 在
host2
上,在test-net
上執行一個互動式且分離的 alpine 容器(alpine2
)。 - 在
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
請注意返回的**網路 ID** - 當您從
host2
連接到它時,您將會再次看到它。在
host1
上,啟動一個連接到test-net
的互動式 (-it
) 容器 (alpine1
)$ 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
上,啟動一個連接到test-net
的分離 (-d
) 和互動式 (-it
) 容器 (alpine2
)$ docker run -dit --name alpine2 --network test-net alpine fb635f5ece59563e7b8b99556f816d24e6949a5f6a5b1fbd92ca244db17a4342
注意事項
自動 DNS 容器發現僅適用於唯一的容器名稱。
在
host2
上,驗證test-net
已建立(並且與host1
上的test-net
具有相同的網路 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