Docker overlay覆盖网络及VXLAN详解.docx

上传人:b****5 文档编号:11802812 上传时间:2023-04-02 格式:DOCX 页数:11 大小:140.48KB
下载 相关 举报
Docker overlay覆盖网络及VXLAN详解.docx_第1页
第1页 / 共11页
Docker overlay覆盖网络及VXLAN详解.docx_第2页
第2页 / 共11页
Docker overlay覆盖网络及VXLAN详解.docx_第3页
第3页 / 共11页
Docker overlay覆盖网络及VXLAN详解.docx_第4页
第4页 / 共11页
Docker overlay覆盖网络及VXLAN详解.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

Docker overlay覆盖网络及VXLAN详解.docx

《Docker overlay覆盖网络及VXLAN详解.docx》由会员分享,可在线阅读,更多相关《Docker overlay覆盖网络及VXLAN详解.docx(11页珍藏版)》请在冰豆网上搜索。

Docker overlay覆盖网络及VXLAN详解.docx

Dockeroverlay覆盖网络及VXLAN详解

Dockeroverlay覆盖网络及VXLAN详解

在现实世界中,容器间通信的可靠性和安全性相当重要,即使容器分属于不同网络中的不同主机。

这也是覆盖网络大展拳脚的地方,它允许创建扁平的、安全的二层网络来连接多个主机,容器可以连接到覆盖网络并直接互相通信。

Docker 提供了原生覆盖网络的支持,易于配置且非常安全。

其背后是基于Libnetwork以及相应的驱动来构建的。

Libnetwork是CNM的典型实现,从而可以通过插拔驱动的方式来实现不同的网络技术和拓扑结构。

Docker提供了一些诸如Overlay的原生驱动,同时第三方也可以提供驱动。

在2015年3月,Docker公司收购了一个叫作SocketPlane的网络初创企业。

收购的原因有二,首先是因为这会给Docker带来真正意义的网络架构,其次是让容器间联网变得非常简单,以至于开发人员都可以配置它。

Docker公司在这两点上都取得了巨大的成功。

但是,简洁的网络命令实际由大量的组件构成。

这部分内容是在进行生产环境部署和问题定位前必须要了解的。

在Swarm模式下构建并测试Docker覆盖网络

要完成下面的示例,需要两台Docker主机,并通过一个路由器上两个独立的二层网络连接在一起。

如下图所示,注意节点位于不同网络之上。

可以选择 Linux 容器主机或者Windows容器主机。

Linux内核版本不能低于4.4(高版本更好),Windows需要WindowsServer2016版本,并且应安装最新的补丁。

1)构建Swarm

首先需要将两台主机配置为包含两个节点的Swarm集群。

接下来会在node1节点上运行 dockerswarminit命令使其成为管理节点,然后在node2节点上运行 dockerswarmjoin 命令来使其成为工作节点。

在node1节点上运行下面的命令。

$dockerswarminit\

--advertise-addr=172.31.1.5\

--listen-addr=172.31.1.5:

2377

Swarminitialized:

currentnode(1ex3...o3px)isnowamanager.

在node2上运行下面的命令。

如果需要在Windows环境下生效,则需要修改Windows防火墙规则,打开2377/tcp、7946/tcp以及7946/udp等几个端口。

$dockerswarmjoin\

--tokenSWMTKN-1-0hz2ec...2vye\

172.31.1.5:

2377

Thisnodejoinedaswarmasaworker.

现在就已经创建好了包含管理节点node1和工作节点node2两个节点的Swarm集群了。

2)创建新的覆盖网络

现在创建一个名为uber-net的覆盖网络。

在node1(管理节点)节点上运行下面的命令。

若要这些命令在Windows上也能运行,需要在WindowsDocker节点上添加4789/udp规则。

$dockernetworkcreate-doverlayuber-net

c740ydi1lm89khn5kd52skrd9

刚刚创建了一个崭新的覆盖网络,能连接Swarm集群内的所有主机,并且该网络还包括一个TLS加密的控制层!

如果还想对数据层加密的话,只需在命令中增加-oencrypted参数。

可以通过 dockernetworkls 命令列出每个节点上的全部网络。

$dockernetworkls

NETWORKIDNAMEDRIVERSCOPE

ddac4ff813b7bridgebridgelocal

389a7e7e8607docker_gwbridgebridgelocal

a09f7e6b2ac6hosthostlocal

ehw16ycy980singressoverlayswarm

2b26c11d3469nonenulllocal

c740ydi1lm89uber-netoverlayswarm

在WindowsDocker主机上输出内容如下。

NETWORKIDNAMEDRIVERSCOPE

8iltzv6sbtgcingressoverlayswarm

6545b2a61b6fnatnatlocal

96d0d737c2eenonenulllocal

nil5ouh44qcouber-netoverlayswarm

列表的最下方就是刚刚创建的网络uber-net。

