一、知识背景

详见:

https://support.huawei.com/enterprise/zh/doc/EDOC1100087027#ZH-CN_TOPIC_0254803605

http://www.h3c.com/cn/d_201811/1131076_30005_0.htm 

1、vxlan 简介

VXLAN 全称是 Virtual eXtensible Local Area Network,虚拟可扩展的局域网。它是一种 overlay 技术,通过三层的网络来搭建虚拟的二层网络。rfc7348 (参考资料1) 上的介绍是这样的:“A framework for overlaying virtualized layer 2 networks over lay 3 networks.”。

每一个技术出来都有它要解决的问题,VXLAN 也不例外,那么我们先看看 VXLAN 到底要解决哪些问题。

  • 虚拟化(虚拟机和容器)的兴起使得一个数据中心会有成千上万的机器需要通信,而传统的 VLAN 技术只能支持 4096 个网络上限,已经满足不了不断扩展的数据中心规模
  • 越来越多的数据中心(尤其是公有云服务)需要提供多租户的功能,不同用户之间需要独立地分配 ip 和 MAC 地址,如何保证这个功能的扩展性和正确性也是一个待解决的问题
  • 云计算业务对业务灵活性要求很高,虚拟机可能会大规模迁移,并保证网络一直可用,也就是大二层的概念。解决这个问题同时保证二层的广播域不会过分扩大,也是云计算网络的要求

传统二层+三层的网络在应对这些要求时变得力不从心,虽然很多改进型的技术比如堆叠、SVF、TRILL 等能够增加二层的范围,努力改进经典网络,但是要做到对网络改动小同时保证灵活性高却非常困难。为了解决这些问题,有很多方案被提出来,vxlan 就是其中之一。vxlan 是 VMware、Cisco 等一众大型企业共同推出的,目前标准文档在 RFC7348

2、VXLAN基本概念

vxlan实战 vxlan技术简介_vxlan实战

 

• VNI(VXLAN Network Identifier,VXLAN网络标识符):VXLAN通过VXLAN ID来标识,其长度为24比特。VXLAN 16M个标签数解决了VLAN标签不足的缺点。

• VTEP(VXLAN Tunnel End Point,VXLAN隧道端点):VXLAN的边缘设备。VXLAN的相关处理都在VTEP上进行,例如识别以太网数据帧所属的VXLAN、基于VXLAN对数据帧进行二层转发、封装/解封装报文等。VTEP可以是一台独立的物理设备,也可以是虚拟机所在服务器的虚拟交换机。

• VXLAN Tunnel两个VTEP之间点到点的逻辑隧道。VTEP为数据帧封装VXLAN头、UDP头、IP头后,通过VXLAN隧道将封装后的报文转发给远端VTEP,远端VTEP对其进行解封装。

• VSIVirtual Switching Instance,虚拟交换实例):VTEP上为一个VXLAN提供二层交换服务的虚拟交换实例。VSI可以看作是VTEP上的一台基于VXLAN进行二层转发的虚拟交换机,它具有传统以太网交换机的所有功能,包括源MAC地址学习、MAC地址老化、泛洪等。VSI与VXLAN一一对应。

• VSI-Interface(VSI的虚拟三层接口):类似于Vlan-Interface,用来处理跨VNI即跨VXLAN的流量。VSI-Interface与VSI一一对应,在没有跨VNI流量时可以没有VSI-Interface。

vxlan实战 vxlan技术简介_vxlan实战_02

现有VTEP设备中,一般用“接口+VLAN”的方式来区分流量与VSI的对应关系,而VSI与VXLAN Tunnel之间既可以建立全连接,也可以根据需求进行关联。

二、vxlan 网络通信过程

通过上节的内容,我们大致了解 vxlan 报文的发送过程。虚拟机的报文通过 vtep 添加上 vxlan 以及外部的报文层,然后发送出去,对方 vtep 收到之后拆除 vxlan 头部然后根据 VNI 把原始报文发送到目的虚拟机。

上面的过程是双方已经知道所有通信信息的过程,但是在第一次通信之前还有很多问题有解决:

  • 哪些 vtep 需要加到一个相同的 VNI 组?
  • 发送方虚拟机怎么知道对方的 MAC 地址?
  • vtep 怎么知道目的虚拟机在哪一台宿主机上?

这三个问题可以归结为同一个问题:vxlan 网络怎么感知彼此的存在并选择正确的路径传输报文?

而且第一个问题也是不用回答的,因为 vtep 形成的组是虚构的概念,只有某些 vtep 能够正确地传递报文,它们就是在同一个组内。也就是说,我们只要回答后面两个问题就行。

