使用覆盖网络

预计阅读时间:11分钟

overlay网络驱动程序会创建多个码头工人守护主机之间的分布式网络。该网络位于特定于主机的网络之上((覆盖)特定主机的网络),从而在启用加密后允许与其连接的容器(包括群集服务容器)进行安全通信。Docker透明地处理每个数据包与正确的Docker守护程序主机和正确的目标容器之间的路由。

初始化群集或将Docker主机加入现有群集时,将在该Docker主机上创建两个新网络:

  • 一个称为的覆盖网络ingress,用于处理与群体服务相关的控制和数据流量。创建群集服务并且不将其连接到用户定义的覆盖网络时,ingress 默认情况下它将连接到网络。
  • 一个名为的桥接网络docker_gwbridge,它将各个Docker守护程序连接到该集群中的其他守护程序。

您可以overlay使用来创建用户定义的网络docker network create,就像创建用户定义的bridge网络一样。服务或容器可以一次连接到多个网络。服务或容器只能在它们各自连接的网络之间进行通信。

尽管您可以将群集服务和独立容器都连接到覆盖网络,但是默认行为和配置问题有所不同。因此,本主题的其余部分分为适用于所有覆盖网络的操作,适用于群集服务网络的操作以及适用于独立容器使用的覆盖网络的操作。

所有覆盖网络的操作

创建覆盖网络

先决条件

  • 使用覆盖网络的Docker守护程序的防火墙规则

    您需要打开以下端口,以往返于参与覆盖网络的每个Docker主机的流量:

    • 用于群集管理通信的TCP端口2377
    • TCP和UDP端口7946,用于节点之间的通信
    • UDP端口4789,用于覆盖网络流量
  • 在创建覆盖网络之前,您需要使用初始化Docker守护进程为swarm管理器,docker swarm init或者使用将该Docker守护进程加入现有的swarm docker swarm join。这两个都将创建默认的ingress覆盖网络,默认情况下,群集服务会使用该 覆盖网络。即使您从未计划使用群体服务,也需要这样做。之后,您可以创建其他用户定义的覆盖网络。

要创建用于群服务的覆盖网络,请使用如下命令:

$ docker network create -d overlay my-overlay

要创建覆盖网络,群集服务 独立容器可以使用该覆盖网络来与在其他Docker守护程序上运行的其他独立容器进行通信,请添加以下--attachable标志:

$ docker network create -d overlay --attachable my-attachable-overlay

您可以指定IP地址范围,子网,网关和其他选项。有关docker network create --help详细信息,请参见 。

加密覆盖网络上的流量

默认情况下,在GCM模式下使用AES算法对所有群集服务管理流量进行加密 。群中的管理器节点每12小时旋转一次用于加密八卦数据的密钥。

要同时加密应用程序数据,请--opt encrypted在创建覆盖网络时添加。这样可以在vxlan级别启用IPSEC加密。这种加密对性能的影响是不可忽略的,因此在生产中使用此选项之前,应先对其进行测试。

启用覆盖加密后,Docker会在计划为覆盖网络上的服务计划任务的所有节点之间创建IPSEC隧道。这些隧道还在GCM模式下使用AES算法,并且管理器节点每12小时自动旋转一次密钥。

不要将Windows节点附加到加密的覆盖网络。

Windows不支持覆盖网络加密。如果Windows节点尝试连接到加密的覆盖网络,则不会检测到任何错误,但是该节点无法通信。

群集模式覆盖网络和独立容器

您可以同时使用覆盖网络功能,--opt encrypted --attachable 并将不受管的容器附加到该网络:

$ docker network create --opt encrypted --driver overlay --attachable my-attachable-multi-host-network

自定义默认入口网络

大多数用户从不需要配置ingress网络,但是Docker允许您这样做。如果自动选择的子网与网络上已经存在的子网冲突,或者您需要自定义其他低级网络设置(例如MTU),这将很有用。

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

在没有ingress网络的时间内,未发布端口的现有服务将继续运行,但负载不平衡。这会影响发布端口的服务,例如发布端口80的WordPress服务。

  1. 使用检查ingress网络docker network inspect 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标志以及要设置的自定义选项创建一个新的覆盖网络。本示例将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,但只能使用一个。尝试创建第二个失败。

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

自定义docker_gwbridge接口

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

  1. 停止Docker。

  2. 删除现有docker_gwbridge接口。

    $ sudo ip link set docker_gwbridge down
    
    $ sudo ip link del dev docker_gwbridge
    
  3. 启动Docker。不要加入或初始化群体。

  4. docker_gwbridge使用docker network create命令使用自定义设置手动创建或重新创建网桥。本示例使用子网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. 初始化或加入群。由于该桥接器已经存在,因此Docker不会使用自动设置来创建它。

群服务的操作

在覆盖网络上发布端口

连接到同一覆盖网络的群集服务有效地将所有端口彼此公开。对于一个端口是服务的访问之外,该端口必须公布使用-p--publish标志上docker service createdocker service update。支持旧的冒号分隔的语法和较新的逗号分隔的值语法。首选较长的语法,因为它有些自我记录。

标志值 描述
-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。

绕过路由网格以实现群集服务

默认情况下,发布端口的群集服务会使用路由网格进行发布。当您连接到任何群集节点上的已发布端口时(无论它是否正在运行给定服务),您都将透明地重定向到正在运行该服务的工作程序。实际上,Docker充当了集群服务的负载平衡器。使用路由网格的服务以虚拟IP(VIP)模式运行。甚至在每个节点上运行的服务(通过--mode global 标志)也使用路由网格。使用路由网格时,无法保证客户端请求哪些Docker节点服务。

要绕过路由网格,可以通过将标志设置为来使用DNS循环(DNSRR)模式启动服务。您必须在服务之前运行自己的负载平衡器。在Docker主机上对服务名称进行DNS查询会返回运行该服务的节点的IP地址列表。配置您的负载均衡器以使用此列表并平衡节点之间的流量。--endpoint-modednsrr

分开的控制和数据流量

默认情况下,尽管群集控制通信已加密,但与群集管理和进出您的应用程序的通信有关的控制通信在同一网络上运行。您可以将Docker配置为使用单独的网络接口来处理两种不同类型的流量。初始化或加入群集时,请分别指定--advertise-addr--datapath-addr。您必须对加入群集的每个节点执行此操作。

覆盖网络上独立容器的操作

将独立容器连接到覆盖网络

ingress网络没有建立--attachable标志,这意味着只有群服务可以使用它,而不是独立的容器。您可以将独立容器连接到使用该--attachable标志创建的用户定义的覆盖网络。这使运行在不同Docker守护程序上的独立容器能够进行通信,而无需在各个Docker守护程序主机上设置路由。

发布端口

标志值 描述
-p 8080:80 将容器中的TCP端口80映射到覆盖网络上的端口8080。
-p 8080:80/udp 将容器中的UDP端口80映射到覆盖网络上的端口8080。
-p 8080:80/sctp 将容器中的SCTP端口80映射到覆盖网络上的端口8080。
-p 8080:80/tcp -p 8080:80/udp 将容器中的TCP端口80映射到覆盖网络上的TCP端口8080,并将容器中的UDP端口80映射到覆盖网络上的UDP端口8080。

容器发现

在大多数情况下,您应该连接到服务名称,该名称是负载均衡的,并由支持该服务的所有容器(“任务”)处理。要获取支持该服务的所有任务的列表,请对DNS执行查找tasks.<service-name>.

下一步

网络覆盖用户定义服务