使用 Swarm 模式路由网格
Docker Engine Swarm 模式可以轻松地为服务发布端口,使其可用于 Swarm 外部的资源。所有节点都参与一个入口路由网格(ingress routing mesh)。路由网格使 Swarm 中的每个节点都能在已发布的端口上接受连接,适用于在 Swarm 中运行的任何服务,即使该节点上没有运行任务。路由网格将所有传入到已发布端口的请求路由到可用节点上的活动容器。
要在 Swarm 中使用入口网络,在启用 Swarm 模式之前,您需要在 Swarm 节点之间开放以下端口:
- 端口
7946TCP/UDP,用于容器网络发现。 - 端口
4789UDP(可配置),用于容器入口网络。
在 Swarm 中设置网络时,应特别注意。请参阅教程以获取概述。
您还必须在 Swarm 节点和任何需要访问该端口的外部资源(例如外部负载均衡器)之间开放已发布的端口。
您还可以为给定服务绕过路由网格。
为服务发布端口
创建服务时,使用 --publish 标志发布端口。target 用于指定容器内部的端口,published 用于指定在路由网格上绑定的端口。如果省略 published 端口,将为每个服务任务绑定一个随机的高位端口。您需要检查任务以确定端口。
$ docker service create \
--name <SERVICE-NAME> \
--publish published=<PUBLISHED-PORT>,target=<CONTAINER-PORT> \
<IMAGE>
注意此语法的旧格式是冒号分隔的字符串,其中发布端口在前,目标端口在后,例如
-p 8080:80。新语法更受青睐,因为它更易于阅读并允许更大的灵活性。
<PUBLISHED-PORT> 是 Swarm 提供服务可用的端口。如果省略它,将绑定一个随机的高位端口。<CONTAINER-PORT> 是容器监听的端口。此参数是必需的。
例如,以下命令将 nginx 容器中的端口 80 发布到 Swarm 中任何节点的 8080 端口:
$ docker service create \
--name my-web \
--publish published=8080,target=80 \
--replicas 2 \
nginx
当您访问任何节点上的 8080 端口时,Docker 会将您的请求路由到一个活动的容器。在 Swarm 节点本身上,8080 端口可能并未实际绑定,但路由网格知道如何路由流量并防止任何端口冲突发生。
路由网格在已发布的端口上侦听分配给该节点的任何 IP 地址。对于外部可路由的 IP 地址,该端口可从主机外部访问。对于所有其他 IP 地址,只能从主机内部访问。

