Docker网络-overlay网络驱动架构

内置的Docker覆盖网络驱动程序从根本上简化了多主机网络中的许多挑战。借助叠加驱动程序,多主机网络是Docker内部的一等公民,而无需外部配置或组件。 overlay使用Swarm分布式控制平面在超大型集群中提供集中管理,稳定性和安全性。

VXLAN数据平面

覆盖驱动程序利用行业标准的VXLAN数据平面,该数据平面将容器网络与基础物理网络(底层)分离。 Docker覆盖网络将容器流量封装在VXLAN标头中,该流量允许流量穿越物理第2层或第3层网络。无论基础物理拓扑如何,覆盖层都使网络分段变得动态且易于控制。使用标准的IETF VXLAN标头可以促进使用标准工具来检查和分析网络流量。

VXLAN(Virtual eXtensible Local Area Network)是一种隧道技术,能在三层网络的基础上建立二层以太网网络隧道,从而实现跨地域的二层互连。VXLAN采取了将原始以太网报文封装在UDP数据包里的封装格式。原来的二数据加上VXLAN头部一起封装一个UDP数据包里。VXLAN部包含有一个VXLAN标识(即VNI,VXLAN Network Identifier),只有在同一个VXLAN的虚拟机之间才能相互通信VNI在数据包之中占24比特,故可支持1600万个VXLAN的同时存在,远多VLAN的4094个,因此可大规模主机的部署

自3.7版以来,VXLAN便已成为Linux内核的一部分,而Docker使用该内核的本机VXLAN功能来创建覆盖网络。 Docker覆盖数据路径完全位于内核空间中。这导致更少的上下文切换,更少的CPU开销以及应用程序和物理NIC之间的低延迟,直接流量路径。

 

 

 

在此图中,我们看到了覆盖网络上的数据包流。当c1通过其共享覆盖网络发送c2数据包时,将执行以下步骤:

  1. c1为c2执行DNS查找。由于两个容器都在同一覆盖网络上,因此Docker Engine本地DNS服务器将c2解析为其overlay网络的IP地址10.0.0.3。
  2. 覆盖网络(overlay)是一个L2网段,因此c1会生成一个以c2的MAC地址为目的地的L2帧。
  3. 覆盖网络驱动程序使用VXLAN标头封装了该帧。分布式覆盖控制平面管理每个VXLAN隧道端点的位置和状态,因此它知道c2驻留在主机B上的物理地址192.168.1.3。该地址成为底层IP标头的目标地址。
  4. 封装后,将发送数据包。物理网络负责将VXLAN数据包路由或桥接到正确的主机。
  5. 数据包到达主机B的eth0接口,并由覆盖网络驱动程序解封装。来自c1的原始L2帧传递到c2的eth0接口,然后传递到监听应用程序。

 内部体系结构

Docker Swarm控制平面可自动执行覆盖网络的所有配置。 不需要VXLAN配置或Linux网络配置。 数据平面加密(覆盖层的可选功能)在创建网络时也由覆盖层驱动程序自动配置。 用户或网络运营商只需定义网络(docker network create -d overlay ...)并将容器连接到该网络。

 

在创建覆盖网络时,Docker Engine创建每个主机上覆盖所需的网络基础结构。 将为每个覆盖网络及其关联的VXLAN接口创建一个Linux网桥。 仅当有容器连接到该网络时,Docker引擎才会实例化主机上的覆盖网络。 这样可以防止不存在连接的覆盖网络蔓延。

在下面的示例中,我们创建一个覆盖网络并将容器连接到该网络。 然后,我们将看到Docker Swarm / UCP自动创建了覆盖网络。

#Create an overlay named "ovnet" with the overlay driver
$ docker network create -d overlay ovnet


#Create a service from an nginx image and connect it to the "ovnet" overlay network
$ docker service create --network ovnet --name container nginx

创建覆盖网络后,在主机内部创建了多个接口和网桥。eth1是桥接网络,eth2是overlay网络

# Run the "ifconfig" command inside the nginx container
$ docker exec -it container ifconfig


#docker_gwbridge network
eth1      Link encap:Ethernet  HWaddr 02:42:AC:12:00:04
          inet addr:172.18.0.4  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe12:4/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1


#overlay network
eth2      Link encap:Ethernet  HWaddr 02:42:0A:00:00:07
          inet addr:10.0.0.7  Bcast:0.0.0.0  Mask:255.255.255.0
          inet6 addr: fe80::42:aff:fe00:7/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
     
#container loopback
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:

 

