VLAN Trunk in OpenStack Neutron and SDN

2020-07-02 00:00:00 数据 网卡 网络 端口 交换机

Neutron 系列文章 Neutron Topic Tree:

好久没有说OpenStack相关的内容了,这次说说OpenStack对于VLAN Trunk的支持。OpenStack对VLAN Trunk的支持具体是什么?虽然OpenStack与容器,物理主机也做了集成,但是OpenStack主要的应用还是虚机管理,而现代的操作系统,不论是Linux还是Windows,都支持将网卡配置成Trunk port。OpenStack对VLAN Trunk的支持就是指对OpenStack所管理的虚机的Trunk port,提供网络支持。

什么是主机的Trunk port?一般来说VLAN只是对交换机可知,主机不感知VLAN,也就是主机网卡发送出来的数据是不带VLAN Tag的。当主机将网卡配置成Trunk port,会在主机的Trunk port上添加多个带有不同VLAN ID的子网卡。通过子网卡发送的数据,会打上VLAN Tag,被发送出去。由于主机发送的网络数据有了变化(带上了VLAN Tag),对主机连接的网络提出了新的要求。另一方面,由于带了不同的VLAN Tag,子网卡可以认为连接在VLAN Tag标识的网络中。这样,不用实际增减主机的网卡,只需要为主机创建带VLAN ID的子网卡,就可以将主机添加到新的VLAN网络中。

主机的Trunk port有什么用?一个应用是在NFV(Network Function Virtualization)场景下。在NFV场景下,一个VNF(Virtual Networking Function)可能需要同时连接多个网络。当然简单是一个网络对应一块网卡,但如果网络数量巨大,网卡数量也巨大,一方面这不现实。另一方面,连接的多个网络也是动态增减的,如果每次增减都插拔VNF的网卡,那明显也是不能接受的。如果用Trunk port,当需要动态连接多个网络时,只需要动态的创建/删除相应的子网卡即可。

本文将先介绍一下VLAN Trunk的基本概念,之后介绍OpenStack Neutron和OpenFlow based SDN是如何为Trunk port提供网络支持。

VLAN

一个个说,先简单说一下VLAN。VLAN(Virtual LAN)由IEEE802.1Q定义。要讲VLAN要先从广播域(Broadcast Domain)开始说起。在下图中,假设PC1-5在一个广播域中,当PC1发出广播帧,例如ARP,DHCP,由于目的MAC地址是广播地址,同一个广播域内的所有设备都将收到相应的广播帧。如果PC1-5在一个子网中,那这本身也无可厚非,因为这正是ARP,DHCP的工作原理。


如果PC1-5不在一个子网中呢?例如上图中,PC1在橙色子网,PC2-3在绿色子网,PC4-5在红色子网。理论上,PC1发出的广播帧只应该在橙色子网内传播。但实际上,是由于PC1-5在一个广播域中,PC2-5还是会收到PC1的广播帧。虽然PC2-5会直接丢弃这个广播帧,但是这里存在安全问题和性能问题。首先,PC2-5虽然不会处理PC1发来的广播帧,但是数据还是发送过来了,通过侦听和伪装,可以达到劫持的目的,例如ARP spoof。其次,广播帧本来不用在整个网络传播,但现在就整个网络传播,这样占用了交换机的带宽,在大规模网络中,尤其会影响网络性能。解决这些问题的方法就是使用VLAN。

VLAN是一组网络端口的集合。实现了VLAN的交换机,会将二层的单播,组播,广播都局限在一个VLAN中,这样不同的VLAN中的主机,就不会收到其他VLAN中主机的数据。并且,只有交换机能看到VLAN,连接交换机的其他设备,例如Server,Router,都感觉不到VLAN的存在。将不同的子网规划在不同的VLAN当中,可以实现子网的隔离。即使所有的设备都在一个交换机上,不同的VLAN之间通信也需要通过Router

VLAN Trunk

