|
前言 本文先介绍一下VLAN Trunk的基本概念,以及OpenStack Neutron和OpenFlow based SDN是如何为Trunk port提供网络支持。OpenStack对VLAN Trunk的支持具体是什么?虽然OpenStack与容器,物理主机也做了集成,但是OpenStack最主要的应用还是虚机管理,而现代的操作系统,不论是Linux还是Windows,都支持将网卡配置成Trunk port。OpenStack对VLAN Trunk的支持就是指对OpenStack所管理的虚机的Trunk port,提供网络支持。
0 A9 B* C/ T3 R* O6 L ( v Q: o: [" O% J) t& [6 S& w
主机的Trunk port是指在主机的一块网卡上添加多个带有不同VLAN ID的子网卡。通过子网卡发送的数据,打上VLAN Tag,被发送出去。由于带了不同的VLAN Tag,子网卡可以认为连接在VLAN Tag标识的网络中。这样,不用增减主机的网卡,就可以将主机添加到新的网络中。更主要的是,这种方式的网络添加是动态的。 主机的Trunk port有什么用?一个应用是在NFV场景下,一个VNF(Virtual Networking Function)可能需要同时连接多个网络。当然最简单是一个网络对应一块网卡,但如果网络数量巨大,网卡数量也巨大,一方面这不现实。另一方面,连接的多个网络也是动态增减的,如果每次增减都插拔VNF的网卡,明显也是不能接受的。如果用Trunk port,当需要动态连接多个网络时,只需要动态的创建/删除相应的子网卡即可。0 p1 R# u, w6 l: T0 C$ h
VLAN Trunk在NFV中的应用 一、VLAN Trunk介绍1.1 VLAN简介VLAN(Virtual LAN)由IEEE802.1Q定义。要讲VLAN要先从广播域(Broadcast Domain)开始说起。在下图中,假设PC1-5在一个广播域中,当PC1发出广播帧,例如ARP,DHCP,由于目的MAC地址是广播地址,同一个广播域内的所有设备都将收到相应的广播帧。如果PC1-5在一个子网中,那这本身也无可厚非,因为这正是ARP,DHCP的工作原理。
' n" H7 T6 ]. K0 y! d0 o5 X8 M0 @6 {! T 3 s( B' E1 X% j6 j# X
如果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。8 v) x! G4 [ n. A; [" z" A
 1.2 VLAN Trunk简介VLAN的划分并非只能在一个交换机上,多个交换机可以共同组成VLAN。那多个交换机上的VLAN是怎么连接到一起的?有两种方法。 第一种方法是把每个交换机上的每个VLAN都连在一起。如下图所示:8 R; t* y" ?, \
6 d2 w4 \5 ~$ [
图中有两个交换机,各有两个VLAN,为了让VLAN能正常工作,将VLAN1和VLAN2分别连接起来。如果是两个交换机,两个VLAN还好,如果是100个VLAN,那么这里需要有100条线路,200个交换机端口。这么连接可以吗?可以,只要有钱,因为这里的线路和交换机端口都是钱。这种方法,运维和成本支出比较大,不实用。 第二种方法是通过VLAN Trunk连接交换机。VLAN Trunk是一种网络设备间的point-to-point的连接。一条VLAN Trunk线路可以同时传输多个甚至所有的VLAN数据。
- p6 a8 F' f$ G3 ^, l, y$ Q3 f ; P. q2 n8 y9 Z+ C6 Y
由于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发送到最右侧的服务器
: L8 j8 }5 w8 Q0 W& k2 ~' C
如果是VLAN200的数据,过程一样,只是VLAN Tag从100变成了200。 通过VLAN Trunk port,两个交换机之间不论需要连接多少个VLAN,只需要一个VLAN Trunk连接(一对Trunk port)即可。 如果有多个交换机需要连接,通常会用另外一个交换机连接它们,如下图所示,交换机之间都通过Trunk port相连。7 r2 {: ]7 t! _' Q6 v

0 p; i. k- u6 V$ ~2 L/ m" _ o红色框内的交换机的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。 1.3 Linux VLAN TrunkWindows也支持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。 [color=rgb(51, 51, 51) !important]
2 {/ U; U2 v' I, z% v% L- s" Y. Q1 h
; F( q% k! m B. Z% ]' N% T$ l: |/ o/ G& a% _2 H' P4 [4 ?
) X# J8 W4 `+ _- P2 O9 e6 K2 k
1 ^, I$ z8 m2 E* w% x. H2 p
a% [+ h, l1 A9 U4 K `, n0 L, V. t4 n) w( ?8 c" K1 Z5 b
+ x4 u7 N& f; ?& O7 R8 }/ X
' q7 r1 W, f9 h9 b7 f9 H2 r- Y. O
+ x6 [: F; u# g( |9 X; M, L[color=rgb(153, 153, 153) !important]Java
1 ^# \, ~3 C8 H! R( Y ) k7 y1 g9 B* t9 d4 o# M
) G8 c; z) ~: ], Z5 J. e
, S3 q2 x/ b! L | [color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]sudo [color=rgb(0, 78, 208) !important]ip [color=rgb(0, 78, 208) !important]link [color=rgb(0, 78, 208) !important]add [color=rgb(0, 78, 208) !important]link [color=rgb(0, 78, 208) !important]eth0 [color=rgb(0, 78, 208) !important]name [color=rgb(0, 45, 122) !important]eth0[color=rgb(51, 51, 51) !important].[color=rgb(206, 0, 0) !important]102[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]type [color=rgb(0, 78, 208) !important]vlan [color=rgb(0, 0, 0) !important]id[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]102 7 u& m/ N% M' f5 e1 R* D; ?. L
; ~( u. s% `7 T |
6 E2 { ]; r' `1 }. g8 T
g8 g. m7 U, V7 o8 j
就这么简单,之后可以看到一个新的网卡在系统的网卡列表中。Linux VLAN Trunk工作过程如下: - 外界传入的带VLAN Tag 102的包,到达了eth0,VLAN Tag 102被去除,然后不带VLAN Tag的Ethernet Frame被重新发往操作系统网络栈,再发送到eth0.102。
- 从eth0.102发送出来的帧,被打上VLAN102的标签,再从eth0传出。+ b& |& Y g( O( D i8 J
应用层面,收发的还是不带VLAN Tag的数据,只是经过Linux VLAN Trunk的处理,进出主机的的数据是带VLAN Tag的数据。 由于eth0配置成了VLAN Trunk port。为了让带有VLAN标签的Ethernet Frame能够在网络上传输。eth0所接入的网络必须是一个Trunk network。否则无法传输任意带VLAN Tag的Ethernet Frame。也就是说,需要将主机的Trunk port连接到红框内。接下来我们看看OpenStack是怎么做的。 二、OpenStack Neutron对VLAN Trunk的支持Neutron VLAN Transparency这是OpenStack Kilo版本的特性,由VLAN trunking networks for NFV定义。这个特性为Neutron network增加一个属性“vlan-transparent”,当vlan-transparent为True时,表明在这个Neutron network是一个Trunk network。在这个Neutron network中的虚机可以使用Linux VLAN Trunk功能。接下来看看Neutron为了实现这个特性做了什么? 什么也没做!Neutron只是提供了这么一个属性,具体的实现交给底层的SDN。如果SDN不支持VLAN Transparency,可以在ML2中告知Neutron。那么用户在创建Neutron network时,如果指定了vlan-transparent=True,Neutron会返回“Backend does not support VLAN Transparency.”。例如OpenVSwitch,就不支持VLAN Transparency。 所以,并非所有的SDN都支持这个功能,就算实现了,每种SDN的实现方式不一样。不过本质上,都是将SDN控制的vSwitch配置成Trunk模式。需要注意的是,vSwitch最终还是要连接到Physical Switch,所以Physical Switch相应的端口也需要配置成Trunk port。 先来看看VLAN Transparency的问题, - 不支持OpenVSwitch
- 要求Physical Switch也配置相应的Trunk port; p3 m: J6 b, E' _' g6 j
VLAN aware VMs在支持相同功能的前提下,解决了上面两个问题。首先看看如何使用VLAN aware VMs这个功能。Neutron VLAN aware VMs是OpenStack Newton版本的特性,由VLAN aware VMs定义。VLAN aware VMs和VLAN Transparency说的其实是一件事情,就是如何传递VM发出来的带VLAN Tag的帧。 2.1 实验步骤我用的是最新代码(Pike 2017-08-08)配合OpenVSwitch完成下面的操作。要使能VLAN aware VMs,只需要在/etc/neutron/neutron.conf中,在service_plugins后面加上trunk。 首先创建Trunk port所在的网络和VLAN子网卡所在的网络。 [color=rgb(51, 51, 51) !important]
( W) c3 A4 V6 P$ u 0 F3 e% H& O6 R
. W. B- ]- x3 w- T3 `- t
" N0 B; U8 h! }: t+ ]4 ~
& r3 b2 B' V& X- c' z+ T3 {
( x6 ]8 T0 c: p# o; @
. T! e2 O. m5 ]6 g 6 j. b( N- v. m* A4 D1 z
, W1 T$ N3 N' { % n/ U/ d, ?: c# y4 l2 P! x' I+ Y
[color=rgb(153, 153, 153) !important]Java ( v5 |! H- f# c9 Z& [0 R" D
8 `$ v& \/ [5 x; ?4 {# I3 x9 V1 K. d. S; c y5 {1 l" s1 k3 t0 z
1
& G8 ]: ^; q7 x* C I: ^& d( P[color=rgb(49, 124, 197) !important]2
0 g, a" d% z l5 v6 b3 T" M+ a3
7 t# t- V! G- r# X2 \; a[color=rgb(49, 124, 197) !important]4
2 s6 M( O9 {% T/ o! S
( s3 x# _1 [- c. g- J# U8 n# ~ | [color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]openstack [color=rgb(0, 78, 208) !important]network [color=rgb(0, 78, 208) !important]create [color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 0, 0) !important]net
4 T7 z+ @- D$ w0 r& C[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]openstack [color=rgb(0, 78, 208) !important]subnet [color=rgb(0, 78, 208) !important]create [color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]subnet[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 78, 208) !important]network [color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]net[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 45, 122) !important]subnet[color=rgb(0, 111, 224) !important]-[color=rgb(0, 0, 0) !important]range[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]20.0.0.0[color=rgb(0, 111, 224) !important]/[color=rgb(206, 0, 0) !important]24 3 k: |: j) }( B
[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]openstack [color=rgb(0, 78, 208) !important]network [color=rgb(0, 78, 208) !important]create [color=rgb(0, 45, 122) !important]sub[color=rgb(0, 111, 224) !important]-[color=rgb(0, 0, 0) !important]net
; g4 b2 z; { E# K[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]openstack [color=rgb(0, 78, 208) !important]subnet [color=rgb(0, 78, 208) !important]create [color=rgb(0, 45, 122) !important]sub[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]subnet[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 78, 208) !important]network [color=rgb(0, 45, 122) !important]sub[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]net[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 45, 122) !important]subnet[color=rgb(0, 111, 224) !important]-[color=rgb(0, 0, 0) !important]range[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.0[color=rgb(0, 111, 224) !important]/[color=rgb(206, 0, 0) !important]24 + m: S# t' Y8 {1 g% _1 _9 j
1 Y& b( E D: w+ e5 E/ D/ R
|
! _* E- c* d4 u1 c& G
5 p; g& B: g9 ?
注意这里我并没有指定网络的类型,网络可以不用是VLAN的,像在我的环境中,网络就是VXLAN类型。为什么会这样?在后面会说。 接下来创建Trunk port和subport。 [color=rgb(51, 51, 51) !important]
1 Y ]( l, T3 a7 {! X$ R 6 p6 G9 H8 {% F Z
" `" U( ?' Y( ]( k ( H. k9 L2 U8 s0 I5 w
' v y& G* H8 Z
; ]! K4 B6 ~9 O1 ~, c* f* l) }+ h, o' T& G( M. j
( H$ E F. J% R- L6 S9 ]
# O. @- @7 V R9 O" d+ Q9 |
! [, \+ k3 I5 d- }6 g[color=rgb(153, 153, 153) !important]Java
, y" v6 {/ g% Q Q. U- r1 j6 i 2 r- s, h' ?- e2 V( E+ L0 T I/ t6 i
6 A. u& T; T+ o" _1 / ?# `( z$ ?& f8 y/ k+ s: X8 e U
[color=rgb(49, 124, 197) !important]2
+ N7 U$ X! ]+ O4 I7 w% p: x# ~3 # B e H! p- u' C# @$ W- l
[color=rgb(49, 124, 197) !important]4 : j. ~9 K6 b; v( J
5 . u- G3 o9 y4 [1 G0 |$ c! {1 D4 O5 H
[color=rgb(49, 124, 197) !important]6
5 I2 r- b+ E7 P0 ]. r7
) V8 i' \+ m" T[color=rgb(49, 124, 197) !important]8
" u0 l& T- Z; ?' @9 `; l: W $ }% V. U. b% ~
| [color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]openstack [color=rgb(0, 78, 208) !important]port [color=rgb(0, 78, 208) !important]create [color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]port1[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 78, 208) !important]network [color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 0, 0) !important]net
5 k/ v; @+ P* P[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]openstack [color=rgb(0, 78, 208) !important]port [color=rgb(0, 78, 208) !important]create [color=rgb(0, 45, 122) !important]sub[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]port1[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 78, 208) !important]network [color=rgb(0, 45, 122) !important]sub[color=rgb(0, 111, 224) !important]-[color=rgb(0, 0, 0) !important]net
" h- Z& p3 ?6 ?% A; {[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]openstack [color=rgb(0, 78, 208) !important]network [color=rgb(0, 78, 208) !important]trunk [color=rgb(0, 78, 208) !important]create [color=rgb(0, 45, 122) !important]trunk1[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 78, 208) !important]port [color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 0, 0) !important]port1
. U& f1 O9 d: e[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]openstack [color=rgb(0, 78, 208) !important]network [color=rgb(0, 78, 208) !important]trunk [color=rgb(0, 78, 208) !important]set [color=rgb(0, 45, 122) !important]trunk1[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 78, 208) !important]subport [color=rgb(0, 45, 122) !important]port[color=rgb(0, 111, 224) !important]=[color=rgb(0, 45, 122) !important]sub[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]port1[color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]segmentation[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]type[color=rgb(0, 111, 224) !important]=[color=rgb(0, 45, 122) !important]vlan[color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]segmentation[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]id[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]102 % q% S8 W1 c$ ]! }; W/ l
[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]openstack [color=rgb(0, 78, 208) !important]port [color=rgb(0, 78, 208) !important]create [color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]port2[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 78, 208) !important]network [color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 0, 0) !important]net ; [; }( B: ?) {6 ]8 ?5 V. a M0 H1 x3 k
[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]openstack [color=rgb(0, 78, 208) !important]port [color=rgb(0, 78, 208) !important]create [color=rgb(0, 45, 122) !important]sub[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]port2[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 78, 208) !important]network [color=rgb(0, 45, 122) !important]sub[color=rgb(0, 111, 224) !important]-[color=rgb(0, 0, 0) !important]net 1 p: m% C- ~: k R7 q1 P$ v
[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]openstack [color=rgb(0, 78, 208) !important]network [color=rgb(0, 78, 208) !important]trunk [color=rgb(0, 78, 208) !important]create [color=rgb(0, 45, 122) !important]trunk2[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 78, 208) !important]port [color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 0, 0) !important]port2
8 _# T* q% z5 k: g' v. n, {3 l6 k[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]openstack [color=rgb(0, 78, 208) !important]network [color=rgb(0, 78, 208) !important]trunk [color=rgb(0, 78, 208) !important]set [color=rgb(0, 45, 122) !important]trunk2[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 78, 208) !important]subport [color=rgb(0, 45, 122) !important]port[color=rgb(0, 111, 224) !important]=[color=rgb(0, 45, 122) !important]sub[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]port2[color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]segmentation[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]type[color=rgb(0, 111, 224) !important]=[color=rgb(0, 45, 122) !important]vlan[color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]segmentation[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]id[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]102 ; Q' W r7 k1 b6 a2 [2 o! B; p& P
* w6 J% B: J2 B' J, {! K |
( M$ I# U% W6 h" j3 L7 I3 S
, A9 t" Z& {' o- h- S4 }, F这里创建了两组4个port,并用trunk模型将它们关联起来了。除此之外,还为Trunk中的subport指定了segmentation-type和segmentation-id。VLAN是目前OpenVSwitch支持的唯一的segmentation type(也是大多数SDN唯一支持的类型),segmentation id就是在虚机中创建subport时指定的VLAN ID。 接下来用parent port创建两个虚机。 [color=rgb(51, 51, 51) !important]
k% ^1 w/ S$ p3 P: Z- @1 U |
" @$ F- I/ I+ [: |6 z* x
- U, t2 E; D6 n4 ]% ^3 i
: N! u6 |% N# X. k9 j* M& o& n3 i3 C5 T
+ D' B+ `9 k+ B9 y. g' J5 x4 E1 x, `+ O% [7 q- V
4 v4 j) S7 G9 P6 Q
2 ]! N& u& F3 j6 A2 O6 T* C' e
" k" {8 X- y$ Z, s: G: D[color=rgb(153, 153, 153) !important]Java
( r% U: u, X: R
( E/ ^ w: W' p+ W! c5 W* {1 ]% O7 F5 d
1 ( P+ U* @ S1 k1 R$ B6 h! ]
[color=rgb(49, 124, 197) !important]2 $ g* q1 J4 v Q2 ]
) g) m0 ]6 a" W) u) r( m, v | [color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]nova [color=rgb(0, 45, 122) !important]boot[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 78, 208) !important]image [color=rgb(0, 45, 122) !important]ubuntu[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 0, 0) !important]flavor[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]2[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 78, 208) !important]nic [color=rgb(0, 45, 122) !important]port[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]id[color=rgb(0, 111, 224) !important]=[color=rgb(0, 111, 224) !important]<[color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 78, 208) !important]port1 [color=rgb(0, 45, 122) !important]id[color=rgb(0, 111, 224) !important]>[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 45, 122) !important]key[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]name[color=rgb(0, 111, 224) !important]=[color=rgb(0, 111, 224) !important]<[color=rgb(0, 78, 208) !important]your [color=rgb(0, 78, 208) !important]key [color=rgb(0, 45, 122) !important]name[color=rgb(0, 111, 224) !important]>[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]vm1 8 g/ B$ q) m) W/ n) h$ K
[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]nova [color=rgb(0, 45, 122) !important]boot[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 78, 208) !important]image [color=rgb(0, 45, 122) !important]ubuntu[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 0, 0) !important]flavor[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]2[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 78, 208) !important]nic [color=rgb(0, 45, 122) !important]port[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]id[color=rgb(0, 111, 224) !important]=[color=rgb(0, 111, 224) !important]<[color=rgb(128, 0, 128) !important]parent[color=rgb(0, 111, 224) !important]-[color=rgb(0, 78, 208) !important]port2 [color=rgb(0, 45, 122) !important]id[color=rgb(0, 111, 224) !important]>[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 45, 122) !important]key[color=rgb(0, 111, 224) !important]-[color=rgb(0, 45, 122) !important]name[color=rgb(0, 111, 224) !important]=[color=rgb(0, 111, 224) !important]<[color=rgb(0, 78, 208) !important]your [color=rgb(0, 78, 208) !important]key [color=rgb(0, 45, 122) !important]name[color=rgb(0, 111, 224) !important]>[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]vm2
( h" |% ]9 _3 ?* h# y- t , i: P8 b5 _, A+ Q% z
|
( z" S+ D9 \" q( y |5 _ . j4 l. V& v! y( H* L/ r
因为Linux VLAN Trunk需要8021q内核模块的支持,这里用了一个Ubuntu16.04的image。 到此为止,OpenStack的操作完成了。接下来,在两个虚机内部,配置Linux VLAN Trunk。在vm1内部,做如下配置: [color=rgb(51, 51, 51) !important]" t# x; x' p: }! u. t; q
. {2 U" |: X [, f# N" t& k# F
) w/ e5 F' l6 i/ B7 O0 m ]8 Y
5 l; g3 g! f3 B/ a2 b: d% ~$ M( `3 M% L9 X, m4 u/ S" e
# H3 b+ _4 M! p- P: j
. t; M5 F8 l. _$ U+ O
0 h, s% u+ B0 [. K0 j K' p, F' R
+ q; c) A5 Q; X: R' M; D, q 0 w* I5 Q4 I3 d9 p' y7 n
[color=rgb(153, 153, 153) !important]Java 8 k: J6 t- \+ {- d/ N& Z3 f# N
; Z0 H! @# W1 [6 T4 c! D
+ j& }8 j! G+ F5 p* o1
6 Y& Y+ Z6 G7 ^0 P[color=rgb(49, 124, 197) !important]2
: t7 B7 w# |" Y/ M. f2 G3
6 L" n% i+ T! u0 Z0 S3 X4 _9 [ 9 Z! i; G# ], N9 J( ]
| [color=rgb(0, 45, 122) !important]ubuntu[color=rgb(102, 102, 102) !important]@vm1[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important]~[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]sudo [color=rgb(0, 78, 208) !important]ip [color=rgb(0, 78, 208) !important]link [color=rgb(0, 78, 208) !important]add [color=rgb(0, 78, 208) !important]link [color=rgb(0, 78, 208) !important]ens3 [color=rgb(0, 78, 208) !important]name [color=rgb(0, 45, 122) !important]ens3[color=rgb(51, 51, 51) !important].[color=rgb(206, 0, 0) !important]102[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]type [color=rgb(0, 78, 208) !important]vlan [color=rgb(0, 0, 0) !important]id[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]102
x! B5 ^% C) R: q1 p3 k) |[color=rgb(0, 45, 122) !important]ubuntu[color=rgb(102, 102, 102) !important]@vm1[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important]~[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]sudo [color=rgb(0, 78, 208) !important]ip [color=rgb(0, 78, 208) !important]link [color=rgb(0, 78, 208) !important]set [color=rgb(0, 78, 208) !important]dev [color=rgb(0, 45, 122) !important]ens3[color=rgb(51, 51, 51) !important].[color=rgb(206, 0, 0) !important]102[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]address N6 _: ~0 { q+ }" i& m. B& j( n
[color=rgb(0, 45, 122) !important]ubuntu[color=rgb(102, 102, 102) !important]@vm1[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important]~[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]sudo [color=rgb(0, 78, 208) !important]ip [color=rgb(0, 78, 208) !important]link [color=rgb(0, 78, 208) !important]set [color=rgb(0, 78, 208) !important]dev [color=rgb(0, 45, 122) !important]ens3[color=rgb(51, 51, 51) !important].[color=rgb(206, 0, 0) !important]102[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]up + w5 c: w: M; k1 ~# U6 h
3 k# J5 e) I, m) X( \ |
' g% }* i. b6 X; b, D
/ @! s: Q, {& v; H这里给虚机的subport配置的VLAN ID是102,这是之前通过OpenStack命令创建Trunk时指定的segmentation-id。这里的ens3.102对应之前创建的sub-port1,为了让ens3.102能使用Neutron DHCP服务,这里将Neutron分配给sub-port1的MAC地址配置在ens3.102上。Linux子网卡默认会跟父网卡用同一个MAC地址,所以也可以在用OpenStack命令创建subport的时候,指定MAC地址。总之,这里我们让虚机内的子网卡的MAC地址与OpenStack Neutron中对应的subport的MAC地址一致。 在vm2内部做同样的操作,只是MAC地址换成成sub-port2的MAC地址。 2.2 验证连通性及DHCP服务DHCP服务
5 J5 e* U h/ _7 x; s在两个虚机内部,通过dhclient命令获取子网卡IP地址。 [color=rgb(51, 51, 51) !important]
: w7 [; S& o p) W6 z9 P 5 x5 n' N3 [# ?8 K
. k* g1 E& M, o0 q9 {$ c3 r( {
; t7 X1 |; J/ g5 S4 n: q1 @9 T$ D
( ?& S1 ?1 A( Q: P
0 \$ C* I& y' a# K% S! o, i) q* b( s7 D) R
: ]# G% Y! P8 r3 z5 d
5 p( P5 u( V' } a4 [8 K& ]# D' {& r
* {1 g5 c4 ^6 p; h[color=rgb(153, 153, 153) !important]Java / P% E6 M; |+ \3 \
. C$ _# c- R6 u6 j8 \2 D8 ~* B' J) j9 ]. N
1
+ }* A0 `" h J1 f[color=rgb(49, 124, 197) !important]2 , g- P! w3 o% @9 L9 W; w
3
$ `3 h. K& v; }) W+ d$ M) w! Z[color=rgb(49, 124, 197) !important]4 # D" n% c; ]) E. ]* z
5
2 G) a3 e/ j8 \% ?$ g[color=rgb(49, 124, 197) !important]6 % E- S! U) N) r7 m9 L% ~# o# ^
9 Y" k, p4 s7 A/ n4 u0 y | [color=rgb(0, 45, 122) !important]ubuntu[color=rgb(102, 102, 102) !important]@vm1[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important]~[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]sudo [color=rgb(0, 45, 122) !important]dhclient[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]-[color=rgb(0, 0, 0) !important]v[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]ens3[color=rgb(51, 51, 51) !important].[color=rgb(206, 0, 0) !important]102[color=rgb(0, 111, 224) !important]
: L: g/ U+ ?" M, E, Y( D3 l[color=rgb(0, 78, 208) !important]DHCPDISCOVER [color=rgb(0, 78, 208) !important]on [color=rgb(0, 45, 122) !important]ens3[color=rgb(51, 51, 51) !important].[color=rgb(206, 0, 0) !important]102[color=rgb(0, 111, 224) !important] [color=rgb(128, 0, 128) !important]to[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]255.255.255.255[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]port[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]67[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]interval[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]3[color=rgb(0, 111, 224) !important] [color=rgb(51, 51, 51) !important]([color=rgb(0, 45, 122) !important]xid[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]0x8e2bc124[color=rgb(51, 51, 51) !important]) 0 j- q5 j3 b# J& @8 \
[color=rgb(0, 78, 208) !important]DHCPREQUEST [color=rgb(0, 0, 0) !important]of[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.6[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]on [color=rgb(0, 45, 122) !important]ens3[color=rgb(51, 51, 51) !important].[color=rgb(206, 0, 0) !important]102[color=rgb(0, 111, 224) !important] [color=rgb(128, 0, 128) !important]to[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]255.255.255.255[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]port[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]67[color=rgb(0, 111, 224) !important] [color=rgb(51, 51, 51) !important]([color=rgb(0, 45, 122) !important]xid[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]0x24c12b8e[color=rgb(51, 51, 51) !important]) 5 A8 c- }9 G) a1 A) m2 R
[color=rgb(0, 78, 208) !important]DHCPOFFER [color=rgb(0, 0, 0) !important]of[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.6[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]from[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.2 1 i- `5 w+ n; I- g& S
[color=rgb(0, 78, 208) !important]DHCPACK [color=rgb(0, 0, 0) !important]of[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.6[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]from[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.2
! F' D. l0 O% j/ s# k" M9 b[color=rgb(0, 78, 208) !important]bound [color=rgb(128, 0, 128) !important]to[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.6[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]--[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]renewal [color=rgb(128, 0, 128) !important]in[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]42323[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]seconds[color=rgb(51, 51, 51) !important].
4 e" A7 M8 n5 J5 @! {( p* D0 ^
' Z! Q8 O. T$ W' {& Z |
: J1 A" K* h; i! M
8 y$ c9 B% F& O. M; F) e% U- S
可以看到,子网卡也可以通过Neutron的DHCP服务获取IP地址。
+ F- a3 c' A9 OVLAN互通 & V8 S$ f4 M3 Q6 p
在vm1内部,ping vm2. [color=rgb(51, 51, 51) !important], t2 h/ h! }% x; G+ u3 g6 f
' f. h% T) O! K6 F9 E7 n8 b( V$ \* M: E3 G: J$ a
6 ~* L+ L8 w% C- L% o D! p+ e
/ S# W, u$ Q4 F6 c1 W- E( c/ x
1 Y( T1 p p7 ~$ R- l3 M3 n' R1 N B o# j. C/ N4 U% l
2 i o- F/ x1 p' g0 X
5 w. u. w7 H' o* f( \
( H+ ?) u, B }( H[color=rgb(153, 153, 153) !important]Java
) x* p$ X6 I" I . E9 l2 @" {$ e! T3 v( _6 V
4 }6 g/ W; x l" {1 . D. E6 h) K" x f
[color=rgb(49, 124, 197) !important]2
8 _/ _0 E# b. }; W2 Y5 x5 G3 - X% q8 J, D5 {) L5 F# k) y
[color=rgb(49, 124, 197) !important]4
7 `) K" k% A9 e9 V* M5 ; S) f* S* w, b
0 [1 S- s8 \5 D4 d | [color=rgb(0, 45, 122) !important]ubuntu[color=rgb(102, 102, 102) !important]@vm1[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important]~[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]ping[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.7 0 L' U4 {* V1 f
[color=rgb(0, 0, 0) !important]PING[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.7[color=rgb(0, 111, 224) !important] [color=rgb(51, 51, 51) !important]([color=rgb(206, 0, 0) !important]21.0.0.7[color=rgb(51, 51, 51) !important])[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]56[color=rgb(51, 51, 51) !important]([color=rgb(206, 0, 0) !important]84[color=rgb(51, 51, 51) !important])[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]bytes [color=rgb(0, 78, 208) !important]of [color=rgb(0, 45, 122) !important]data[color=rgb(51, 51, 51) !important]. * u" k" K5 K, i2 [1 ?
[color=rgb(206, 0, 0) !important]64[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]bytes [color=rgb(0, 0, 0) !important]from[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.7[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]icmp_seq[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]1[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]ttl[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]64[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]time[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]10.2[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]ms u1 ?6 `$ F& O
[color=rgb(206, 0, 0) !important]64[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]bytes [color=rgb(0, 0, 0) !important]from[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.7[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]icmp_seq[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]2[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]ttl[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]64[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]time[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]0.979[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]ms - H- \( H2 J* _3 N0 A U4 S
[color=rgb(206, 0, 0) !important]64[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]bytes [color=rgb(0, 0, 0) !important]from[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.7[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]icmp_seq[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]3[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]ttl[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]64[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]time[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]0.817[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]ms * e* ]1 A& ~- [5 B
# R% J B' o1 I+ a, d |
8 @, m* b; k) Q1 M: K ?
( U/ M% Z) @) q! V. L4 O& B! S
在vm2内部,查看收到的包。前面讲过Linux VLAN Trunk的工作过程,Ethernet Frame发送到ens3.102时,已经剥离了VLAN标签。为了查看VLAN信息,所以我们这里直接监听ens3 [color=rgb(51, 51, 51) !important]# b$ F, t* P! z+ P, ^6 N, A7 @7 I" ?
1 `9 I9 @- [' i2 H% O
9 Y) a$ g& b2 U % A }! |( M) }- A* `. t
8 J0 K! d$ |% X/ K
/ D! S ^- J2 M! [3 a! x! A+ A) q: k5 g0 d/ n) Z, ]8 y. f- `
% U0 `0 u N0 S2 q: w
A& P" ?3 I4 @6 Z1 u, t4 y$ M: F+ \
" v/ Q7 W/ j) I% a- v- o[color=rgb(153, 153, 153) !important]Java
8 g( g2 A; W: m' v- T4 Z
' b: B3 Q- E7 y1 {) n V. I: g2 C3 c9 f' \+ R4 r
1 2 \ H N8 n" C! T0 e# ]7 S, B% v
[color=rgb(49, 124, 197) !important]2
* ]/ w" T3 {* ]3 k. j3 8 ?$ ]) w5 l& ?7 G7 g+ [
2 i& w! ]' k9 Y0 B' Q! B# f5 M | [color=rgb(0, 45, 122) !important]ubuntu[color=rgb(102, 102, 102) !important]@vm2[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important]~[color=rgb(51, 51, 51) !important]$[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]sudo [color=rgb(0, 45, 122) !important]tcpdump[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]-[color=rgb(0, 78, 208) !important]nei [color=rgb(0, 78, 208) !important]ens3 [color=rgb(0, 0, 0) !important]icmp
7 P$ J1 j- m+ M: M. ?[color=rgb(206, 0, 0) !important]08[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]42[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]24.256617[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]fa[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]16[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]3e[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]61[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]62[color=rgb(0, 111, 224) !important]:[color=rgb(0, 45, 122) !important]fa[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]>[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]fa[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]16[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]3e[color=rgb(0, 111, 224) !important]:[color=rgb(0, 45, 122) !important]da[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]61[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]99[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]ethertype[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]802.1Q[color=rgb(0, 111, 224) !important] [color=rgb(51, 51, 51) !important]([color=rgb(206, 0, 0) !important]0x8100[color=rgb(51, 51, 51) !important])[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]length[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]102[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]vlan[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]102[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]p[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]0[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]ethertype [color=rgb(0, 45, 122) !important]IPv4[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.6[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]>[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.7[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]ICMP [color=rgb(0, 78, 208) !important]echo [color=rgb(0, 45, 122) !important]request[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]id[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]11731[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]seq[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]388[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]length[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]64[color=rgb(0, 111, 224) !important]
- R2 ]; l3 u( D, W[color=rgb(206, 0, 0) !important]08[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]42[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]25.258424[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]fa[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]16[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]3e[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]61[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]62[color=rgb(0, 111, 224) !important]:[color=rgb(0, 45, 122) !important]fa[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]>[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]fa[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]16[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]3e[color=rgb(0, 111, 224) !important]:[color=rgb(0, 45, 122) !important]da[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]61[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]99[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]ethertype[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]802.1Q[color=rgb(0, 111, 224) !important] [color=rgb(51, 51, 51) !important]([color=rgb(206, 0, 0) !important]0x8100[color=rgb(51, 51, 51) !important])[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]length[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]102[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]vlan[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]102[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]p[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]0[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]ethertype [color=rgb(0, 45, 122) !important]IPv4[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.6[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]>[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]21.0.0.7[color=rgb(0, 111, 224) !important]:[color=rgb(0, 111, 224) !important] [color=rgb(0, 78, 208) !important]ICMP [color=rgb(0, 78, 208) !important]echo [color=rgb(0, 45, 122) !important]request[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]id[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]11731[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]seq[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]389[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 0, 0) !important]length[color=rgb(0, 111, 224) !important] [color=rgb(206, 0, 0) !important]64 # U/ Z! O1 b6 ^8 K8 b: U
; U q/ v5 f- R# p. i& Y7 z* w. A
|
x/ I2 l8 R2 S- i' N4 z
* p! F; U% ]+ T7 h) E( {可以看到,vm2收到的原始Ethernet Frame是带VLAN Tag的。 2.3 原理注:这部分内容假设你对OpenStack Neutron已经有一定的了解了。" G3 P- J0 V+ Q
虽然上面完成了VLAN aware VMs的配置和Linux VLAN Trunk的验证,甚至虚机内的subport都可以使用Neutron的DHCP服务,但是这里留下了两个问题没有解答。 - 首先,不用在vSwitch和Physical switch上打开trunk模式,就能支持带VLAN Tag的帧的传递,这中间发生了什么?
- 其次,一个传输VLAN数据的subport如何能使用定义在VXLAN网络中的DHCP服务?
/ U$ k- j8 ~* H# {% g5 I, X
看完Neutron VLAN aware VMs的架构,这两个问题自然就能解决。首先我们看看计算节点上的OpenVSwitch网桥。可以发现,对每个Trunk port,对应的新增了一个网桥。
. e& J% ]: A( H. Z
4 n2 z4 A9 y+ \在这个网桥的端口中,qvo端口是用来连接虚机的,剩下的端口中,一个是bridge对应的端口,剩下两个都是patch port。其中一个还带了VLAN Tag 102,正是我们配置的segmentation-id。patch port都是成对出现,这里的patch port peer都挂在br-int上。具体的网桥和端口的关系如下图所示:
* W/ d5 Q1 t) [0 w2 m" K, C ' D9 W, W$ W7 F( m$ z8 x! _
左上角是正常的OpenVSwitch上连接的虚机,为什么不是虚机直接到OpenVSwitch网桥?这是历史遗留问题,这里不做解释,大家只需要知道qvo是br-int上用来连接虚机的端口。再看虚线框内,上半部分与原来虚机伸出的部分相同,下半部分就是之前展示的新增的网桥。网桥向上通过qvo连接虚机。向下通过patch port pair 连接parent port,从虚机出来的不带VLAN Tag的帧,从这对patch port走到br-int。同时向下通过patch port pair 连接subport,一个subport对应一对spt-spi,注意的是每个spt都带有相应的VLAN Tag,根据OVS的特性,所有从虚机出来的,带上相应VLAN Tag的帧都会发送到相应的spt,再通过spi发送到br-int。 所以,从虚机出来的Ethernet Frame,根据所携带的VLAN Tag(或者不带VLAN Tag),在tbr网桥上,可以分配到不同的patch port,进而转发到br-int上的不同端口。也就是说,在tbr上,从虚机里一块网卡发出来的Ethernet Frame被分流了。 在br-int上,其实不知道qvo、spi,tpi有什么区别,这些端口对于br-int来说地位是一样的。这些端口分别在不同的网络中(最开始为parent port和subport分别创建了网络),br-int根据端口所在的网络,将虚机发出来的Ethernet Frame打上Local network ID(又一个VLAN ID,类似于VTEP中VLAN ID与VXLAN ID对应中的VLAN),发往br-tun。在br-tun根据Local network ID转换成VXLAN数据发送出去。 在对端,经过br-tun发送到br-int,br-int根据不同的网络,将数据发送到相应的qvo,spi,tpi。这里看spi这条线路,因为patch port的相连,数据发送到了tbr网桥,再经由qvo发向虚机。由于qvo没有自己的VLAN Tag,所以它将保留入口端口的VLAN Tag,也就是VLAN 102,最后VLAN 102的帧发送给虚机。 总结一下Ethernet Frame的处理流程。从虚机发出来的VLAN数据,在tbr网桥通过相应的patch port 对,发送到br-int。在patch port对的传递过程中,VLAN Tag由虚机内定义的VLAN ID变成了br-int内部的Local network ID。br-int将数据发送给br-tun。br-tun根据自身记录的VLAN ID与VXLAN ID的对应,将VLAN数据中VLAN Tag去除,并将剩余的Ethernet Frame封装成VXLAN数据,在VXLAN tunnel上传输。 对端收到VXLAN数据,在br-tun转换成VLAN数据,VLAN Tag是Local network ID,再发送给br-int。br-int根据Local network ID和目的MAC地址,将VLAN数据从对应的端口(spi)发出。经过patch port 对的传输,VLAN Tag由Local network ID变成了spt上的VLAN Tag,最后通过qvo发送给虚机。虚机收到还是VLAN 102的数据,但是数据在中间是通过VXLAN网络传输。 所以为什么不需要vSwitch和Physical Switch对Trunk模式进行支持?因为VLAN数据换成了VXLAN数据,传输的都不是VLAN了,自然不需要交换机配置Trunk。为什么子网卡能使用Neutron的DHCP服务,因为数据被换成了Neutron network网络数据(VXLAN),接入到Neutron network,自然就能使用Neutron network内的服务。 三、SDN中VLAN的实现Neutron在OpenVSwitch上实现的VLAN aware VMs原理在上面介绍过,不得不说,这个方案比较复杂,希望我已经说清楚了。虽然这个方案不依赖物理网络配置Trunk,但是需要创建额外的网桥和端口,对应的转换步骤也太多了。这么实现有Neutron的历史原因,也有Neutron轻度依赖OpenFlow的因素在里面。我们接下来看看在OpenFlow中,如何实现VLAN aware VMs。 VLAN aware VMs的核心思想是,用Neutron tenant network的overlay网络,来传输Linux VLAN Trunk发出来的各种VLAN数据。像上面的介绍,就是用VXLAN网络来传输虚机发出的VLAN数据,在进出虚机的时候再对VLAN Tag做相应的处理。相同的功能在OpenFlow中实现就简单的多,我们以Dragonflow项目的实现为例,具体介绍在Spec for VLAN aware VMs。只需要在网桥上添加几条OpenFlow流表,就能识别虚机发出的数据,并分发到不同的Neutron tenant network,进而通过Neutron tenant network传输。 在虚机的出口,添加下列流表: [color=rgb(51, 51, 51) !important]
' ], u f {& E9 w0 C8 e6 U5 O % x l* K+ U$ p( l2 |
) S: p* s- B; ^) a& `8 l: n
. O! B+ o7 q) Y" d# y' u+ ]! {/ N; k
8 u& [$ S6 F! S + i2 V+ x6 q k* H8 B/ K
) J6 S4 F: c: N9 H% k
3 G$ Z: O' ~+ S( ^" N" M& i
& N ?" ?6 n/ g6 T! a ) u }% j) a4 l- R: D
[color=rgb(153, 153, 153) !important]Java
, D. V) o7 [+ ]% _3 F, t + |$ V6 ~& S+ A! k8 }6 y
, f% m5 h! @3 n: n( e" L1
5 M/ S6 H7 G- Q, h0 z* H6 r1 B# E[color=rgb(49, 124, 197) !important]2 " T' a$ w/ n4 I/ E% M3 p
5 } e1 J% A8 k" N
| [color=rgb(0, 45, 122) !important]table[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]0[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]priority[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]150[color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]in_port[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]183[color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]vlan[color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]vlan_tag[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]102[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]actions[color=rgb(0, 111, 224) !important]=[color=rgb(0, 45, 122) !important]strip_vlan[color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]load[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]0x168[color=rgb(0, 111, 224) !important]->[color=rgb(0, 45, 122) !important]NXM_NX_REG6[color=rgb(51, 51, 51) !important][[color=rgb(51, 51, 51) !important][color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]load[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]0x2[color=rgb(0, 111, 224) !important]->[color=rgb(0, 45, 122) !important]OXM_OF_METADATA[color=rgb(51, 51, 51) !important][[color=rgb(51, 51, 51) !important][color=rgb(51, 51, 51) !important],[color=rgb(0, 78, 208) !important]resubmit[color=rgb(51, 51, 51) !important]([color=rgb(51, 51, 51) !important],[color=rgb(206, 0, 0) !important]5[color=rgb(51, 51, 51) !important])[color=rgb(0, 111, 224) !important]
( X# X; \9 p& i( N[color=rgb(0, 45, 122) !important]table[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]0[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]priority[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]100[color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]in_port[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]183[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]actions[color=rgb(0, 111, 224) !important]=[color=rgb(0, 45, 122) !important]load[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]0x166[color=rgb(0, 111, 224) !important]->[color=rgb(0, 45, 122) !important]NXM_NX_REG6[color=rgb(51, 51, 51) !important][[color=rgb(51, 51, 51) !important][color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]load[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]0x1[color=rgb(0, 111, 224) !important]->[color=rgb(0, 45, 122) !important]OXM_OF_METADATA[color=rgb(51, 51, 51) !important][[color=rgb(51, 51, 51) !important][color=rgb(51, 51, 51) !important],[color=rgb(0, 78, 208) !important]resubmit[color=rgb(51, 51, 51) !important]([color=rgb(51, 51, 51) !important],[color=rgb(206, 0, 0) !important]5[color=rgb(51, 51, 51) !important])
# z- W9 n& [5 p% z/ v! b5 z) Z
+ r& [" u, D$ ? |
* ^$ e' a& S" \) L* C$ U A7 s. t; `# V b+ Q0 F* a1 `; V8 Z
这里的REG6表明入口端口,METADATA用来识别网络,可见,在table0就已经完成了将虚机中一块网卡发出的Ethernet Frame根据VLAN Tag分成不同的通道,并识别相应的网络。之后的传输不需要区分究竟是不是子网卡的数据,就是当成普通的overlay tenant network传输。 在虚机的入口,添加下列流表: [color=rgb(51, 51, 51) !important]
. C$ G- @" U% E, \4 {
% [: g2 K9 |) g J
5 C9 t: n# P H8 F. H2 I O1 R; Q8 e
- S# n: b+ Z$ k/ Z5 L. v
: U3 z# A8 u w9 h$ H1 m3 n : ~) G( C2 X% ^9 k% ]- N7 `
* H8 k. @# e, V) U$ w! g6 Y0 Y5 D
( J. g2 ~( L. |" \% ~( c9 G8 d2 j( o% [
H2 I& S5 V/ G: d, T; }+ V% x
[color=rgb(153, 153, 153) !important]Java $ e) Y$ Z6 [. o* z1 G
3 S& T% m) I4 J9 n$ d9 { Q/ o5 K; y3 l
1
* m2 T, |9 p& K1 o) D[color=rgb(49, 124, 197) !important]2 8 ]% U0 Q% C3 J4 y. z
4 D* r0 h' W2 x. A
| [color=rgb(0, 45, 122) !important]table[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]115[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]priority[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]100[color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]reg7[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]0x168[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]actions[color=rgb(0, 111, 224) !important]=[color=rgb(0, 45, 122) !important]mod_vlan_vid[color=rgb(0, 111, 224) !important]:[color=rgb(0, 45, 122) !important]vlan_vid[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]0x10066[color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]output[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]183 1 d% X# J5 \7 S5 i
[color=rgb(0, 45, 122) !important]table[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]115[color=rgb(51, 51, 51) !important],[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]priority[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]100[color=rgb(51, 51, 51) !important],[color=rgb(0, 45, 122) !important]reg7[color=rgb(0, 111, 224) !important]=[color=rgb(206, 0, 0) !important]0x166[color=rgb(0, 111, 224) !important] [color=rgb(0, 45, 122) !important]actions[color=rgb(0, 111, 224) !important]=[color=rgb(0, 45, 122) !important]output[color=rgb(0, 111, 224) !important]:[color=rgb(206, 0, 0) !important]183 & b" ?1 D' Z4 M5 n
4 K5 m0 l' ?3 }4 s) F& i |
& @3 s" l9 k9 s- g' {3 B; D0 R
- D, n% X C8 ?, @! B7 E) q* g
“mod_vlan_vid:vlan_vid:0x10066”就是打上VLAN Tag102,可以看出不同网络的数据,打上不同的VLAN Tag(对于parent port不打VLAN Tag)发向了同一个端口183(虚机网卡)。( N( T: o x2 J5 _* m
没有多余的网桥,没有网桥上换来换去的VLAN ID,仅仅是在入口和出口处去除VLAN Tag和打上VLAN Tag,几条流表就实现了所有的功能。简单的实现一般意味着更高的效率和更少的错误,因此使用SDN方式实现VLAN aware VMs更具有优势。 四、VLAN Trunk在NFV中的应用最后我们再看看VLAN Trunk在NFV中的应用吧,这个在最开头一些简单的介绍,这里来说个用例。一个多路复用设备,需要连接多个子设备,子设备的数目是不确定的,且有可能变化,并且要求子设备间网络是隔离的。当然,我也可以给多路复用设备配置多块网卡,但是由于子设备数目不确定,网卡数目是不确定的。这个时候可以将多路复用设备的一块Ethernet网卡配置成VLAN Trunk port,在之上创建相应的subport。子设备上的网卡也配置成VLAN Trunk port,并创建对应的subport。由于配置的VLAN不一样,不同子设备之间的网络是隔离的。并且多路复用设备的subport是可以动态删减的,这满足了子设备数据是不确定的要求。具体如下图所示:! _6 j- ^1 v* t& H3 _3 u
( e/ S! P) b4 M: ^. g# l
不论是VLAN Transparency还是VLAN aware VMs,都是为了使得OpenStack中的虚机能够使用Linux VLAN Trunk功能。VLAN Transparency依赖vSwitch和物理交换机的配置,不说实际物理交换机的复杂性,单就是vSwitch也不一定支持Trunk模式。VLAN aware VMs通过一系列的转换,摆脱了对vSwitch和物理交换机配置的依赖,走在网线上的数据甚至都可以不是VLAN数据,这比VLAN Transparency进了一步。而通过SDN实现VLAN aware VMs可以大大简化实现过程,又更进了一步。 |