overlay 网络驱动在多个 Docker 守护进程主机之间创建分布式网络。它叠加在各主机自身的网络之上,启用加密后,连接到该网络的容器可以安全通信。Docker 透明地处理每个数据包的路由,将其发送到正确的 Docker 守护进程主机和目标容器,或从这些位置接收数据包。
你可以使用 docker network create 创建用户自定义的 overlay 网络,方式与创建用户自定义的 bridge 网络相同。服务或容器可以同时连接多个网络。服务或容器只能通过双方都连接的网络通信。
Overlay 网络常用于连接 Swarm 服务,也可以连接运行在不同主机上的独立容器。使用独立容器时,仍然必须启用 Swarm 模式来建立主机间的连接。
本页介绍 overlay 网络的一般概念及其与独立容器配合使用的方式。有关 Swarm 服务的 overlay 网络,请参阅“管理 Swarm 服务网络”。 [1]
要求 [2]
要使用 overlay 网络,Docker 主机必须加入同一个 swarm,即使连接的是独立容器也一样。参与通信的主机之间必须开放下列端口:
| 端口 | 说明 |
|---|---|
| 2377/tcp | 默认的 Swarm 控制平面端口,可通过 docker swarm join –listen-addr 配置。 [3] |
| 4789/udp | 默认的 overlay 流量端口,可通过 docker swarm init –data-path-port 配置。 [4] |
| 7946/tcp、7946/udp | 用于节点间通信,不能配置。 |
创建 overlay 网络 [5]
要创建一个允许其他 Docker 主机上的容器连接的 overlay 网络,请运行以下命令:
$ docker network create -d overlay --attachable my-attachable-overlay
–attachable 选项允许独立容器和 Swarm 服务连接 overlay 网络。不使用 –attachable 时,只有 Swarm 服务可以连接该网络。
你可以指定 IP 地址范围、子网、网关等选项。详情请参阅 docker network create –help。
加密 overlay 网络中的流量 [6]
使用 –opt encrypted 标志来加密通过 overlay 网络传输的应用数据:
$ docker network create \
--opt encrypted \
--driver overlay \
--attachable \
my-attachable-multi-host-network
这会在虚拟可扩展局域网(VXLAN)层启用 IPsec 加密。加密带来的性能开销不可忽略,因此应先测试这一选项,再用于生产环境。
警告不要将 Windows 容器连接到加密的 overlay 网络。
Windows 不支持 overlay 网络加密。Windows 主机尝试连接加密的 overlay 网络时,Swarm 不会报告错误,但 Windows 容器的网络会受到以下影响:
- Windows 容器无法与该网络中的 Linux 容器通信。
- 该网络中 Windows 容器之间的数据流量不会被加密。
将容器连接到 overlay 网络 [7]
把容器加入 overlay 网络后,它们可以与其他容器通信,而不必在每台 Docker 守护进程主机上单独配置路由。前提是这些主机已经加入同一个 Swarm。
要使用 busybox 容器加入名为 multi-host-network 的 overlay 网络:
$ docker run --network multi-host-network busybox sh
说明这只适用于可附加的 overlay 网络,即创建时使用了 –attachable 标志的网络。
容器发现 [8]
发布 overlay 网络中容器的端口,会向同一网络中的其他容器开放这些端口。通过使用容器名称进行 DNS 查询,可以发现容器。
| 标志值 | 说明 |
|---|---|
| -p 8080:80 | 将容器中的 TCP 端口 80 映射到 overlay 网络中的端口 8080。 |
| -p 8080:80/udp | 将容器中的 UDP 端口 80 映射到 overlay 网络中的端口 8080。 |
| -p 8080:80/sctp | 将容器中的 SCTP 端口 80 映射到 overlay 网络中的端口 8080。 |
| -p 8080:80/tcp -p 8080:80/udp | 将容器中的 TCP 端口 80 映射到 overlay 网络中的 TCP 端口 8080,并将容器中的 UDP 端口 80 映射到 overlay 网络中的 UDP 端口 8080。 |
Overlay 网络的连接数量限制 [9]
受 Linux 内核的限制,当 1000 个容器集中运行在同一主机上时,overlay 网络会变得不稳定,容器间通信可能中断。
有关这一限制的更多信息,请参阅 moby/moby#44973。 [10]
使用示例 [11]
本节提供使用 overlay 网络的实践示例,涵盖多个 Docker 主机上的 swarm 服务和独立容器。
前提条件 [12]
所有示例至少需要一个单节点 swarm。在主机上运行 docker swarm init 即可初始化。也可以在多节点 swarm 中运行这些示例。
使用默认 overlay 网络 [13]
本示例说明默认 overlay 网络如何与 swarm 服务协作。你将创建一个 nginx 服务,并从服务容器的角度查看网络。
多节点设置的前提条件 [14]
本教程需要三台 Docker 主机,它们位于同一网络且可以互相通信,主机间流量不被防火墙阻挡:
- manager:同时充当管理节点和工作节点。
- worker-1:仅充当工作节点。
- worker-2:仅充当工作节点。
如果没有三台可用主机,可以在云服务商上创建三台虚拟机并安装 Docker。
创建 swarm [15]
-
在 manager 上初始化 swarm。如果主机只有一个网络接口,–advertise-addr 标志可以省略:
$ docker swarm init --advertise-addr=<IP-ADDRESS-OF-MANAGER>保存显示的加入令牌,以便工作节点使用。
-
在 worker-1 上加入 swarm:
$ docker swarm join --token <TOKEN> \ --advertise-addr <IP-ADDRESS-OF-WORKER-1> \ <IP-ADDRESS-OF-MANAGER>:2377 -
在 worker-2 上加入 swarm:
$ 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如有需要,可按角色筛选:
$ docker node ls --filter role=manager $ docker node ls --filter role=worker -
在所有主机上列出 Docker 网络。现在每台主机都有一个名为 ingress 的 overlay 网络和一个名为 docker_gwbridge 的 bridge 网络:
$ 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 主机的网络接口。创建服务时如果不指定网络,服务会连接 ingress。建议为每个应用或一组相关应用使用独立的 overlay 网络。
创建服务 [16]
-
在 manager 上创建一个新的 overlay 网络:
$ docker network create -d overlay nginx-net当工作节点运行需要该网络的服务任务时,overlay 网络会自动在工作节点上创建。
-
在 manager 上创建一个具有 5 个副本、连接到 nginx-net 的 Nginx 服务:
说明只能在管理节点上创建服务。
$ docker service create \ --name my-nginx \ --publish target=80,published=80 \ --replicas=5 \ --network nginx-net \ nginx默认的 ingress 发布模式意味着,你可以访问任意节点的端口 80,并连接到 5 个服务任务中的某一个,即使该节点上没有运行任何任务。
-
观察服务创建进度:
$ docker service ls -
在所有主机上检查 nginx-net 网络。Containers 部分列出了该主机上连接到 overlay 网络的所有服务任务。
-
在 manager 上检查服务:
$ docker service inspect my-nginx留意端口和端点信息。
-
创建第二个网络,并更新服务以使用该网络:
$ 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检查两个网络,确认容器已经从 nginx-net 迁移到 nginx-net-2。
说明Overlay 网络会按需在 swarm 工作节点上自动创建,但不会自动删除。
-
清理:
$ docker service rm my-nginx $ docker network rm nginx-net nginx-net-2
使用用户自定义的 overlay 网络 [17]
本示例展示生产服务使用自定义 overlay 网络的推荐方式。
前提条件 [18]
假设 swarm 已经设置完成,且你正在管理节点上操作。
步骤 [19]
-
创建用户自定义的 overlay 网络:
$ docker network create -d overlay my-overlay -
启动一个使用该 overlay 网络的服务,将端口 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
为独立容器使用 overlay 网络 [20]
本示例演示不同 Docker 主机上的独立容器如何通过 overlay 网络使用 DNS 发现彼此。
前提条件 [21]
需要两台可以互相通信的 Docker 主机,并在它们之间开放以下端口:
- TCP 端口 2377。
- TCP 和 UDP 端口 7946。
- UDP 端口 4789。
本示例将这两台主机称为 host1 和 host2。
步骤 [22]
-
设置 swarm:
在 host1 上初始化 swarm:
$ 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在 host2 上使用上一步输出中的令牌加入 swarm:
$ docker swarm join --token <your_token> <your_ip_address>:2377 This node joined a swarm as a worker.如果加入失败,在 host2 上运行 docker swarm leave –force,检查网络和防火墙设置后重试。
-
在 host1 上创建一个可附加的 overlay 网络:
$ docker network create --driver=overlay --attachable test-net uqsof8phj3ak0rq9k86zta6ht记下返回的网络 ID。
-
在 host1 上启动连接 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 上启动一个在后台运行、连接 test-net 的交互式容器:
$ docker run -dit --name alpine2 --network test-net alpine fb635f5ece59563e7b8b99556f816d24e6949a5f6a5b1fbd92ca244db17a4342
说明自动 DNS 容器发现只适用于具有唯一名称的容器。
-
在 host2 上确认 test-net 已创建,且其网络 ID 与 host1 上的相同:
$ docker network ls NETWORK ID NAME DRIVER SCOPE ... uqsof8phj3ak test-net overlay swarm -
在 host1 上,从 alpine1 容器内 ping alpine2:
/ # 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两个容器通过连接两台主机的 overlay 网络通信。你也可以在 host2 上运行另一个容器并 ping alpine1:
$ docker run -it --rm --name alpine3 --network test-net alpine / # ping -c 2 alpine1 / # exit -
在 host1 上退出 alpine1 会话,这会停止容器:
/ # exit -
清理。必须在每台主机上分别停止并删除容器:
在 host2 上:
$ docker container stop alpine2 $ docker network ls $ docker container rm alpine2停止 alpine2 时,test-net 会从 host2 上消失。
在 host1 上:
$ docker container rm alpine1 $ docker network rm test-net











暂无评论内容