“VLAN aware VMs”有时也叫做”VM trunk ports”, 主要是让虚拟机收发的vlan tagged报文, 能够被虚拟网络所识别和处理。

VLAN aware VMs应用场景

该功能的主要使用场景有:

  1. 有些应用程序, 需要连接很多neutron网络。传统的方法是虚拟机上连接很多neutron网络, 但是这样做显然不好维护, 并不实用。比较好的办法是在虚拟机上使用1个VIF网卡接口,创建多个VLAN接口, 并通过收发不同VLAN报文来区分不同网络。

  2. 云计算网络中的负载较为动态, 有时需要动态的增删虚拟机上的网络接口。通过增删vlan相对来说更加简单和快捷。

  3. 通过配置VLAN, 可以不用增删VIF, 把VM从一个网络挪到另一个网络

  4. 一个VM可能跑多个容器, 通过给容器分配VLAN来连接到不同的neutron网络, 比给每个容器分配一个VM的VIF, 更加有效和更好的可扩展性。

  5. 有些老的应用程序以及部分NFV, 要求能够通过VLAN来连接网络, 本功能能够满足这个需求。

VLAN aware VMs配置和使用方法

需要在网络节点的neutron.conf里配置service_plugins为: “trunk”。

service_plugins=...., trunk

我们将要创建一个虚拟机trunk-vm1, 虚拟机上希望有3个网络接口: eth0, VLAN接口: eth0.1, VLAN接口: eth0.2。 其中:

nova创建虚拟机时创建的eth0, 主要用来收发VLANuntagged报文, 所属net0网络(子网为:10.0.4.0/24)。 对应的neutron port被称为parent_port, 取名为: trunkparent。

手动在VM里创建的VLAN接口: eth0.1, 用来收发VLAN tag=1的报文, 所属net1网络(子网为: 10.0.5.0/24)。对应的neutron port被称为subport, 取名为: subport1。

手动在VM里创建的VLAN接口: eth0.2, 用来收发VLAN tag=2的报文, 所属net2网络(子网为: 10.0.6.0/24)。对应的neutron port被称为subport, 取名为: subport2。

  1. 创建网络net0, net1, net2, 以及对应的子网: subnet0 (10.0.4.0/24),subnet1 (10.0.5.0/24), subnet2 (10.0.6.0/24)
# OpenStack network create net0
# openstack network create net1
# openstack network create net2
# openstack subnet create --network net0 --subnet-range 10.0.4.0/24 subnet0
# openstack subnet create --network net1 --subnet-range 10.0.5.0/24 subnet1
# openstack subnet create --network net2 --subnet-range 10.0.6.0/24 subnet2
  1. 在net0上创建trunkparentport, 在net1上创建subport1, 在net2上创建subport2
# openstack port create --network net0 trunkparent
# openstack port create --network net1 subport1
# openstack port create --network net2 subport2
  1. 创建mytrunk, 并设置parent-port为: trunkparent。subport 1的vlan_id=1。 subport2的vlan_id=2。
# openstack network trunk create --parent-port trunkparent \
 --subport port=subport1,segmentation-type=vlan,segmentation-id=1 \
 --subport port=subport2,segmentation-type=vlan,segmentation-id=2 mytrunk
 
+-----------------+-----------------------------------------------------------------------------------------------+
| Field           | Value                                                                                         |
+-----------------+-----------------------------------------------------------------------------------------------+
| admin_state_up  | UP                                                                                            |
| created_at      | 2016-11-15T01:58:13Z                                                                          |
| description     |                                                                                               |
| id              | a5f0be95-67bd-4dea-b321-b4cad753b91d                                                          |
| name            | mytrunk                                                                                       |
| port_id         | b7d4c968-afb2-4709-9f64-0e7853209673                                                          |
| revision_number | 1                                                                                             |
| status          | DOWN                                                                                          |
| sub_ports       | port_id='c7dd9ac2-730a-4476-b93f-08a6f31367d4', segmentation_id='1', segmentation_type='vlan' |
|                 | port_id='3ba8b2d5-fe03-4d2a-bcd7-abeee2121739', segmentation_id='2', segmentation_type='vlan' |
| tenant_id       | f332909670c841abb78c2e30e8c50c68                                                              |
| updated_at      | 2016-11-15T01:58:13Z                                                                          |
+-----------------+-----------------------------------------------------------------------------------------------+
  1. 检查当前创建的trunk 以及相关subport信息
# openstack network trunk list
+--------------------------------------+---------+--------------------------------------+-------------+
| ID                                   | Name    | Parent Port                          | Description |
+--------------------------------------+---------+--------------------------------------+-------------+
| a5f0be95-67bd-4dea-b321-b4cad753b91d | mytrunk | b7d4c968-afb2-4709-9f64-0e7853209673 |             |
+--------------------------------------+---------+--------------------------------------+-------------+
 
