管理 swarm 服務網路
本頁介紹 Swarm 服務的網路。
Swarm 和流量型別
Docker Swarm 生成兩種不同型別的流量
控制和管理平面流量:這包括 Swarm 管理訊息,例如加入或離開 Swarm 的請求。此流量始終加密。
應用程式資料平面流量:這包括容器流量和往返於外部客戶端的流量。
關鍵網路概念
以下三個網路概念對 Swarm 服務非常重要
覆蓋網路管理參與 Swarm 的 Docker 守護程序之間的通訊。您可以建立覆蓋網路,就像為獨立容器建立使用者定義網路一樣。您還可以將服務附加到一個或多個現有的覆蓋網路,以實現服務到服務的通訊。覆蓋網路是使用 `overlay` 網路驅動程式的 Docker 網路。
入口網路是一個特殊的覆蓋網路,它有助於服務節點之間的負載均衡。當任何 Swarm 節點在已釋出的埠上收到請求時,它會將該請求傳遞給一個名為 `IPVS` 的模組。`IPVS` 跟蹤參與該服務的所有 IP 地址,選擇其中一個,並透過 `ingress` 網路將請求路由到它。
當您初始化或加入 Swarm 時,`ingress` 網路會自動建立。大多數使用者不需要自定義其配置,但 Docker 允許您這樣做。
`docker_gwbridge` 是一個橋接網路,它將覆蓋網路(包括 `ingress` 網路)連線到單個 Docker 守護程序的物理網路。預設情況下,服務執行的每個容器都連線到其本地 Docker 守護程序主機的 `docker_gwbridge` 網路。
當您初始化或加入 Swarm 時,`docker_gwbridge` 網路會自動建立。大多數使用者不需要自定義其配置,但 Docker 允許您這樣做。
提示另請參閱 網路概述 以獲取有關 Swarm 網路的更多詳細資訊。
防火牆注意事項
參與 Swarm 的 Docker 守護程序需要能夠透過以下埠進行通訊
- 埠 `7946` TCP/UDP 用於容器網路發現。
- 埠 `4789` UDP(可配置)用於覆蓋網路(包括入口)資料路徑。
在 Swarm 中設定網路時,應特別小心。有關概述,請參閱教程。
覆蓋網路
當您初始化一個 Swarm 或將一個 Docker 主機加入到現有 Swarm 時,該 Docker 主機上會建立兩個新網路
- 一個名為 `ingress` 的覆蓋網路,它處理與 Swarm 服務相關的控制和資料流量。當您建立一個 Swarm 服務並且沒有將其連線到使用者定義的覆蓋網路時,它會預設連線到 `ingress` 網路。
- 一個名為 `docker_gwbridge` 的橋接網路,它將單個 Docker 守護程序連線到參與 Swarm 的其他守護程序。
建立覆蓋網路
要建立覆蓋網路,請在使用 `docker network create` 命令時指定 `overlay` 驅動程式
$ docker network create \
--driver overlay \
my-network
上述命令沒有指定任何自定義選項,因此 Docker 會分配一個子網並使用預設選項。您可以使用 `docker network inspect` 檢視有關網路的資訊。
當沒有容器連線到覆蓋網路時,其配置並不是很令人興奮
$ docker network inspect my-network
[
{
"Name": "my-network",
"Id": "fsf1dmx3i9q75an49z36jycxd",
"Created": "0001-01-01T00:00:00Z",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": []
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"Containers": null,
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "4097"
},
"Labels": null
}
]
在上面的輸出中,請注意驅動程式是 `overlay`,作用域是 `swarm`,而不是您可能在其他型別的 Docker 網路中看到的 `local`、`host` 或 `global` 作用域。此作用域表示只有參與 Swarm 的主機才能訪問此網路。
當服務首次連線到網路時,網路的子網和閘道器是動態配置的。以下示例顯示了與上面相同的網路,但有三個 `redis` 服務的容器連線到它。
$ docker network inspect my-network
[
{
"Name": "my-network",
"Id": "fsf1dmx3i9q75an49z36jycxd",
"Created": "2017-05-31T18:35:58.877628262Z",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.0.0/24",
"Gateway": "10.0.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"Containers": {
"0e08442918814c2275c31321f877a47569ba3447498db10e25d234e47773756d": {
"Name": "my-redis.1.ka6oo5cfmxbe6mq8qat2djgyj",
"EndpointID": "950ce63a3ace13fe7ef40724afbdb297a50642b6d47f83a5ca8636d44039e1dd",
"MacAddress": "02:42:0a:00:00:03",
"IPv4Address": "10.0.0.3/24",
"IPv6Address": ""
},
"88d55505c2a02632c1e0e42930bcde7e2fa6e3cce074507908dc4b827016b833": {
"Name": "my-redis.2.s7vlybipal9xlmjfqnt6qwz5e",
"EndpointID": "dd822cb68bcd4ae172e29c321ced70b731b9994eee5a4ad1d807d9ae80ecc365",
"MacAddress": "02:42:0a:00:00:05",
"IPv4Address": "10.0.0.5/24",
"IPv6Address": ""
},
"9ed165407384f1276e5cfb0e065e7914adbf2658794fd861cfb9b991eddca754": {
"Name": "my-redis.3.hbz3uk3hi5gb61xhxol27hl7d",
"EndpointID": "f62c686a34c9f4d70a47b869576c37dffe5200732e1dd6609b488581634cf5d2",
"MacAddress": "02:42:0a:00:00:04",
"IPv4Address": "10.0.0.4/24",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "4097"
},
"Labels": {},
"Peers": [
{
"Name": "moby-e57c567e25e2",
"IP": "192.168.65.2"
}
]
}
]
自定義覆蓋網路
在某些情況下,您可能不想使用覆蓋網路的預設配置。有關可配置選項的完整列表,請執行命令 `docker network create --help`。以下是一些最常更改的選項。
配置子網和閘道器
預設情況下,當第一個服務連線到網路時,會自動配置網路的子網和閘道器。您可以在建立網路時使用 `--subnet` 和 `--gateway` 標誌來配置這些。以下示例透過配置子網和閘道器擴充套件了前一個示例。
$ docker network create \
--driver overlay \
--subnet 10.0.9.0/24 \
--gateway 10.0.9.99 \
my-network
使用自定義預設地址池
要自定義 Swarm 網路的子網分配,您可以在 `swarm init` 期間選擇性地配置它們。
例如,以下命令在初始化 Swarm 時使用
$ docker swarm init --default-addr-pool 10.20.0.0/16 --default-addr-pool-mask-length 26
每當使用者建立一個網路,但未使用 `--subnet` 命令列選項時,該網路的子網將從池中下一個可用的子網順序分配。如果指定的網路已分配,則該網路將不用於 Swarm。
如果需要不連續的地址空間,可以配置多個池。但是,不支援從特定池進行分配。網路子網將從 IP 池空間順序分配,並且當子網從已刪除的網路中釋放時,它們將被重用。
可以配置預設掩碼長度,並且對所有網路都相同。預設設定為 `/24`。要更改預設子網掩碼長度,請使用 `--default-addr-pool-mask-length` 命令列選項。
注意預設地址池只能在 `swarm init` 時配置,並且在叢集建立後無法更改。
覆蓋網路大小限制
Docker 建議使用 `/24` 塊建立覆蓋網路。`/24` 覆蓋網路塊將網路限制為 256 個 IP 地址。
此建議解決了Swarm 模式的限制。如果您需要超過 256 個 IP 地址,請不要增加 IP 塊大小。您可以使用帶有外部負載均衡器的 `dnsrr` 端點模式,或使用多個較小的覆蓋網路。有關不同端點模式的更多資訊,請參閱配置服務發現。
配置應用程式資料加密
與 Swarm 相關的管理和控制平面資料始終是加密的。有關加密機制的更多詳細資訊,請參閱 Docker Swarm 模式覆蓋網路安全模型。
Swarm 節點之間的應用程式資料預設不加密。要在給定的覆蓋網路上加密此流量,請在 `docker network create` 上使用 `--opt encrypted` 標誌。這將在 vxlan 級別啟用 IPSEC 加密。此加密會帶來不可忽視的效能損失,因此您應在生產中使用此選項之前進行測試。
注意您必須自定義自動建立的入口網路以啟用加密。預設情況下,所有入口流量都是未加密的,因為加密是一個網路級別的選項。
將服務附加到覆蓋網路
要將服務附加到現有覆蓋網路,請將 `--network` 標誌傳遞給 `docker service create`,或將 `--network-add` 標誌傳遞給 `docker service update`。
$ docker service create \
--replicas 3 \
--name my-web \
--network my-network \
nginx
連線到覆蓋網路的服務容器可以透過它相互通訊。
要檢視服務連線到哪些網路,請使用 `docker service ls` 查詢服務名稱,然後使用 `docker service ps <service-name>` 列出網路。或者,要檢視哪些服務的容器連線到網路,請使用 `docker network inspect <network-name>`。您可以從任何已加入 Swarm 且處於 `running` 狀態的 Swarm 節點執行這些命令。
配置服務發現
服務發現是 Docker 用於將來自服務外部客戶端的請求路由到單個 Swarm 節點,而客戶端無需知道參與服務的節點數量或其 IP 地址或埠的機制。您不需要釋出在同一網路上服務之間使用的埠。例如,如果您有一個將資料儲存在 MySQL 服務中的 WordPress 服務,並且它們連線到同一個覆蓋網路,則無需向客戶端釋出 MySQL 埠,只需釋出 WordPress HTTP 埠即可。
服務發現可以透過兩種不同的方式工作:使用嵌入式 DNS 和虛擬 IP (VIP) 在第 3 層和第 4 層進行基於內部連線的負載均衡,或使用 DNS 輪詢 (DNSRR) 在第 7 層進行基於外部和自定義請求的負載均衡。您可以為每個服務配置此項。
預設情況下,當您將服務附加到網路並且該服務釋出一個或多個埠時,Docker 會為該服務分配一個虛擬 IP (VIP),這是客戶端訪問該服務的前端。Docker 會保留服務中所有工作節點的列表,並在客戶端和一個節點之間路由請求。來自客戶端的每個請求都可能被路由到不同的節點。
如果您將服務配置為使用 DNS 輪詢 (DNSRR) 服務發現,則沒有單個虛擬 IP。相反,Docker 會為服務設定 DNS 條目,以便對服務名稱的 DNS 查詢返回一個 IP 地址列表,客戶端直接連線到其中一個。
當您想要使用自己的負載均衡器(例如 HAProxy)時,DNS 輪詢非常有用。要將服務配置為使用 DNSRR,請在建立新服務或更新現有服務時使用 `--endpoint-mode dnsrr` 標誌。
自定義入口網路
大多數使用者永遠不需要配置 `ingress` 網路,但 Docker 允許您這樣做。如果自動選擇的子網與網路上已存在的子網衝突,或者您需要自定義其他低階網路設定(如 MTU),或者您想啟用加密,這可能會很有用。
自定義 `ingress` 網路涉及刪除並重新建立它。這通常在您在 Swarm 中建立任何服務之前完成。如果您有釋出埠的現有服務,則需要先刪除這些服務,然後才能刪除 `ingress` 網路。
在沒有 `ingress` 網路期間,不釋出埠的現有服務將繼續執行,但不會進行負載均衡。這會影響釋出埠的服務,例如釋出埠 80 的 WordPress 服務。
使用 `docker network inspect ingress` 檢查 `ingress` 網路,並刪除其容器連線到該網路的任何服務。這些是釋出埠的服務,例如釋出埠 80 的 WordPress 服務。如果未停止所有此類服務,下一步將失敗。
刪除現有的 `ingress` 網路
$ docker network rm ingress WARNING! Before removing the routing-mesh network, make sure all the nodes in your swarm run the same docker engine version. Otherwise, removal may not be effective and functionality of newly created ingress networks will be impaired. Are you sure you want to continue? [y/N]
使用 `--ingress` 標誌建立一個新的覆蓋網路,並附帶您要設定的自定義選項。此示例將 MTU 設定為 1200,將子網設定為 `10.11.0.0/16`,並將閘道器設定為 `10.11.0.2`。
$ docker network create \ --driver overlay \ --ingress \ --subnet=10.11.0.0/16 \ --gateway=10.11.0.2 \ --opt com.docker.network.driver.mtu=1200 \ my-ingress
注意您可以將 `ingress` 網路命名為 `ingress` 以外的名稱,但只能有一個。嘗試建立第二個會失敗。
重新啟動您在第一步中停止的服務。
自定義 docker_gwbridge
`docker_gwbridge` 是一個虛擬網橋,它將覆蓋網路(包括 `ingress` 網路)連線到單個 Docker 守護程序的物理網路。當您初始化一個 Swarm 或將一個 Docker 主機加入到 Swarm 時,Docker 會自動建立它,但它不是一個 Docker 裝置。它存在於 Docker 主機的核心中。如果您需要自定義其設定,則必須在將 Docker 主機加入 Swarm 之前或暫時從 Swarm 中刪除主機之後進行。
您需要在作業系統上安裝 `brctl` 應用程式才能刪除現有網橋。包名為 `bridge-utils`。
停止 Docker。
使用 `brctl show docker_gwbridge` 命令檢查是否存在名為 `docker_gwbridge` 的網橋裝置。如果存在,請使用 `brctl delbr docker_gwbridge` 刪除它。
啟動 Docker。不要加入或初始化 Swarm。
使用您的自定義設定建立或重新建立 `docker_gwbridge` 網橋。此示例使用子網 `10.11.0.0/16`。有關可自定義選項的完整列表,請參閱網橋驅動程式選項。
$ docker network create \ --subnet 10.11.0.0/16 \ --opt com.docker.network.bridge.name=docker_gwbridge \ --opt com.docker.network.bridge.enable_icc=false \ --opt com.docker.network.bridge.enable_ip_masquerade=true \ docker_gwbridge
初始化或加入 Swarm。
為控制和資料流量使用單獨的介面
預設情況下,所有 Swarm 流量都透過同一個介面傳送,包括用於維護 Swarm 本身的控制和管理流量以及往返於服務容器的資料流量。
您可以在初始化或加入 Swarm 時透過傳遞 `--data-path-addr` 標誌來分離此流量。如果有多個介面,則必須明確指定 `--advertise-addr`,如果未指定,`--data-path-addr` 預設為 `--advertise-addr`。有關加入、離開和管理 Swarm 的流量透過 `--advertise-addr` 介面傳送,服務容器之間的流量透過 `--data-path-addr` 介面傳送。這些標誌可以採用 IP 地址或網路裝置名稱,例如 `eth0`。
此示例使用單獨的 `--data-path-addr` 初始化 Swarm。它假定您的 Docker 主機有兩個不同的網路介面:10.0.0.1 應用於控制和管理流量,192.168.0.1 應用於與服務相關的流量。
$ docker swarm init --advertise-addr 10.0.0.1 --data-path-addr 192.168.0.1
此示例加入由主機 `192.168.99.100:2377` 管理的 Swarm,並將 `--advertise-addr` 標誌設定為 `eth0`,將 `--data-path-addr` 標誌設定為 `eth1`。
$ docker swarm join \
--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2d7c \
--advertise-addr eth0 \
--data-path-addr eth1 \
192.168.99.100:2377
在覆蓋網路上釋出埠
連線到同一覆蓋網路的 Swarm 服務有效地向彼此公開所有埠。要使埠在服務外部可訪問,該埠必須使用 `docker service create` 或 `docker service update` 上的 `-p` 或 `--publish` 標誌進行*釋出*。支援舊的冒號分隔語法和新的逗號分隔值語法。首選較長的語法,因為它在某種程度上是自文件化的。
標誌值 | 描述 |
---|---|
-p 8080:80或 -p published=8080,target=80 | 將服務上的 TCP 埠 80 對映到路由網格上的埠 8080。 |
-p 8080:80/udp或 -p published=8080,target=80,protocol=udp | 將服務上的 UDP 埠 80 對映到路由網格上的埠 8080。 |
-p 8080:80/tcp -p 8080:80/udp或 -p published=8080,target=80,protocol=tcp -p published=8080,target=80,protocol=udp | 將服務上的 TCP 埠 80 對映到路由網格上的 TCP 埠 8080,並將服務上的 UDP 埠 80 對映到路由網格上的 UDP 埠 8080。 |