管理 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"
}
]
}
]
自定义覆盖网络
在某些情况下,您可能不想使用 overlay 网络的默认配置。要查看所有可配置选项的完整列表,请运行命令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
时配置,集群创建后无法更改。
Overlay 网络大小限制
Docker 建议使用/24
块创建 overlay 网络。/24
overlay 网络块将网络限制为 256 个 IP 地址。
此建议解决了swarm 模式的一些限制。如果您需要超过 256 个 IP 地址,请不要增加 IP 块大小。您可以使用带有外部负载均衡器的dnsrr
端点模式,或使用多个较小的 overlay 网络。有关不同端点模式的更多信息,请参见配置服务发现。
配置应用程序数据的加密
与 swarm 相关的管理和控制平面数据始终会被加密。有关加密机制的更多详细信息,请参见Docker swarm 模式 overlay 网络安全模型。
默认情况下,swarm 节点之间的应用程序数据不会加密。要在给定的 overlay 网络上加密此流量,请在docker network create
上使用--opt encrypted
标志。这将在 vxlan 级别启用 IPSEC 加密。此加密会带来不可忽略的性能损失,因此您应在生产环境中使用此选项之前对其进行测试。
注意
您必须自定义自动创建的入口以启用加密。默认情况下,所有入口流量都是未加密的,因为加密是网络级别的选项。
将服务附加到覆盖网络
要将服务附加到现有的 overlay 网络,请将--network
标志传递给docker service create
,或将--network-add
标志传递给docker service update
。
$ docker service create \
--replicas 3 \
--name my-web \
--network my-network \
nginx
连接到 overlay 网络的服务容器可以通过它相互通信。
要查看服务连接到的网络,请使用docker service ls
查找服务的名称,然后使用docker service ps <service-name>
列出网络。或者,要查看连接到网络的服务容器,请使用docker network inspect <network-name>
。您可以从任何已加入 swarm 并处于running
状态的 swarm 节点运行这些命令。
配置服务发现
服务发现是 Docker 用于将请求从服务的外部客户端路由到单个 swarm 节点,而客户端无需知道有多少节点参与服务或它们的 IP 地址或端口的机制。您不需要发布在同一网络上的服务之间使用的端口。例如,如果您有一个将数据存储在 MySQL 服务中的 WordPress 服务,并且它们连接到同一个 overlay 网络,则您不需要将 MySQL 端口发布到客户端,只需要发布 WordPress HTTP 端口。
服务发现可以通过两种不同的方式工作:使用嵌入式 DNS 和虚拟 IP (VIP) 的第 3 层和第 4 层内部基于连接的负载均衡,或使用 DNS 轮询 (DNSRR) 的第 7 层外部和自定义基于请求的负载均衡。您可以为每个服务配置此选项。
默认情况下,当您将服务附加到网络并且该服务发布一个或多个端口时,Docker 会为服务分配一个虚拟 IP (VIP),它是客户端访问服务的“前端”。Docker 会保留服务中所有工作节点的列表,并将请求在客户端和其中一个节点之间路由。来自客户端的每个请求都可能被路由到不同的节点。
如果您将服务配置为使用 DNS 轮询 (DNSRR) 服务发现,则不会只有一个虚拟 IP。相反,Docker 会为服务设置 DNS 条目,以便对服务名的 DNS 查询会返回一个 IP 地址列表,客户端会直接连接到其中一个地址。
DNS 轮询在您想要使用自己的负载均衡器(例如 HAProxy)的情况下非常有用。要将服务配置为使用 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
标志以及您想要设置的自定义选项创建一个新的 overlay 网络。此示例将 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
是一个虚拟桥接器,它将 overlay 网络(包括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。不要加入或初始化集群。
使用自定义设置创建或重新创建
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
初始化或加入集群。
使用单独的接口进行控制和数据流量
默认情况下,所有集群流量都通过相同的接口发送,包括用于维护集群本身的控制和管理流量,以及与服务容器之间的数据流量。
您可以通过在初始化或加入集群时传递--data-path-addr
标志来分离此流量。如果有多个接口,则必须显式指定--advertise-addr
,如果没有指定--data-path-addr
,则默认为--advertise-addr
。有关加入、离开和管理集群的流量通过--advertise-addr
接口发送,服务容器之间的流量通过--data-path-addr
接口发送。这些标志可以采用IP地址或网络设备名称,例如eth0
。
此示例使用单独的--data-path-addr
初始化集群。假设您的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
管理的集群,并将--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
在覆盖网络上发布端口
连接到同一覆盖网络的集群服务有效地将所有端口相互公开。要使端口在服务外部可访问,必须使用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。 |