使用Swarm模式路由网格
Docker Engine Swarm 模式使得为服务发布端口变得容易,以便使它们对 Swarm 外部的资源可用。所有节点都参与入口路由网格。路由网格使得 Swarm 中的每个节点都能接受在 Swarm 中运行的任何服务的已发布端口上的连接,即使该节点上没有运行任务。路由网格将所有传入请求路由到可用节点上的已发布端口,并将其转发到活动的容器。
要在群集中使用入口网络,您需要在启用群集模式之前在群集节点之间打开以下端口:
- 端口
7946TCP/UDP 用于容器网络发现。 - 端口
4789UDP(可配置)用于容器入口网络。
在设置Swarm网络时,应特别注意。请参阅 教程 以获取概述。
您还必须在群集节点和任何需要访问该端口的外部资源(例如外部负载均衡器)之间打开已发布的端口。
你也可以为给定的服务 绕过路由网格。
为服务发布端口
使用--publish标志在创建服务时发布端口。target用于指定容器内的端口,published用于指定要绑定到路由网格的端口。如果省略published端口,则会为每个服务任务绑定一个随机的高编号端口。您需要检查任务以确定端口。
$ docker service create \
--name <SERVICE-NAME> \
--publish published=<PUBLISHED-PORT>,target=<CONTAINER-PORT> \
<IMAGE>
注意
这种语法的旧形式是一个冒号分隔的字符串,其中 发布的端口在前,目标端口在后,例如
-p 8080:80。新语法更受欢迎,因为它更易于阅读且 提供了更多的灵活性。
是群集使服务可用的端口。
如果省略它,则会绑定一个随机的高编号端口。
是容器监听的端口。此参数
是必需的。
例如,以下命令将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}]
输出显示了来自容器的(标记为TargetPort)和节点监听服务请求的(标记为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
绕过路由网格
默认情况下,发布端口的群集服务使用路由网格进行发布。 当你连接到任何群集节点上的发布端口时(无论它是否正在运行给定的服务),你都会被透明地重定向到运行该服务的工作节点。 实际上,Docker 充当了你的群集服务的负载均衡器。
您可以绕过路由网格,这样当您访问给定节点上的绑定端口时,您总是访问在该节点上运行的服务实例。这被称为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服务。例如,你可以配置HAProxy来平衡发布到8080端口的nginx服务的请求。

在这种情况下,负载均衡器和群集节点之间的8080端口必须开放。群集节点可以位于代理服务器可访问的私有网络上,但该网络不对外公开访问。
你可以配置负载均衡器在群集中的每个节点之间平衡请求,即使该节点上没有安排任务。例如,你可以在/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节点。 要了解更多关于HAProxy的信息,请参阅 HAProxy文档。
没有路由网格
要在不使用路由网格的情况下使用外部负载均衡器,请将--endpoint-mode设置为dnsrr,而不是默认的vip。在这种情况下,没有单一的虚拟IP。相反,Docker为服务设置了DNS条目,使得对服务名称的DNS查询返回一个IP地址列表,客户端直接连接到其中一个。
你不能同时使用--endpoint-mode dnsrr和--publish mode=ingress。
你必须在服务前面运行自己的负载均衡器。在Docker主机上对服务名称进行DNS查询时,会返回运行该服务的节点的IP地址列表。配置你的负载均衡器以使用此列表并在节点之间平衡流量。
参见
配置服务发现。