要回答这两个问题,我们还是回到 vxlan 协议报文上,看看一个完整的 vxlan 报文需要哪些信息。

  • 内层报文:通信的虚拟机双方要么直接使用 IP 地址,要么通过 DNS 等方式已经获取了对方的 IP 地址,因此网络层地址已经知道。同一个网络的虚拟机需要通信,还需要知道对方虚拟机的 MAC 地址,vxlan 需要一个机制来实现传统网络 ARP 的功能
  • vxlan 头部:只需要知道 VNI,这一般是直接配置在 vtep 上的,要么是提前规划写死的,要么是根据内部报文自动生成的,也不需要担心
  • UDP 头部:最重要的是源地址和目的地址的端口,源地址端口是系统生成并管理的,目的端口也是写死的,比如 IANA 规定的 4789 端口,这部分也不需要担心
  • IP 头部:IP 头部关心的是 vtep 双方的 IP 地址,源地址可以很简单确定,目的地址是虚拟机所在地址宿主机 vtep 的 IP 地址,这个也需要由某种方式来确定
  • MAC 头部:如果 vtep 的 IP 地址确定了,MAC 地址可以通过经典的 ARP 方式来获取,毕竟 vtep 网络在同一个三层,经典网络架构那一套就能直接用了

总结一下,一个 vxlan 报文需要确定两个地址信息:目的虚拟机的 MAC 地址和目的 vtep 的 IP 地址,如果 VNI 也是动态感知的,那么 vtep 就需要一个三元组:

内部 MAC <--> VNI <--> VTEP IP

根据实现的不同,一般分为两种方式:多播和控制中心。多播的概念是同个 vxlan 网络的 vtep 加入到同一个多播网络,如果需要知道以上信息,就在组内发送多播来查询;控制中心的概念是在某个集中式的地方保存了所有虚拟机的上述信息,自动化告知 vtep 它需要的信息。

针对这两种方式,我们下面就分别分析。

1、多播

多播的概念和工作原理不是这里的重点,所以就不介绍了。简单来说,每个多播组对应一个多播 IP 地址,往这个多播 IP 地址发送的报文会发给多播组的所有主机。

为什么要使用多播?因为 vxlan 的底层网络是三层的,广播地址无法穿越三层网络,要给 vxlan 网络所有 vtep 发送报文只能通过多播。

下图是在多播模式下,vxlan 的报文工作流程,位于左下方的 机器 A 要通过 vxlan 网络发送报文给右下方的机器 B。

 

vtep 建立的时候会通过配置加入到多播组(具体做法取决于实现),图中的多播组 IP 地址是 239.1.1.1

  1. 机器 A 只知道对方的 IP 地址,不知道 MAC 地址,因此会发送 ARP 报文进行查询,内部的 ARP 报文很普通,目标地址为全 1 的广播地址
  2. vtep 收到 ARP 报文,发现虚拟机目的 MAC 为广播地址,封装上 vxlan 协议头部之后(外层 IP 为多播组 IP,MAC 地址为多播组的 MAC 地址),发送给多播组 239.1.1.1,支持多播的底层网络设备(交换机和路由器)会把报文发送给组内所有的成员
  3. vtep 接收到 vxlan 封装的 ARP 请求,去掉 vxlan 头部,并通过报文学习到发送方 <虚拟机 MAC - VNI - Vtep IP> 三元组保存起来,把原来的 ARP 报文广播给主机
  4. 主机接收到 ARP 请求报文,如果 ARP 报文请求的是自己的 MAC 地址,就返回 ARP 应答
  5. vtep-2 此时已经知道发送放的虚拟机和 vtep 信息,把 ARP 应答添加上 vxlan 头部(外部 IP 地址为 vtep-1 的 IP 地址,VNI 是原来报文的 VNI)之后通过单播发送出去
  6. vtep-1 接收到报文,并学习到报文中的三元组,记录下来。然后 vtep 进行解包,知道内部的 IP 和 MAC 地址,并转发给目的虚拟机
  7. 虚拟机拿到 ARP 应答报文,就知道了到目的虚拟机的 MAC 地址

在这个过程中,只有一次多播,因为 vtep 有自动学习的能力,后续的报文都是通过单播直接发送的。可以看到,多播报文非常浪费,每次的多播其实只有一个报文是有效的,如果某个多播组的 vtep 数量很多,这个浪费是非常大的。但是多播组也有它的实现起来比较简单,不需要中心化的控制,只有底层网络支持多播,只有配置好多播组就能自动发现了。