您可以使用以下命令为现有服务发布端口:
$ docker service update \
--publish-add published=<PUBLISHED-PORT>,target=<CONTAINER-PORT> \
<SERVICE>
您可以使用 docker service inspect 查看服务已发布的端口。例如:
$ docker service inspect --format="{{json .Endpoint.Spec.Ports}}" my-web
[{"Protocol":"tcp","TargetPort":80,"PublishedPort":8080}]
输出显示了容器的 <CONTAINER-PORT>(标记为 TargetPort)和节点为服务请求监听的 <PUBLISHED-PORT>(标记为 PublishedPort)。
仅为 TCP 或 UDP 发布端口
默认情况下,当您发布一个端口时,它是一个 TCP 端口。您可以专门发布一个 UDP 端口,而不是或除了 TCP 端口之外。当您同时发布 TCP 和 UDP 端口时,如果省略协议说明符,该端口将被发布为 TCP 端口。如果您使用较长的语法(推荐),请将 protocol 键设置为 tcp 或 udp。
仅 TCP
长语法
$ docker service create --name dns-cache \
--publish published=53,target=53 \
dns-cache
短语法
$ docker service create --name dns-cache \
-p 53:53 \
dns-cache
TCP 和 UDP
长语法
$ docker service create --name dns-cache \
--publish published=53,target=53 \
--publish published=53,target=53,protocol=udp \
dns-cache
短语法
$ docker service create --name dns-cache \
-p 53:53 \
-p 53:53/udp \
dns-cache
仅 UDP
长语法
$ docker service create --name dns-cache \
--publish published=53,target=53,protocol=udp \
dns-cache
短语法
$ docker service create --name dns-cache \
-p 53:53/udp \
dns-cache
绕过路由网格
默认情况下,发布端口的 Swarm 服务通过路由网格进行。当您连接到任何 Swarm 节点上的已发布端口(无论它是否正在运行某个服务)时,您将被透明地重定向到正在运行该服务的工作节点。实际上,Docker 充当了您 Swarm 服务的负载均衡器。
您可以绕过路由网格,这样当您访问给定节点上的绑定端口时,您总是访问在该节点上运行的服务实例。这被称为 host 模式。有几点需要注意。
如果您访问的节点没有运行服务任务,则该服务不会在该端口上监听。可能什么都没有在监听,或者一个完全不同的应用程序正在监听。
如果您希望在每个节点上运行多个服务任务(例如,您有 5 个节点但运行 10 个副本),您不能指定静态目标端口。要么允许 Docker 分配一个随机的高位端口(通过省略
published),要么通过使用全局服务而不是复制服务,或使用放置约束来确保在给定节点上只运行服务的单个实例。
要绕过路由网格,您必须使用长的 --publish 服务并将 mode 设置为 host。如果省略 mode 键或将其设置为 ingress,则将使用路由网格。以下命令使用 host 模式创建一个全局服务并绕过路由网格。
$ docker service create --name dns-cache \
--publish published=53,target=53,protocol=udp,mode=host \
--mode global \
dns-cache
配置外部负载均衡器
您可以为 Swarm 服务配置外部负载均衡器,可以与路由网格结合使用,也可以完全不使用路由网格。
使用路由网格
您可以配置外部负载均衡器将请求路由到 Swarm 服务。例如,您可以配置 HAProxy 来平衡发布到 8080 端口的 nginx 服务的请求。

在这种情况下,负载均衡器和 Swarm 中的节点之间必须开放 8080 端口。Swarm 节点可以驻留在一个代理服务器可以访问但非公开访问的私有网络中。
您可以配置负载均衡器在 Swarm 中的每个节点之间平衡请求,即使该节点上没有任务调度。例如,您可以在 /etc/haproxy/haproxy.cfg 中有以下 HAProxy 配置:
global
log /dev/log local0
log /dev/log local1 notice
...snip...
# Configure HAProxy to listen on port 80
frontend http_front
bind *:80
stats uri /haproxy?stats
default_backend http_back
# Configure HAProxy to route requests to swarm nodes on port 8080
backend http_back
balance roundrobin
server node1 192.168.99.100:8080 check
server node2 192.168.99.101:8080 check
server node3 192.168.99.102:8080 check当您在 80 端口访问 HAProxy 负载均衡器时,它会将请求转发到 Swarm 中的节点。Swarm 路由网格会将请求路由到活动任务。如果由于任何原因,Swarm 调度程序将任务分派到不同的节点,您不需要重新配置负载均衡器。
您可以配置任何类型的负载均衡器来将请求路由到 Swarm 节点。要了解更多关于 HAProxy 的信息,请参阅 HAProxy 文档。
不使用路由网格
要在不使用路由网格的情况下使用外部负载均衡器,请将 --endpoint-mode 设置为 dnsrr,而不是默认值 vip。在这种情况下,没有单一的虚拟 IP。相反,Docker 会为服务设置 DNS 条目,以便对服务名称的 DNS 查询返回 IP 地址列表,客户端直接连接到其中一个。
您不能将 --endpoint-mode dnsrr 与 --publish mode=ingress 一起使用。您必须在服务前面运行自己的负载均衡器。在 Docker 主机上对服务名称进行 DNS 查询会返回运行该服务的节点的 IP 地址列表。配置您的负载均衡器以使用此列表并在这些节点之间平衡流量。请参阅配置服务发现。