# openstack network trunk show mytrunk
+-----------------+-----------------------------------------------------------------------------------------------+
| Field           | Value                                                                                         |
+-----------------+-----------------------------------------------------------------------------------------------+
| admin_state_up  | UP                                                                                            |
| created_at      | 2016-11-15T01:58:13Z                                                                          |
| description     |                                                                                               |
| id              | a5f0be95-67bd-4dea-b321-b4cad753b91d                                                          |
| name            | mytrunk                                                                                       |
| port_id         | b7d4c968-afb2-4709-9f64-0e7853209673                                                          |
| revision_number | 1                                                                                             |
| status          | DOWN                                                                                          |
| sub_ports       | port_id='c7dd9ac2-730a-4476-b93f-08a6f31367d4', segmentation_id='1', segmentation_type='vlan' |
|                 | port_id='3ba8b2d5-fe03-4d2a-bcd7-abeee2121739', segmentation_id='2', segmentation_type='vlan' |
| tenant_id       | f332909670c841abb78c2e30e8c50c68                                                              |
| updated_at      | 2016-11-15T01:58:13Z                                                                          |
+-----------------+-----------------------------------------------------------------------------------------------+
  1. 查询subport1的mac地址 (mac地址为: fa:16:3e:cc:b9:27), 以及subport2的mac地址(mac地址为: fa:16:3e:25:d2:c9)
# openstack port show subport1
+-----------------------+--------------------------------------+
| Field                 | Value                                |
+-----------------------+--------------------------------------+
| id                    | c7dd9ac2-730a-4476-b93f-08a6f31367d4 |
| mac_address           | fa:16:3e:cc:b9:27                    |
| name                  | subport1                             |
...
+-----------------------+--------------------------------------+
 
# openstack port show subport2
+-----------------------+--------------------------------------+
| Field                 | Value                                |
+-----------------------+--------------------------------------+
| id                    | 3ba8b2d5-fe03-4d2a-bcd7-abeee2121739 |
| mac_address           | fa:16:3e:25:d2:c9                    |
| name                  | subport2                             |
...
+-----------------------+--------------------------------------+
  1. 创建虚拟机, 网卡设置为parent_port:trunkparent
# openstack server create --image 5c43aefd-7256-4fd8-b641-72a5a0945666 --flavor 3--nic port-id=trunkparent trunk-vm1

虚拟机创建成功后, parent_port会绑定成功, 底层trunk设备也会被创建。

  1. 虚拟机中配置vlan接口, 并根据subport1/subport2的mac地址, 配置VLAN接口。

subport1的vlan id为1, mac地址为: fa:16:3e:cc:b9:27

subport2的vlan id为2, mac地址为: fa:16:3e:25:d2:c9

VM# sudo ip link add link eth0 eth0.1 address fa:16:3e:cc:b9:27 broadcast ff:ff:ff:ff:ff:ff type vlan id 1
VM# sudo ip link add link eth0 eth0.2 address fa:16:3e:25:d2:c9 broadcast ff:ff:ff:ff:ff:ff type vlan id 2
 
VM# sudo ip link set eth0.1 up
VM# sudo ip link set eth0.2 up
  1. 通过执行对接口eth0.1和eth0.2上执行dhclient, 可以使eth0.1, eth0.2得到对应虚拟网络的ip地址。
VM# sudo dhclient eth0.1
VM# sudo dhclient eth0.2

  1. VM中通过eth0.1 ping dhcp端口来验证vlan tags。
VM# ping -I eth0.1 10.0.5.2

qvo上抓包, 能够抓到报文带vlan id=1:

# tcpdump -en -i qvob7d4c968-af
tcpdump: WARNING: qvob7d4c968-af: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on qvob7d4c968-af, link-type EN10MB (Ethernet), capture size 65535 bytes
17:38:56.411075 fa:16:3e:cc:b9:27 > fa:16:3e:cc:4b:83, ethertype 802.1Q (0x8100), length 102: vlan 1, p 0, ethertype IPv4, 10.0.5.7 > 10.0.5.2: ICMP echo request, id 15784, seq 180, length 64
17:38:56.411123 fa:16:3e:cc:4b:83 > fa:16:3e:cc:b9:27, ethertype 802.1Q (0x8100), length 102: vlan 1, p 0, ethertype IPv4, 10.0.5.2 > 10.0.5.7: ICMP echo reply, id 15784, seq 180, length 64
17:38:57.413020 fa:16:3e:cc:b9:27 > fa:16:3e:cc:4b:83, ethertype 802.1Q (0x8100), length 102: vlan 1, p 0, ethertype IPv4, 10.0.5.7 > 10.0.5.2: ICMP echo request, id 15784, seq 181, length 64

