这篇文章来讲下GRE和VXLAN分别是什么。
1.GRE
首先看先GRE。GRE的全称是Generic Routing Encapsulation,协议格式见RFC2784(https://tools.ietf.org/html/rfc2784)。简单的说,GRE是一种协议封装的格式。
协议封装指的是用一种格式的协议封装另一种格式的协议。我们熟悉的TCP/IP协议可以看成是一种封装:TCP传输层协议被网络层的IP协议封装,通过IP协议来进行传输。还有比如很有用的IP SAN,就是通过IP协议封装scsi协议,使得我们可以直接通过IP网络来进行磁盘数据的传输。对于这两个例子来说,前一种封装的目的是通过分层来严格的区分协议的设计,使得具体的协议设计的时候可以更加的清晰,而后者则是为了使用现有的设施,方便厂商推广自己的产品,同时通过两种协议的结合产生更多的功能。对于GRE来说,小秦更认为其是偏向后者的一种封装。
GRE的目的是设计一种通用的封装格式,所以如果将它与一些为特定目的进行设计的封装协议比较,那么GRE是没有太多优势的。
在GRE中,需要被传输和封装的报文称之为payload packet,而用于封装和传输的协议则成为delivery protocol。GRE在封装的时候,除了payload和delivery协议的header外,会生成一个GRE header。GRE header + payload一起被delivery协议封装用于传输,GRE header会包含payload的一些信息,包括checksum、version、payload的协议类型等。可以看到,通过这个GRE header的协议类型字段,我们可以做很多的事情。既然底层的delivery协议是用于传输的,那么A和B通信的时候delivery协议可以看成是个邮局送信火车,虽然很重要,但是对于业务理解来说没有其运送的信重要。当脱取这一层delivery层后,我们怎么知道信的格式呢?通过GRE header中的协议类型我们就能知道协议类型了,既然知道了协议类型,那么就有能力解析了。
由于GRE是一种通用的格式,我们可以使用GRE进行很多不同种类的封装。比如我们可以使用PPTP协议来进行VPN,可以使用IPv4来包裹IPv6。比较常见的delivery协议一般是IP协议。
不过GRE在设计的时候有一个问题,那就是没有考虑加密。因此现在常见的需要加密的封装一般是用的IPsec协议。
一个例子可以参考http://assafmuller.com/2013/10/10/gre-tunnels/,比如说:
A主机是在公司,B主机是在家,A网络的地址为192.168.1.1,B网络的地址为192.168.1.2,A如果要和B通信,则需要通过互联网,所以在A连接的路由器RA上,会配置一个tunnel口,tunnel口的信息是(18.9.3.2 -> 17.3.2.4),在B连接的路由器RB上也会配置一个tunnel口,tunnel口的信息是(17.3.2.4 -> 18.9.3.2)。同时在设置好路由的情况下,A发送一个报文给B,报文会首先到RA,RA发现报文需要走互联网,于是通过tunnel口封装,封装的delivery协议的目的地址写的是配置的RB的地址17.3.2.4
。报文到了RB后delivery协议被脱去,然后RB根据路由信息转发给B。
在openstack中,GRE可以代替VLAN来实现VM之间的通信,具体的可以参考http://assafmuller.com/2013/10/14/gre-tunnels-in-openstack-neutron/。主要是通过ovs,ovs支持GRE,通过GRE,VM之间的ARP、IP报文都能在GRE的封装下通过IP网络进行传递。不同的网络通过GRE header中的tunnel id号区别。由于ovs支持openflow协议,为了效率和性能,mac和GRE的路由关系会存放在ovs的流表中。从链接中的文章可以看出,GRE有一个缺点,那就是每新增一个计算节点,都需要其和所有其他计算节点以及network控制器建立GRE链接。在计算节点很多的时候会有性能问题。
2.VXLAN
相比于GRE的通用性,VXLAN主要用于封装、转发2层报文。VXLAN全称Virtual eXtensible Local Area Network,简单的说就是扩充了的VLAN,其使得多个通过三层连接的网络可以表现的和直接通过一台一台物理交换机连接配置而成的网络一样处在一个LAN中。其将二层报文加上个vxlan header,封装在一个UDP包中进行传输。vxlan header会包括一个24位的ID(称为VNI),含义类似于VLAN id或者上面提到的GRE的tunnel id。在上面GRE的例子中,是通过路由器来进行GRE协议的封装和解封的,在VXLAN中这类封装和解封的组件有个专有的名字叫做VTEP。相比起VLAN来说,好处在于其突破了VLAN只有4000+子网的限制,同时架设在UDP协议上后其扩展性提高了不少(因为UDP是高层协议,屏蔽了底层的差异,换句话说屏蔽了二层的差异)。
关于VXLAN,推荐大家看下下面的两个连接:http://www.borgcube.com/blogs/2011/11/vxlan-primer-part-1/, http://www.borgcube.com/blogs/2012/03/vxlan-primer-part-2-lets-get-physical/。
表面上看VXLAN和GRE区别不大,只是对delivery协议做了限定,使用UDP。但是实际上在协议的交互动作上面还是有区别的。和上面的例子一样,假如主机A和主机B想通信,那么A的报文会的被VTEP封装,然后发往连接B的VTEP。在上面的例子中类似于VTEP的角色是由路由器来充当的,而且路由器的两端的地址是配置好的,所以RA知道RB的地址,直接将报文发给RB即可。但是在VXLAN中,A的VTEP并不知道B的VTEP在哪,所以需要一个发现的过程。如何发现呢?VXLAN要求每个VNI都关联一个组播地址。所以对于一次ARP请求,A的VTEP会的发送一个组播IGMP报文给所有同在这个网络组中的其他VTEP。所有的订阅了这个组播地址的VTEP会的收到这个报文,学习发送端的A的MAC和VTEP地址用于以后使用,同时VTEP会的将报文解析后比较VNI,发送给同VNI的主机。当某个主机B的IP和ARP中的一样时,其会的发送ARP应答报文,应答报文通过B的VTEP按照类似的流程发送给A,但是由于B的VTEP已经学习到了A的MAC地址,因此B的VTEP直接就可以发送给A的VTEP,而不需要再走一遍通过IGMP的组播过程了。
从这个例子可以看出,VXLAN屏蔽了UDP的存在,上层基本上不感知这层封装。同时VXLAN避免了GRE的点对点必须有连接的缺点。由于需要IGMP,对于物理交换机和路由器需要做一些配置,这点在GRE是不需要的。
在openstack中,VXLAN也可以和GRE一样替代VLAN来实现VM之间的通信。具体的可以参考http://www.opencloudblog.com/?p=300。或许在openstack中并不需要组播来学习VTEP地址,计算节点和网络节点的流表或许是从持久化的数据库中获取并建立的(也可能走openflow协议,有一个外在的SDN controller),这点小秦不是很确定,之后有时间看下源码确定下。另外对openstack网络感兴趣的推荐看下https://www.rdoproject.org/Networking_in_too_much_detail这个文章,也是不错的。
3.总结
GRE和VXLAN都是用于封装其它协议的两种协议,记得当初网络课还是通信课的时候老师说道计算机网络协议有三要素:语义、语法和时序。这两个协议区别最大的或许就是时序了。对于VXLAN来说,为了避免GRE的连接个数,其需要做组播。但是在如今通过openflow协议,或许从某个SDN控制器就可以得到相关的流表,从而避免组播时的开销。因此个人觉得实际生产中,VXLAN可能用到的会多些。