管理 Swarm 服务网络

本页面描述了 Swarm 服务的网络。

Swarm 和流量类型

Docker swarm 生成两种不同类型的流量:

  • 控制和管理平面流量:这包括 swarm 管理消息,例如加入或离开 swarm 的请求。此流量始终是加密的。

  • 应用数据平面流量:这包括容器流量以及与外部客户端之间的流量。

关键网络概念

以下三个网络概念对于 Swarm 服务很重要:

  • Overlay 网络管理参与 swarm 的 Docker 守护进程之间的通信。您可以创建 overlay 网络,就像为 standalone 容器创建用户定义网络一样。您还可以将服务附加到一个或多个现有 overlay 网络,以启用服务到服务之间的通信。Overlay 网络是使用 overlay 网络驱动的 Docker 网络。

  • Ingress 网络是一种特殊的 overlay 网络,用于促进服务节点之间的负载均衡。当任何 swarm 节点接收到已发布端口上的请求时,它会将该请求交给一个名为 IPVS 的模块。IPVS 会跟踪参与该服务的所有 IP 地址,选择其中一个,并通过 ingress 网络将请求路由到该地址。

    ingress 网络在您初始化或加入 swarm 时自动创建。大多数用户无需自定义其配置,但 Docker 允许您这样做。

  • docker_gwbridge 是一个桥接网络,它将 overlay 网络(包括 ingress 网络)连接到单个 Docker 守护进程的物理网络。默认情况下,服务运行的每个容器都连接到其本地 Docker 守护进程主机的 docker_gwbridge 网络。

    docker_gwbridge 网络在您初始化或加入 swarm 时自动创建。大多数用户无需自定义其配置,但 Docker 允许您这样做。

提示

另请参阅网络概览,了解更多关于 Swarm 网络的通用详细信息。

防火墙注意事项

参与 swarm 的 Docker 守护进程需要能够通过以下端口相互通信:

  • 端口 7946 TCP/UDP 用于容器网络发现。
  • 端口 4789 UDP(可配置)用于 overlay 网络(包括 ingress)数据路径。

在 Swarm 中设置网络时,应特别小心。请查阅教程获取概览。

Overlay 网络

当您初始化一个 swarm 或将 Docker 主机加入现有 swarm 时,该 Docker 主机上会创建两个新的网络:

  • 一个名为 ingress 的 overlay 网络,用于处理与 swarm 服务相关的控制和数据流量。当您创建 swarm 服务且未将其连接到用户定义的 overlay 网络时,它默认连接到 ingress 网络。
  • 一个名为 docker_gwbridge 的 bridge 网络,用于连接单个 Docker 守护进程与参与 swarm 的其他守护进程。

创建 overlay 网络

要创建 overlay 网络,请在使用 docker network create 命令时指定 overlay 驱动:

$ docker network create \
  --driver overlay \
  my-network

上面的命令没有指定任何自定义选项,因此 Docker 会分配一个子网并使用默认选项。您可以使用 docker network inspect 查看网络信息。

当没有容器连接到 overlay 网络时,其配置并不是很有趣:

$ 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 网络中可能看到的 localhostglobal 范围。此范围表示只有参与 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 网络

在某些情况下,您可能不希望使用 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 加密。此加密会带来不可忽视的性能损失,因此您应在使用前进行测试。

注意

您必须自定义自动创建的 ingress 网络以启用加密。默认情况下,所有 ingress 流量都未加密,因为加密是网络级别选项。

将服务附加到 overlay 网络

要将服务附加到现有 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 循环 (DNSRR) 在您希望使用自己的负载均衡器(例如 HAProxy)的情况下非常有用。要将服务配置为使用 DNSRR,请在创建新服务或更新现有服务时使用 --endpoint-mode dnsrr 标志。

自定义 ingress 网络

大多数用户从不需要配置 ingress 网络,但 Docker 允许您这样做。如果自动选择的子网与您的网络上已有的子网冲突,或者您需要自定义其他底层网络设置(例如 MTU),或者如果您想启用加密,这将非常有用。

自定义 ingress 网络涉及删除并重新创建它。这通常在您创建 swarm 中的任何服务之前完成。如果您有发布端口的现有服务,则需要先删除这些服务才能删除 ingress 网络。

在没有 ingress 网络存在的期间,不发布端口的现有服务会继续运行,但不会进行负载均衡。这会影响发布端口的服务,例如发布端口 80 的 WordPress 服务。

  1. 使用 docker network inspect ingress 检查 ingress 网络,并删除连接到它的所有服务容器。这些是发布端口的服务,例如发布端口 80 的 WordPress 服务。如果所有此类服务都没有停止,下一步将失败。

  2. 删除现有的 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]
    
  3. 使用 --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 之外的其他名称,但只能有一个。创建第二个 ingress 网络的尝试将失败。

  4. 重新启动您在第一步中停止的服务。

自定义 docker_gwbridge

docker_gwbridge 是一个虚拟网桥,用于将 overlay 网络(包括 ingress 网络)连接到单个 Docker 守护进程的物理网络。Docker 在您初始化 swarm 或将 Docker 主机加入 swarm 时自动创建它,但它不是 Docker 设备。它存在于 Docker 主机的内核中。如果您需要自定义其设置,则必须在将 Docker 主机加入 swarm 之前或暂时将主机从 swarm 中移除之后进行。

您需要在操作系统上安装 brctl 应用程序才能删除现有网桥。软件包名称为 bridge-utils

  1. 停止 Docker。

  2. 使用 brctl show docker_gwbridge 命令检查是否存在名为 docker_gwbridge 的网桥设备。如果存在,则使用 brctl delbr docker_gwbridge 将其删除。

  3. 启动 Docker。不要加入或初始化 swarm。

  4. 使用自定义设置创建或重新创建 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
    
  5. 初始化或加入 Swarm。

为控制和数据流量使用独立接口

默认情况下,所有 Swarm 流量都通过同一接口发送,包括用于维护 Swarm 本身的控制和管理流量以及进出服务容器的数据流量。

您可以在初始化或加入 Swarm 时通过传递 --data-path-addr 标志来分离此流量。如果有多个接口,则必须显式指定 --advertise-addr,如果未指定 --data-path-addr,则其默认值为 --advertise-addr。关于加入、离开和管理 Swarm 的流量通过 --advertise-addr 接口发送,而服务容器之间的流量通过 --data-path-addr 接口发送。这些标志可以采用 IP 地址或网络设备名称,例如 eth0

此示例初始化一个带有单独的 --data-path-addr 的 Swarm。它假定您的 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 管理的 Swarm,并将 --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

在 overlay 网络上发布端口

连接到同一 Overlay 网络的服务容器实际上相互暴露所有端口。要使某个端口可以从服务外部访问,必须使用 docker service createdocker 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。

了解更多

页面选项