VLAN的划分并非只能在一个交换机上,多个交换机可以共同组成VLAN。那多个交换机上的VLAN是怎么连接到一起的?有两种方法。

种方法是把每个交换机上的每个VLAN都连在一起。如下图所示:

图中有两个交换机,各有两个VLAN,为了让VLAN能正常工作,将VLAN1和VLAN2分别连接起来。如果是两个交换机,两个VLAN还好,如果是100个VLAN,那么这里需要有100条线路,200个交换机端口。这么连接可以吗?可以,只要有钱,因为这里的线路和交换机端口都是钱。这种方法,运维和成本支出比较大,不实用。

第二种方法是通过VLAN Trunk连接交换机。VLAN Trunk是一种网络设备间的point-to-point的连接。一条VLAN Trunk线路可以同时传输多个甚至所有的VLAN数据。


由于VLAN Trunk可以传输多个VLAN数据,Ethernet Frame在VLAN Trunk上传输时,需要带上802.1Q定义的VLAN tag,这样交换机才能区分Ethernet Frame到底属于哪个VLAN。VLAN Trunk的具体使用过程如下:

  • 当左侧服务器想要访问右侧服务器,左侧服务器将Ethernet Frame发送到左侧交换机
  • 左侧交换机本地没有目的MAC对应的转发信息,因此Ethernet Frame发送到了左侧交换机的VLAN Trunk port
  • 由于这是来自VLAN100的Ethernet Frame,交换机给Ethernet Frame打上VLAN 100的Tag,从自己的VLAN Trunk port发出,发送到右侧交换机的VLAN Trunk port
  • 右侧的VLAN Trunk port收到VLAN 100的Ethernet Frame,去除VLAN Tag,再在本地的VLAN 100端口中查找MAC转发
  • 找到对应的MAC/端口记录,终Ethernet Frame发送到右侧的服务器

如果是VLAN200的数据,过程一样,只是VLAN Tag从100变成了200。

通过VLAN Trunk port,两个交换机之间不论需要连接多少个VLAN,只需要一个VLAN Trunk连接(一对Trunk port)即可。

如果有多个交换机需要连接,通常会用另外一个交换机连接它们,如下图所示,交换机之间都通过Trunk port相连。


红色框内的交换机的4个port都是Trunk port,任意的VLAN 标签的Ethernet Frame都可以在这个交换机内传输。可以把红色框内看成是一个Trunk network,一个Trunk network可以传输带VLAN标签的Ethernet Frame。虽然图中只有一个交换机,但是Trunk network可以更加复杂,由多个交换机组成。多个VLAN的网络数据共同在Trunk network上传输,通过VLAN Tag来识别VLAN。

如果把上图中下面四个交换机换成主机(虚机),那就是OpenStack VLAN Trunk希望支持的场景。为了支持这个场景,需要为虚机提供一个Trunk Network。

Linux VLAN Trunk

Windows也支持Trunk port,与Linux类似,这里只说明Linux系统下的Trunk port。

Linux系统可以通过内核模块8021q支持VLAN Trunk。这里有什么不一样?在一般情况下,主机是不感知VLAN Tag的,也就是说主机发送的网络数据都是不带VLAN Tag,所有VLAN Tag操作都是由交换机完成。但是实际上交换机也不知道自己连接的是什么,所以,如果在主机完成VLAN Tag的操作,再发送到交换机,交换机也能处理。基于这个前提,Linux能够将一块以太网卡配置成一个支持802.1q的Trunk port,使得这块网卡跟前面描述的交换机上的Trunk port一样,能够收发多个VLAN的网络数据包。并且通过配置Linux主机的子网卡,可以使得Linux主机内部完成VLAN Tag的操作(打上VLAN Tag,去除VLAN Tag)。有不止一种方法可以配置Linux VLAN Trunk,这里以ip命令为例,为eth0添加名为eth0.102的子网卡,其VLAN ID为102。

$ sudo ip link add link eth0 name eth0.102 type vlan id 102

相关文章