其他的网络是在安装Docker以及初始化Swarm集群的时候创建的。

如果在node2节点上运行 dockernetworkls 命令,就会发现无法看到uber-net网络。

这是因为只有当运行中的容器连接到覆盖网络的时候,该网络才变为可用状态。

这种延迟生效策略通过减少网络梳理,提升了网络的扩展性。

3)将服务连接到覆盖网络

现在覆盖网络已经就绪,接下来新建一个Docker服务并连接到该网络。

Docker服务会包含两个副本(容器),一个运行node1节点上,一个运行在node2节点上。

这样会自动将node2节点接入uber-net网络。

在node1节点上运行下面的命令。

Linux示例如下。

$dockerservicecreate--nametest\

--networkuber-net\

--replicas2\

ubuntusleepinfinity

Windows示例如下。

>dockerservicecreate--nametest`

--networkuber-net`

--replicas2`

microsoft\powershell:

nanoserverStart-Sleep3600

Windows示例使用反引号的方式将单条命令分为多行,以提高命令的可读性。

PowerShell 中使用反引号来转义换行字符。

该命令创建了名为test的新服务,连接到了uber-net这个覆盖网络,并且还基于指定的镜像创建了两个副本(容器)。

在两个示例中,均在容器中采用sleep命令来保持容器运行,并在休眠结束后退出该容器。

由于运行了两个副本(容器),而Swarm包含两个节点,因此每个节点上都会运行一个副本。

可以通过 dockerserviceps 命令来确认上面的操作。

$dockerservicepstest

IDNAMEIMAGENODEDESIREDSTATECURRENTSTATE

77q...rkxtest.1ubuntunode1RunningRunning

97v...pa5test.2ubuntunode2RunningRunning

当Swarm在覆盖网络之上启动容器时,会自动将容器运行所在节点加入到网络当中。

这意味着此时在node2节点上就可以看到uber-net网络了。

目前已经成功在两个由物理网络连接的节点上创建了新的覆盖网络。

同时,还将两个容器连接到了该网络当中。

4)测试覆盖网络

现在使用ping命令来测试覆盖网络。

如下图所示,在两个独立的网络中分别有一台Docker主机,并且两者都接入了同一个覆盖网络。

目前在每个节点上都有一个容器接入了覆盖网络。

测试一下两个容器之间是否可以ping通。

为了执行该测试,需要知道每个容器的IP地址(为了测试,暂时忽略相同覆盖网络上的容器可以通过名称来互相ping通的事实)。

运行 dockernetworkinspect 查看被分配给覆盖网络的Subnet。

$dockernetworkinspectuber-net

[

{

 "Name":

"uber-net",

 "Id":

"c740ydi1lm89khn5kd52skrd9",

 "Scope":

"swarm",

 "Driver":

"overlay",

 "EnableIPv6":

false,

 "IPAM":

{

  "Driver":

"default",

  "Options":

null,

  "Config":

[

   {

    "Subnet":

"10.0.0.0/24",

    "Gateway":

"10.0.0.1"

   }

  

由以上输出可见,uber-net的子网是10.0.0.0/24。

注意,这与两个节点的任意底层物理网络IP均不相符(172.31.1.0/24和192.168.1.0/24)。

在node1和node2节点上运行下面两条命令。

这两条命令可以获取到容器ID和IP地址。

在第二条命令中一定要使用读者自己的环境中的容器ID。

需要在两台节点上分别运行上述命令,获取两个容器的ID和IP地址。

下图展示了配置现状。

在运行环境中,子网和IP地址信息可能不同。

由图可知,一个二层覆盖网络横跨两台主机,并且每个容器在覆盖网络中都有自己的IP地址。

这意味着node1节点上的容器可以通过node2节点上容器的IP地址10.0.0.4来ping通,该IP地址属于覆盖网络。

尽管两个节点分属于不同的二层网络,还是可以直接ping通。

接下来验证这一点。

登录到node1的容器,并ping另一个的容器。

在LinuxUbuntu容器中执行该操作的话,需要安装ping工具包。

如果读者使用WindowsPowerShell示例,ping工具已默认安装。

Linux示例如下。

Windows示例如下。

>dockercontainerexec-it1a4f29e5a4b6pwsh.exe

WindowsPowerShell

Copyright(C)2016MicrosoftCorporation.Allrightsreserved.

PSC:

\>ping10.0.0.4

Pinging10.0.0.4with32bytesofdata:

Replyfrom10.0.0.4:

bytes=32time=1msTTL=128

Replyfrom10.0.0.4:

bytes=32time<1msTTL=128

Replyfrom10.0.0.4:

bytes=32time=2msTTL=128

Replyfrom10.0.0.4:

bytes=32time=2msTTL=12

PSC:

\>

由运行结果可知node1上的容器可以通过覆盖网络ping通node2之上的容器了。

还可以在容器内部跟踪ping命令的路由信息。

路由信息只有一条,证明容器间通信确实通过覆盖网络直连。

如果希望Linux示例中的traceroute可执行,需要安装traceroute包。

Linux示例如下。

$root@396c8b142a85:

/#traceroute10.0.0.4

tracerouteto10.0.0.4(10.0.0.4),30hopsmax,60bytepackets

1test-svc.2.97v...a5.uber-net(10.0.0.4)1.110ms1.034ms1.073ms

Windows示例如下。

PSC:

\>tracert10.0.0.3

Tracingroutetotest.2.ttcpiv3p...7o4.uber-net[10.0.0.4]

overamaximumof30hops:

1<1ms<1ms<1mstest.2.ttcpiv3p...7o4.uber-net[10.0.0.4]

Tracecomplete.

到目前为止,已经通过单条命令创建了覆盖网络,并向该网络中接入了容器。

这些容器分布在两个不同的主机上,两台主机分属于不同的二层网络。

在找出两台容器的IP之后,验证了容器可以通过覆盖网络完成直连。

工作原理

现在已经知道如何创建并使用容器覆盖网络,接下来介绍一下这一切背后的技术原理。

1)VXLAN入门

首先必须知道,Docker使用VXLAN隧道技术创建了虚拟二层覆盖网络。

所以,在详解之前,先快速了解一下VXLAN。

在VXLAN的设计中,允许用户基于已经存在的三层网络结构创建虚拟的二层网络。

在前面的示例中创建了一个子网掩码为10.0.0.0/24的二层网络,该网络是基于一个三层IP网络实现的,三层IP网络由172.31.1.0/24和192.168.1.0/24这两个二层网络构成。

具体如下图所示。

VXLAN的美妙之处在于它是一种封装技术,能使现存的路由器和网络架构看起来就像普通的IP/UDP包一样,并且处理起来毫无问题。

为了创建二层覆盖网络,VXLAN基于现有的三层IP网络创建了隧道。

小伙伴可能听过基础网络(UnderlayNetwork)这个术语,它用于指代三层之下的基础部分。

VXLAN隧道两端都是VXLAN隧道终端(VXLANTunnelEndpoint,VTEP)。

VTEP完成了封装和解压的步骤,以及一些功能实现所必需的操作,如下图所示。

2)梳理一下两个容器的示例

在前面的示例中,读者通过IP网络将两台主机连接起来。

每个主机运行了一个容器,之后又为容器连接创建了一个VXLAN覆盖网络。

为了实现上述场景,在每台主机上都新建了一个Sandbox(网络命名空间)。

正如前文所讲,Sandbox就像一个容器,但其中运行的不是应用,而是当前主机上独立的网络栈。

在Sandbox内部创建了一个名为Br0的虚拟交换机(又称做虚拟网桥)。

同时Sandbox内部还创建了一个VTEP,其中一端接入到名为Br0的虚拟交换机当中,另一端接入主机网络栈(VTEP)。

在主机网络栈中的终端从主机所连接的基础网络中获取到IP地址,并以UDPSocket的方式绑定到4789端口。

不同主机上的两个VTEP通过VXLAN隧道创建了一个覆盖网络,如下图所示。

这是VXLAN上层网络创建和使用所必需的。

接下来每个容器都会有自己的虚拟以太网(veth)适配器,并接入本地Br0虚拟交换机。

目前拓扑结构如下图所示,虽然是在主机所属网络互相独立的情况下,但这样能更容易看出两个分别位于不同主机上的容器之间是如何通过VXLAN上层网络进行通信的。

3)通信示例

在本例中,将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完成数据帧的封装,这样就能在底层网络传输。

具体来说,封装操作就是把VXLANHeader信息添加以太帧当中。

VXLANHeader信息包含了VXLAN网络ID(VNID),其作用是记录VLAN到VXLAN的映射关系。

每个VLAN都对应一个VNID,以便包可以在解析后被转发到正确的VLAN。

封装的时候会将数据帧放到UDP包中,并设置UDP的目的IP字段为node2节点的VTEP的IP地址,同时设置UDPSocket端口为4789。

这种封装方式保证了底层网络即使不知道任何关于VXLAN的信息,也可以完成数据传输。

当包到达node2之后,内核发现目的端口为UDP端口4789,同时还知道存在VTEP接口绑定到该Socket。

所以内核将包发给VTEP,由VTEP读取VNID,解压包信息,并根据VNID发送到本地名为Br0的连接到VLAN的交换机。

在该交换机上,包被发送给容器C2。

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

最后一件需要注意的是,Docker支持使用同样的覆盖网络实现三层路由。

例如,读者可以创建包含两个子网的覆盖网络,Docker会负责子网间的路由。

创建的命令如dockernetworkcreate--subnet=10.1.1.0/24--subnet=11.1.1.0/24-doverlayprod-net。

该命令会在Sandbox中创建两个虚拟交换机,默认支持路由。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1