单播报文的发送过程就是上述应答报文的逻辑,应该也非常容易理解了。还有一种通信方式,那就是不同 VNI 网络之间的通信,这个需要用到 vxlan 网关(可以是物理网络设备,也可以是软件),它接收到一个 vxlan 网络报文之后解压,根据特定的逻辑添加上另外一个 vxlan 头部转发出去。

因为并不是所有的网络设备都支持多播,再加上多播方式带来的报文浪费,在实际生产中这种方式很少用到。

2、分布式控制中心

从多播的流程可以看出来,其实 vtep 发送报文最关键的就是知道对方虚拟机的 MAC 地址和虚拟机所在主机的 vtep IP 地址。如果能够事先知道这两个信息,直接告诉 vtep,那么就不需要多播了。

在虚拟机和容器的场景中,当虚拟机或者容器启动还没有进行网络通讯时,我们就可以知道它的 IP 和 MAC(可能是用某种方式获取,也有可能是事先控制这两个地址),分布式控制中心保存了这些信息。除此之外,控制中心还保存了每个 vxlan 网络有哪些 vtep,这些 vtep 的地址是多少。有了这些信息,vtep 就能发送报文时直接查询并添加头部,不需要多播去满网络地问了。

一般情况下,在每个 vtep 所在的节点都会有一个 agent,它会和控制中心通信,获取 vtep 需要的信息以某种方式告诉 vtep。具体的做法取决于具体的实现,每种实现可能会更新不同的信息给 vtep,比如 HER(Head End Replication)只是把多播组替换成多个单播报文,也就是把多播组所有的 VTEP IP 地址告诉 vtep,这样查询的时候不是发送多播,而是给组内每个 vtep 发送一个单播报文;有些实现只是告诉 vtep 目的虚拟机的 MAC 地址信息;有些实现告诉 MAC 地址对应的 vtep IP 地址。

此外,什么时候告诉 vtep 这些信息也是有区别的。一般有两种方式:常见的是一旦知道了虚拟机的三元组信息就告诉 vtep(即使某个 vtep 用不到这个信息,因为它管理的虚拟机不会和这个地址通信),一般这时候第一次通信还没有发生;另外一种方式是在第一次通信时,当 vtep 需要这些信息的时候以某种方式通知 agent,然后 agent 这时候才告诉 vtep 信息。

分布式控制的 vxlan 是一种典型的 SDN 架构,也是目前使用最广泛的方式。因为它的实现多样,而且每种实现都有些许差距,这里不便来具体的例子来说明,只要明白了上面的原理,不管是什么样的实现,都能很快上手。

三、vxlan实验

1、点对点的vxlan通信

点对点的vxlan通信,在这个实验中使用两台虚拟机构成一个vlan网络,每台机器的网卡作为vtep,通过设置的ip互相通信。实验结构图如下图所示。

vxlan实战 vxlan技术简介_vxlan_03

对于,两台主机的网卡之间的通信,如果不使用vxlan,就需要设置路由表,此时两个网卡的ip不能是同一个网段。接下来,进行点对点的vxlan的通信。

在虚拟机一(上图左边)中输入命令如下:

root@yang-VirtualBox:/home/yang# ip link add vxlan-ethd type vxlan id 1 dstport 4789 remote 192.168.56.102 local 192.168.56.101
root@yang-VirtualBox:/home/yang# ip link set vxlan-ethd up
root@yang-VirtualBox:/home/yang# ip addr add 10.0.1.1/24 dev vxlan-ethd

上面第一条命令创建一个名字为 vxlan-ethd,类型为 vxlan 的网卡,后面是 vxlan-ethd 网卡需要的参数:

  • id 1:指定 VNI 的值,这个值可以在 1 到 2^24 之间
  • dstport:vtep 通信的端口,linux 默认使用 8472(为了保持兼容,默认值一直没有更改),而 IANA 分配的端口是 4789,所以我们这里显式指定了它的值
  • remote 192.168.56.102:对方 vtep 的地址,类似于点对点协议
  • local 192.168.56.101:当前节点 vtep 要使用的 IP 地址

第二条命令启动vxlan-ethd网卡,只有启动网卡,才能正常工作;

第三条命令为网卡vxlan-ethd分配IP地址。

在虚拟机为(上图右边)中输入的命令和虚拟机一的命令基本相同,如下图所示:

root@yangmumu-VirtualBox:/home/yangmumu# ip link add vxlan-ethc type vxlan id 1 dstport 4789 remote 192.168.56.101 local 192.168.56.102
root@yangmumu-VirtualBox:/home/yangmumu# ip link set vxlan-ethc up
root@yangmumu-VirtualBox:/home/yangmumu# ip addr add 10.0.1.2/24 dev vxlan-ethc

