使用Swarm模式路由网格
Docker Engine Swarm 模式使您可以轻松地为服务发布端口,以便它们可供集群外部的资源使用。所有节点都参与入口路由网格。路由网格使集群中的每个节点都可以接受集群中运行的任何服务的已发布端口上的连接,即使节点上没有运行任务也是如此。路由网格将所有传入的已发布端口请求路由到可用节点上的活动容器。
要在集群中使用入口网络,您需要在启用 Swarm 模式之前打开集群节点之间的以下端口
- 端口 `7946` TCP/UDP 用于容器网络发现。
- 端口 `4789` UDP(可配置)用于容器入口网络。
在 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节点上发布的端口(无论它是否正在运行给定的服务)时,您都会被透明地重定向到正在运行该服务的Worker。实际上,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地址列表。配置您的负载均衡器以使用此列表并在节点之间平衡流量。请参见配置服务发现。