VLAN aware VMs
有时也叫做VM trunk ports
,主要是让虚拟机收发的vlan tagged
报文, 能够被虚拟网络所识别和处理。
VLAN aware VMs应用场景
该功能的主要使用场景有:
-
有些应用程序, 需要连接很多neutron网络。传统的方法是虚拟机上连接很多neutron网络, 但是这样做显然不好维护, 并不实用。比较好的办法是在虚拟机上使用1个VIF网卡接口,创建多个VLAN接口, 并通过收发不同VLAN报文来区分不同网络。
-
云计算网络中的负载较为动态, 有时需要动态的增删虚拟机上的网络接口。通过增删vlan相对来说更加简单和快捷。
-
通过配置VLAN, 可以不用增删VIF, 把VM从一个网络挪到另一个网络
-
一个VM可能跑多个容器, 通过给容器分配VLAN来连接到不同的neutron网络, 比给每个容器分配一个VM的VIF, 更加有效和更好的可扩展性。
-
有些老的应用程序以及部分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。
- 创建网络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
- 在net0上创建trunkparentport, 在net1上创建subport1, 在net2上创建subport2
# openstack port create --network net0 trunkparent
# openstack port create --network net1 subport1
# openstack port create --network net2 subport2
- 创建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 |
+-----------------+-----------------------------------------------------------------------------------------------+
- 检查当前创建的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 |
+-----------------+-----------------------------------------------------------------------------------------------+
- 查询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 |
...
+-----------------------+--------------------------------------+
- 创建虚拟机, 网卡设置为parent_port:trunkparent
# openstack server create --image 5c43aefd-7256-4fd8-b641-72a5a0945666 --flavor 3--nic port-id=trunkparent trunk-vm1
虚拟机创建成功后, parent_port会绑定成功, 底层trunk设备也会被创建。
- 虚拟机中配置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
- 通过执行对接口eth0.1和eth0.2上执行dhclient, 可以使eth0.1, eth0.2得到对应虚拟网络的ip地址。
VM# sudo dhclient eth0.1
VM# sudo dhclient eth0.2
- 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接口