VLAN aware VMs底层原理

在使用VLAN aware VMs之前, 传统Openstack VM vif和neutron端口, 网络之间的关系如下,虚拟机(openstack instance)通过eth0/eth1/eth2这类vNIC虚拟网卡和计算节点上的port相联, port再添加到不同虚拟网络中去进行2层互联。

传统Openstack VM vif和neutron端口、网络之间的关系

在使用了vlan-aware-vms功能后, 虚拟机中的网络接口将会配成vlan接口方式, 并通过1个vNIC连接到计算节点的parent_port上, parent_port将把不同tagged的报文发送给不同的vlan subport, 并和虚拟网络相连接。其中parent_port可用来收发untagged VLAN报文, 而subports(child_ports)用来收发VLAN tagged的报文。 如下图, 这样可以省去在VM上添加多个网络端口的动作:

使用了vlan-aware-vms功能后, VM vif和neutron端口、网络之间的关系

目前, openstack newton中实现了ovs和linuxbridge 两种trunk的驱动实现方式, 我们看一下OVS的驱动实现原理, linuxbridge实现方式类似。

OVS trunk驱动实现原理:

在使用trunk之前, 我们的ovs 2层网络和报文走向是这样子的(左图):

VM中eth0 -> tap -> qbr -> qvb-> qvo -> br-int -> br-tun ...

在使用trunk之后, qvo(trunkport)挂到了新的ovs bridge:tbr- 上, 我们的ovs 2层网络和报文走向变成了这样子(右图)。

eth0(trunk port, 不带vlan tag), 通过tbr-上的ovs port: tpt (不设置vlan tag), 和tpi (为patch-port对)相连, tpi最终连接到了br-int上。

eth0.1(subport, 带vlan:1), 通过tbr-上的ovs port: spi(配置vlan tag: 1), 和spi (为patch-port对)相连, spi最终连接到了br-int上。

eth0.2同上。

其中ovs bridge: tbr-XXX中下的流表为: 匹配所有报文,action=NORMAL, 即传统的2层bridge模式。

qvo等ovs port默认为trunk port(可收发带vlan报文, 并且出去后不剥掉vlan tag), 而tpt/tpi为access port(一般进来和出去为untagged报文, 进到网桥/交换机后按照端口上的tag配置进行vlan划分和处理)。

缩写解释:

tbr: trunk bridge
tpt: trunk port trunk-end (即和trunk bridge连接的端口)
tpi: trunk port integration-end(即和br-int连接的端口)
spt: subport trunk-end (即和trunk bridge连接的端口)
spi: subport integration end (即和br-int连接的端口) 

使用ovs trunk前后, 底层设备和报文走向

Linux trunk驱动实现原理:

通过VM的tap口上创建vlan子接口实现。

例如: parent_port为tap9965461c-91, subport1为: tapca4c78e2-66@tap9965461c-91,subport2为: tapbf54d831-fe@tap9965461c-91。

# ip -d link show | grep 9965 -C 6
39: tap9965461c-91: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65486 qdisc pfifo_fast master brq7412a74a-7b state UNKNOWN mode DEFAULT group default qlen 500
    link/ether fe:16:3e:90:7a:ca brd ff:ff:ff:ff:ff:ff promiscuity 2
    tun
40: tapbf54d831-fe@tap9965461c-91: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65486 qdisc noqueue state UP mode DEFAULT group default
    link/ether fa:16:3e:d5:55:a5 brd ff:ff:ff:ff:ff:ff promiscuity 0
    vlan protocol 802.1Q id 2 <REORDER_HDR>
41: tapca4c78e2-66@tap9965461c-91: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65486 qdisc noqueue state UP mode DEFAULT group default
    link/ether fa:16:3e:b5:5b:a1 brd ff:ff:ff:ff:ff:ff promiscuity 0
    vlan protocol 802.1Q id 1 <REORDER_HDR>

parent_port所属网络为net0 (uuid: 7412a74a-7b04-4c45-9491-b8929cf1fcf4), 则其对应的linux bridge为: brq7412a74a-7b

# brctl show brq7412a74a-7b
bridge name                bridge id           STP enabled              interfaces
brq7412a74a-7b      8000.5a63a569d91c                 no              tap8f6a9f8b-8d
                                                                    tap9965461c-91
                                                                          vxlan-100

使用linuxbridge trunk前后, 底层设备和报文走向

代码:

trunk驱动支持ovs和linux bridge, 代码主要在neutron/services/trunk目录下:

trunk驱动

CLI命令行和API接口

转载自http://blog.csdn.net/bc_vnetwork/article/details/53927687。

完毕。