如何实现不同租户和应用间的地址空间和数据流量的隔离是实现数据中心网络虚拟化首先需要解决的几个问题之一。所谓地址空间的隔离是指不同租户和应用之间的网络(ip)地址之间不会产生相互干扰。换句话说,两个租户完全可以使用相同的网络地址。所谓数据流量的隔离是指任何一个租户和应用都不会感知或捕获到其他虚拟网络内部的流量。为了实现上述目的,我们可以在物理网络上面为租户构建各自的覆盖(overlay)网络,而隧道封装技术则是实现覆盖网络的关键。本节我们将针对目前较为流行的构建覆盖网络的隧道封装技术展开讨论,具体包括VXLAN,VXLAN-GPE,NVGRE和STT技术。
1.VXLAN
VXLAN(Virtual eXtensible Local Area Network)即虚拟可扩展局域网,是一种将二层报文用四层协议进行封装的Overlay技术。具体来说,VXLAN采用MAC-in-UDP的封装方式对二层网络进行扩展。目前在数据中心内应用VXLAN技术最广泛的场景即是实现虚拟机在三层网络范围内的自由迁移。使用VXLAN之后,原来局限于同数据中心、同物理二层网、同VLAN的虚拟机迁移可以不再受这些限制,可以按需扩展到虚拟二层网络上的任何地方。此外,VXLAN使用户可以创建多达16M相互隔离的虚拟网络,相对于VLAN所能支持的4096个虚拟网络而言具有质的提升。如图 1所示,VXLAN报文共有50字节(或54字节)的封装报文头,包括14字节(或18字节,含802.1 QTag)的外部以太网帧头(对应虚拟机所在物理机的MAC)、20字节的外部IP头(对应虚拟机所在物理机的IP)、8字节的外部UDP头、8字节的VXLAN头。
图 1. VXLAN封装格式
外层UDP头的目的端口缺省使用4798,也可以根据需要进行修改,源端口号是一个使用内层数据包计算出来的hash值,变动范围为49152-65535。外层IP头的源IP地址为源VTEP(VXLAN Tunnel End Point, VXLAN隧道端点)的地址,目的IP为目的VTEP地址(在内层数据包对应的目的VTEP未知时,此处为该内层数据包所属虚拟网络对应的IP多播组地址)。外层以太网头的MAC地址为VTEP的MAC 地址。由此可见对传输路径上的网络设备而言,虚拟机的信息完全被掩盖了。
如图 2所示,VXLAN头长8个字节,其中目前有效的字段包括一个字节的Flags标识位和3个字节的VNI(VXLAN Network Identifier,VXLAN网络标识符,用于标识一个虚拟网络)。其余4个字节作为保留域留作它用,但是目前在使用的时候必须将这些位置为0。对于Flags域而言,其中I 位(I代表Invalidation有效)必须被设为1,其余7位需要被设为0。VXLAN利用VNI进行网络隔离,同一个VNI中的虚拟机可以相互通讯。因VXLAN的网络标识VNI为24bit,故用户可以创建16M个相互隔离的虚拟网络。
图 2. VXLAN头格式[1]
VXLAN报文的封装/解封装是由位于隧道两端的VTEP负责完成。源端VTEP在对一段报文进行VXLAN封装之后,通过隧道向目的端VTEP发送封装报文。内层数据包对传输路径上的网络设备是不可见的,无需为内层数据包维护转发信息。当目的端VTEP接收到报文之后,首先对报文进行解封装,然后发给相应的虚拟机。VXLAN协议并没有对VTEP的实现形式进行规定,其可由支持VXLAN的硬件设备或软件来实现。
由于通信的VM对并不知道对端VM所对应VTEP的IP地址(即不知道该VM在哪个物理机上),因此VXLAN采取了数据平面学习机制:VXLAN的每个虚拟网络对应一个IP多播组(即VNI与IP多播地址为一一映射关系),并在VTEP本地维护这种对应关系。在进行数据包封装时,若本地没有目的VM对应的VTEP信息,则在该虚拟网络对应的IP多播组内进行多播,收到多播的VTEP检查目的VM是否在本地,做出响应,并将源VM和源VTEP的对应关系记录在本地。当源VTEP收到这一响应消息后即学得了目的VM和目的VTEP的对应关系。除此之外,VXLAN还可采用中央控制器的方式获取对端VTEP信息:各VTEP将本地VM MAC地址和VTEP IP的对应关系推送给控制器,当源VTEP不知道目的VM对应的VTEP IP时,直接向控制器请求该信息。
下面我们通过一个例子来介绍使用VXLAN构建虚拟网络的工作方式(根据[RFC7348],VTEP可实现在物理交换机或物理服务器上,下例以VTEP在VM所在物理服务器的hypervisor内来示例)。首先,假设当前虚拟网络(VNI=300)包含两台虚拟机:VM1和VM2。如图 3所示,为了实现虚拟网络内部虚拟机之间的相互通信,首先所有相关的VTEP需要通过IGMP协议加入多播组(239.0.0.1)。
图 3. VXLAN虚拟网络的初始化/加入多播组
此时,假设VM1需要向VM2发送数据。由于是第一次通信,VM1并没有VM2的MAC地址。因此,如图 4所示,VM1首先发出ARP请求。VTEP1捕获该报文,对其进行封装,并将VXLAN头中VNI设置为300,用于说明该消息属于编号为300的虚拟网络。目标ip地址被设为组播地址239.0.0.1,而源ip地址则为VTEP1的ip地址。经过多播转发之后,目的端的VTEP2会收到数据包。其首先对其进行解封装,并且发现其还没有存储VM1的地址信息,所以VTEP2首先将VM1的虚拟网络编号(300)、MAC地址(MAC1)和VTEP1的ip地址之间的映射关系进行缓存。在完成VM1地址的学习之后,VTEP2将解封装后ARP数据包在与其相连的所有VNI=300的虚拟机内进行广播。
图 4. VXLAN中发送ARP请求过程
如图 5所示,当VM2接收到ARP请求之后,因为发现其自身为目标主机,因此按照标准流程向VM1发送ARP响应。显然,响应必然被VTEP2所截获,并进行封装。由于此时VTEP2已经学习到了VM1的地址信息,因此其可以使用VTEP1的ip地址,以及主机1的MAC地址进行单播传输。VTEP1接收到单播报文后,学习内层MAC到外层IP地址的映射,解封装并根据被封装内容的目的MAC地址转发给VM1。最后由VM1完成对ARP应答报文的处理。
图 5. VXLAN中发送ARP响应过程
2.VXLAN-GPE
VXLAN定义了将以太网帧封装在外部UDP报文中的封装格式。VXLAN-GPE(Generic Protocol Extension VXLAN)则是对VXLAN的扩展,从而使得可以封装任意层次的数据包,另外还提供了对OAM(Operations ,Administration and Management)协议的支持。VXLAN-GPE扩展的方法是通过对外层VXLAN 头的一些保留位进行修改。如图 6所示,VXLAN-GPE对VXLAN头做了以下4方面的变动:
1)增加封装协议域(Next Protocol Field):该域用于指明被封装的数据报的协议类型,当前已定义的Next Protocol值包括:
2)增加P bit域:Flag域中的第5位(从零开始编号)被定义为P bit,其中如果8比特的封装协议域(Next Protocol)存在,则P bit需要设置为1。如果P bit为0,则按照标准的VXLAN协议进行解析。
3)增加O bit域:Flag的第7位被定义为O(OAM)bit。当O bit被设置为1时,内层的被封装数据包为OAM包,从而触发OAM包的处理过程。
4)增加Ver域:Flag的第8和第9两位被定义为Ver(Version),用于指明VXLAN-GPE版本(当前VXLAN-GPE版本为0)。
图 6. VXLAN-GPE头格式[2]
3.NVGRE
在介绍NVGRE之前,我们首先介绍一下由Cisco公司提出的GRE(Generic Routing Encapsulation,通用路由封装协议)。GRE的提出主要为了解决在任意层次网络协议之间的封装问题。本小节的内容主要参考了RFC1701和RFC1702。首先,GRE将需要传输的真实数据包称为载荷包(payload packet)。为了在隧道内进行传输,我们首先需要使用GRE头对载荷包进行封装,并且称封装后的数据包为GRE包。最后,GRE头外部还需封装相应的包头从而实现在物理网络上的传输。为了方便,外层的协议被称为传送协议(deliver protocol)。如图 7所示为GRE包头,其中各域的定义如下:
1)Flag域:GRE头的前2个字节为Flag域,其中:
2)Next Protocol(2个字节):指明内层被封装数据包的协议类型,如果内层数据包是IPv4类型,则应该被设置为 0x800。
3)Checksum(2字节):检验和
4)Offset(2字节):表明路由字段的起始地址到第一个有效的路由信息字段的偏移量,单位为字节。这个字段只有在C或者R位被置1时才存在,并且只有在R位有效时,其所包含的信息才有意义。
5)Key(4 字节):相同流中的数据包含有相同的Key值,解封装的隧道终端依据该值判断数据包是否属于相同的流。在NVGRE中,该字段被用来表示虚拟网络的标识。
6)Sequence Number (4 字节):用于标明数据包的传送顺序。
7)Routing(变长):源路由信息,当R位有效时,该域包含多个源路由条目(Source Routing Entry, SRE)。SRE的具体定义此处省略,有兴趣的读者可以参看RFC1701。
图 7. GRE包头的格式
GRE的封装和解封装过程与VXLAN的封装和解封装过程类似,此处就不再赘述。下面我们介绍一下NVGRE(Network Virtualization using Generic Routing Encapsulation)协议。NVGRE最初由微软公司提出,其目的是为了实现数据中心的多租户虚拟二层网络,其实现方式是将以太网帧封装在GRE头内并在三层网络上传输(MAC-in-IP)[3]。顾名思义,NVGRE的底层实现细节都可是复制GRE,因此我们将主要针对NVGRE与传统GRE的区别进行说明。如图 8所示,使用NVGRE封装的数据包包头格式与使用GRE封装是相同的。区别在于,在使用NVGRE时,GRE包头中的C和S位必须置0。换句话说,NVGRE的头中将没有检验和以及序列号。K位必须设置为1,从而使得Key域有效。但是NVGRE对Key域做了重新定义,其中前3个字节并定义为VSID(Virtual Subnet ID)、第四个字节被定义为FlowID。其中24位的VSID用于标示二层虚拟网络,因此NVGRE可以最多支持16M虚拟网。这个数量与VXLAN支持的虚拟网络数量是相同的。8位的FlowID使得管理程序可以在一个虚拟网络内部针对不同的数据流进行更加细粒度的操控。FlowID应该由NVGRE端点(NVE)来生成并添加,在网络传输过程中不允许网络设备修改。如果NVE没有生成FlowID,那么该域必须置零。另外,因为NVGRE内部封装的是以太网帧,所以GRE头中的protocol type域一定要设置为0x6558(transparent Ethernet bridging,透明以太网桥)。
图 8. 采用NVGRE封装的数据包头格式