已在容器内创建了两个接口eth0,eth1,它们对应于主机上存在的eth2 overlay和eth1 docker_gwbridge。 在覆盖网络(overlay)上,每个容器将至少有两个接口将其连接到overlay和docker_gwbridge

集群网络概念

Overlay networks

管理 Swarm 中 Docker 守护进程间的通信。你可以将服务附加到一个或多个已存在的 overlay 网络上,使得服务与服务之间能够通信。

ingress network

是一个特殊的 overlay 网络,用于服务节点间的负载均衡。它将覆盖范围扩展到参与此特定覆盖范围的所有主机,也就说所有的swarm集群共享一个overlay网络。

当任何 Swarm 节点在发布的端口上接收到请求时,它将该请求交给一个名为 IPVS 的模块。IPVS 跟踪参与该服务的所有IP地址,选择其中的一个,并通过 ingress 网络将请求路由到它。
初始化或加入 Swarm 集群时会自动创建 ingress 网络,大多数情况下,用户不需要自定义配置,但是 docker 17.05 和更高版本允许你自定义。

docker_gwbridge

是一种桥接网络,群集流量的出口网桥。 每个主机仅存在一个docker_gwbridge。 容器到容器的通信在此网桥上被阻止,仅允许ingress/egress 通信流。将 overlay 网络(包括 ingress 网络)连接到一个单独的 Docker 守护进程的物理网络。默认情况下,服务正在运行的每个容器都连接到本地 Docker 守护进程主机的 docker_gwbridge 网络。docker_gwbridge 网络在初始化或加入 Swarm 时自动创建。

 

 

 

通信流程

在本例中,将 node1 上的容器称为 C1,node2 上的容器称为 C2,如下图所示。假设 C1 希望 ping 通 C2,类似前面章节中的示例。

 

 

C1 发起 ping 请求,目标 IP 为 C2 的地址 10.0.0.4。该请求的流量通过连接到 Br0 虚拟交换机 veth 接口发出。虚拟交换机并不知道将包发送到哪里,因为在虚拟交换机的 MAC 地址映射表(ARP 映射表)中并没有与当前目的 IP 对应的 MAC 地址。

所以虚拟交换机会将该包发送到其上的全部端口。连接到 Br0 的 VTEP 接口知道如何转发这个数据帧,所以会将自己的 MAC 地址返回。这就是一个代理 ARP 响应,并且虚拟交换机 Br0 根据返回结果学会了如何转发该包。接下来虚拟交换机会更新自己的 ARP 映射表,将 10.0.0.4 映射到本地 VTEP 的 MAC 地址上。

现在 Br0 交换机已经学会如何转发目标为 C2 的流量,接下来所有发送到 C2 的包都会被直接转发到 VTEP 接口。VTEP 接口知道 C2,是因为所有新启动的容器都会将自己的网络详情采用网络内置 Gossip 协议发送给相同 Swarm 集群内的其他节点。

交换机会将包转发到 VTEP 接口,VTEP 完成数据帧的封装,这样就能在底层网络传输。具体来说,封装操作就是把 VXLAN Header 信息添加以太帧当中。

VXLAN Header 信息包含了 VXLAN 网络 ID(VNID),其作用是记录 VLAN 到 VXLAN 的映射关系。每个 VLAN 都对应一个 VNID,以便包可以在解析后被转发到正确的 VLAN。

封装的时候会将数据帧放到 UDP 包中,并设置 UDP 的目的 IP 字段为 node2 节点的 VTEP 的 IP 地址,同时设置 UDP Socket 端口为 4789。这种封装方式保证了底层网络即使不知道任何关于 VXLAN 的信息,也可以完成数据传输。

当包到达 node2 之后,内核发现目的端口为 UDP 端口 4789,同时还知道存在 VTEP 接口绑定到该 Socket。所以内核将包发给 VTEP,由 VTEP 读取 VNID,解压包信息,并根据 VNID 发送到本地名为 Br0 的连接到 VLAN 的交换机。在该交换机上,包被发送给容器 C2。

以上大体介绍了 Docker 覆盖网络是如何利用 VXLAN 技术的。

最后一件需要注意的是,Docker 支持使用同样的覆盖网络实现三层路由。例如,读者可以创建包含两个子网的覆盖网络,Docker 会负责子网间的路由。创建的命令如 docker network create --subnet=10.1.1.0/24 --subnet=11.1.1.0/24 -d overlay prod-net。该命令会在 Sandbox 中创建两个虚拟交换机,默认支持路由。

参考文档:http://c.biancheng.net/view/3198.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章