接下来,这两个位于不同虚拟机上的网卡就可以通过vxlan隧道进行通信了,在虚拟机一中输入ping -I 10.0.1.1 10.0.1.2,结果如下图所示。

vxlan实战 vxlan技术简介_vxlan_04

2、基于交换机的跨主机的容器通信实验

此次实验是利用隧道实现多个网络空间的通信。尽管上一个实验能够通过vxlan实现两个网卡的跨主机通信,但是通信的双方只有 vtep,在实际的生产中,每台主机上都有几十台甚至上百台的虚拟机或者容器需要通信,因此我们需要找到一种方法能够把这些通信实体组织起来。在 linux 中把同一个网段的 interface 组织起来正是网桥(bridge,或者 switch,这两个名称等价)的功能,因此这部分我们介绍如何用网桥把多个虚拟机或者容器放到同一个 vxlan overlay 网络中。最终实现的网络架构如下图所示。

vxlan实战 vxlan技术简介_ovs_05

我们知道,同一个vm下的同一个交换机连接的主机之间如果不设置vlan,主机之间可以随意的相互通信,但是不同vm下的虚拟网络空间,即便网络号一样也不能相互通信,只能实现不同网络号的主机之间利用路由器实现通信,vxlan的作用就是设置一个隧道,让不同的虚拟空间就像在同一个交换机下面一样,也就是本实验完成后,实验拓扑实际上类似下图所示。

vxlan实战 vxlan技术简介_vxlan_06

接下来,设置network namespace、ovs等的命令,参考之前的博客。

首先,在vm1中新建ns1-d、ns2-d、ns3-d三个网络空间,新建三对veth网卡,作为ns与ovs之间的连接,新建一个ovs交换机,设置其流表为普通交换机。具体的新建命令如下。

# 新建三个网络空间
ip netns add ns1-d
ip netns add ns2-d
ip netns add ns3-d
# 新建三队veth网卡
ip link add veth1-ns1 type veth peer name veth2-ns1
ip link add veth1-ns2 type veth peer name veth2-ns2
ip link add veth1-ns3 type veth peer name veth2-ns3
# 新建一个ovs交换机
ovs-vsctl add-br vswicth-d

然后将veth1-ns1、veth1-ns2、veth1-ns3三个网卡分别添加进ns1-d、ns2-d、ns3-d,其余的三个网卡加入ovs中,然后启动加入ovs的三个网卡,具体的命令如下所示。

# 将网卡加入网络空间中
ip link set veth1-ns1 netns ns1-d
ip link set veth1-ns2 netns ns2-d
ip link set veth1-ns3 netns ns3-d
# 将网卡加入ovs中
ovs-vsctl add-port vswitch-d veth2-ns1
ovs-vsctl add-port vswitch-d veth2-ns2
ovs-vsctl add-port vswitch-d veth2-ns3
# 启动ovs的网卡
ip link set veth2-ns1 up
ip link set veth2-ns2 up
ip link set veth2-ns3 up

分别进入各个网络空间,分别为网卡veth1-ns1、veth1-ns2、veth1-ns3设置ip地址并启动网卡,命令如下。

# 进入ns1-d的网络空间,启动网卡,设置IP地址
ip netns exec ns1-d bash
ip link set lo up
ip link set veth1-ns1 up
ip addr add 10.0.1.1/24 dev veth1-ns1

# 进入ns2-d的网络空间,启动网卡,设置IP地址
ip netns exec ns2-d bash
ip link set lo up
ip link set veth1-ns2 up
ip addr add 10.0.1.2/24 dev veth1-ns1

# 进入ns3-d的网络空间,启动网卡,设置IP地址
ip netns exec ns3-d bash
ip link set lo up
ip link set veth1-ns3 up
ip addr add 10.0.1.3/24 dev veth1-ns1

然后,在vm1的命令行中新建类型为vxlan的网卡vxlan-d,并启动网卡,加入ovs中,命令如下所示。

ip link add vxlan-d type vxlan id 1 dstport 4789 remote 192.168.56.102 local 192.168.56.101
ip link set vxlan-d up
ovs-vsctl add-port vswitch-d vxlan-d

此时,vm1内的设置已经全部完成了,接下来就是对vm2内进行设置,命令除了名称外和ip外其余和vm1的一致。这里就不再赘述。

接下来,在vm1的ns1-d网络空间下,执行命令ping 10.0.1.11,即vm2的ns1-c的网址,结果如下图所示。

vxlan实战 vxlan技术简介_vxlan_07

可以根据图看出,通过设置vxlan隧道,实现了两个主机之间的网络空间的通信。