|
前言 本文先介绍一下VLAN Trunk的基本概念,以及OpenStack Neutron和OpenFlow based SDN是如何为Trunk port提供网络支持。OpenStack对VLAN Trunk的支持具体是什么?虽然OpenStack与容器,物理主机也做了集成,但是OpenStack最主要的应用还是虚机管理,而现代的操作系统,不论是Linux还是Windows,都支持将网卡配置成Trunk port。OpenStack对VLAN Trunk的支持就是指对OpenStack所管理的虚机的Trunk port,提供网络支持。
( ~7 s, g1 t1 V N' a: S8 l7 o9 S6 o $ \; m' m# R& D- H
主机的Trunk port是指在主机的一块网卡上添加多个带有不同VLAN ID的子网卡。通过子网卡发送的数据,打上VLAN Tag,被发送出去。由于带了不同的VLAN Tag,子网卡可以认为连接在VLAN Tag标识的网络中。这样,不用增减主机的网卡,就可以将主机添加到新的网络中。更主要的是,这种方式的网络添加是动态的。 主机的Trunk port有什么用?一个应用是在NFV场景下,一个VNF(Virtual Networking Function)可能需要同时连接多个网络。当然最简单是一个网络对应一块网卡,但如果网络数量巨大,网卡数量也巨大,一方面这不现实。另一方面,连接的多个网络也是动态增减的,如果每次增减都插拔VNF的网卡,明显也是不能接受的。如果用Trunk port,当需要动态连接多个网络时,只需要动态的创建/删除相应的子网卡即可。7 g [" G3 ^4 U" Z$ ^3 {
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的工作原理。
2 W& n4 P& q# b7 z
* h# K0 y a f9 T如果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。
( @7 Y, F% u) E( } 1.2 VLAN Trunk简介VLAN的划分并非只能在一个交换机上,多个交换机可以共同组成VLAN。那多个交换机上的VLAN是怎么连接到一起的?有两种方法。 第一种方法是把每个交换机上的每个VLAN都连在一起。如下图所示:
0 i( C/ L2 P' L! T! Z * b% F% I9 s4 g# j/ W" v
图中有两个交换机,各有两个VLAN,为了让VLAN能正常工作,将VLAN1和VLAN2分别连接起来。如果是两个交换机,两个VLAN还好,如果是100个VLAN,那么这里需要有100条线路,200个交换机端口。这么连接可以吗?可以,只要有钱,因为这里的线路和交换机端口都是钱。这种方法,运维和成本支出比较大,不实用。 第二种方法是通过VLAN Trunk连接交换机。VLAN Trunk是一种网络设备间的point-to-point的连接。一条VLAN Trunk线路可以同时传输多个甚至所有的VLAN数据。4 o. K, y3 s$ S: j% R d: R
$ T' j6 e! ~; D0 E) i' A
由于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发送到最右侧的服务器1 J" \5 a% \9 j% d+ l
如果是VLAN200的数据,过程一样,只是VLAN Tag从100变成了200。 通过VLAN Trunk port,两个交换机之间不论需要连接多少个VLAN,只需要一个VLAN Trunk连接(一对Trunk port)即可。 如果有多个交换机需要连接,通常会用另外一个交换机连接它们,如下图所示,交换机之间都通过Trunk port相连。
; A# {/ i4 G& W
& b9 l. c- g1 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]
+ E; `# D, `. g* t' `7 |
1 H7 Q+ B# v5 }# t% x( I5 |5 q& }+ n
, l' k2 q& X" r6 e4 K% H
$ ~+ |# U3 r( v! ^: {
% ?- V4 P2 {- M1 l
- Y" b" ^2 ~" d; k+ }$ ^) E+ L; e* f2 G3 d/ ~: }7 S
2 c' X8 X. d+ ?2 b4 N9 ?$ F& d: F% ~& c( t" `
0 }( x$ Q6 m5 {[color=rgb(153, 153, 153) !important]Java * h' [3 @) v6 e$ O+ t8 k7 |
4 b( r$ x# o9 ?$ F
5 [: Z+ b9 r3 z0 Q, D; n& L3 e1
2 t+ c. c2 c" S2 d- S. }! C8 j % ~% J2 v5 Q, F7 |7 _* t
| [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
$ X1 W/ [. v3 p) g$ K% o 3 j: C8 z3 W: q2 |, u! } a
|
0 E# \! R; ]! A
. y" [. g( [- Z2 a0 E就这么简单,之后可以看到一个新的网卡在系统的网卡列表中。Linux VLAN Trunk工作过程如下: - 外界传入的带VLAN Tag 102的包,到达了eth0,VLAN Tag 102被去除,然后不带VLAN Tag的Ethernet Frame被重新发往操作系统网络栈,再发送到eth0.102。
- 从eth0.102发送出来的帧,被打上VLAN102的标签,再从eth0传出。- r r8 L# ^4 Q- {( D& _2 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
4 K5 J8 i. d- L( F: |9 {
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. V! g" w% Z v+ H
$ m" {( ]! O& d
. O4 I7 Y: o/ ^/ `3 j8 a; l ' g7 }1 s) M4 O# f M+ {: E+ N
- n# D; n ^2 P7 T - [ G) ^4 L8 R: Q# l9 g/ F. m# D2 s
# ]! `, o$ e$ e5 t3 F0 E; n
0 n4 j1 b2 y1 |% \. Q
9 x( [4 E! y4 X: v3 m' d 7 P' R8 E9 p" J$ l7 i
[color=rgb(153, 153, 153) !important]Java
# r8 r2 j2 d0 G( @2 L' \
, R$ ]( s/ D' G) R5 w( M+ y8 N( H; f0 g
1 : M6 R; ~- d2 Z
[color=rgb(49, 124, 197) !important]2
& J% A6 \1 @; }1 {1 f- l3
$ ]4 N" u" N! T[color=rgb(49, 124, 197) !important]4 3 ^1 U! e8 T% f8 u' z9 }
) o [" P! ^' _1 v' c% f
| [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 : E# {5 G9 {; _, P" {0 |
[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
& D+ N) P K5 A) F[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
* i' z1 |* [; t* K& ?5 s: r8 X[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 ! _6 f+ H( n5 c6 u
4 {- w0 h/ U* s( Z( b4 l/ g |
" B. p) o/ `( d2 M N" U* U
* N5 k: U$ @: k' {) |注意这里我并没有指定网络的类型,网络可以不用是VLAN的,像在我的环境中,网络就是VXLAN类型。为什么会这样?在后面会说。 接下来创建Trunk port和subport。 [color=rgb(51, 51, 51) !important]: V* W: ~' @- ?# x
3 Q8 [1 I W2 P, Z) {, |% K5 ^! }2 d4 i/ B# ]/ e( w6 j8 X% v
) u( O4 \' w& k7 P, y' e" `. {; S. |5 P* C
! D2 }, a, v' D% l; b4 _
& \ w+ o* o0 J% @ t
: F& A8 o1 Y6 v! |( Y
, I, A# r7 y6 _. c$ P- O
+ d$ M0 z q/ d: E1 W L; l! l[color=rgb(153, 153, 153) !important]Java
! F7 V/ S* w# |; X- H! a: Q, E 5 T$ N& t1 \) X% o) `8 m3 E ^
2 J6 Z+ u7 p' F+ J1 ( m4 F" y& ^5 Y( n2 v& V" b# p9 U
[color=rgb(49, 124, 197) !important]2
! E8 {8 u1 Q; ?7 {: o( Q3 " h/ z9 m; e! r* D: j
[color=rgb(49, 124, 197) !important]4
( Z5 h; t6 _0 G+ a$ L# H5 \9 b; `- ]% i0 O. S
[color=rgb(49, 124, 197) !important]6 9 p% u8 ~6 h8 c# f/ }8 U
7
' Q/ U1 l) Q. g8 a1 c/ H6 g[color=rgb(49, 124, 197) !important]8 9 G1 p. D% S, V& I: g
$ R/ A& o" E2 E- P( r1 p& Z8 n0 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]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 V. z2 l0 K8 k! ^" g. ?[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
]; _8 U) j! b& _, l3 H[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
. C2 N& F. v; T* O/ i# G[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 ! s5 K4 ^' ?- @) _& F" 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(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
% Z0 R5 \; x) \3 @# F[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
S- o9 k' {6 o) 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
9 G2 U2 ~; E+ E% f/ o. |6 I[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 ; Z( d) B1 G9 P, [" s* K. o
0 a) |' U" ]/ l2 p- |( B! N7 ^. n |
( I& n2 e7 ~, m0 m+ n, R
0 D4 N. j6 J9 T- D0 p9 }6 Q! g8 \这里创建了两组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]
$ u" t$ j. A+ _; P& C # `8 q7 r4 H. L' c! ~/ B
9 h1 C5 ]* Z$ R, A$ j
& C* `: c3 r" m7 R! O& D4 } D/ Y9 F7 j, Q# ?/ d0 g; j) s6 {
, W. m0 ]$ G* ^+ s( _2 Q V
- s% e" A* ?$ v# H+ @
% H% ~9 J5 K! P6 k
: b% k) J0 b4 L" k# j4 z! Q8 X
* v; `7 z- X% ]. D2 q$ R7 k' r[color=rgb(153, 153, 153) !important]Java 5 x$ A0 {0 g! U9 M7 u
* U$ ]0 h, m& }( X* i8 d
) V7 T8 n6 G! N# q# [0 m( @9 w1
) ]- {6 {5 n6 X3 t5 l$ C! h% X[color=rgb(49, 124, 197) !important]2
. E, X% j, y) G& |# L; _; j
* m1 z1 |, ]) s9 m | [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
' U0 L( M* l7 F. J[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 - c7 f( x n6 ]& _
0 S# c6 k1 e R
|
* V9 ^8 Z/ u+ _* V( O
- @0 r. K- p% b$ R+ A因为Linux VLAN Trunk需要8021q内核模块的支持,这里用了一个Ubuntu16.04的image。 到此为止,OpenStack的操作完成了。接下来,在两个虚机内部,配置Linux VLAN Trunk。在vm1内部,做如下配置: [color=rgb(51, 51, 51) !important]2 K" l; }( v, L5 t% y& C& q
5 B3 p& A5 d5 x) ~8 u$ @
; J+ d. |7 n1 K- ^( F7 T2 t V 1 D: }( h5 L. P, P7 F( Y3 p
. d) w2 z2 h2 O# |3 p6 d- h \
. j+ I3 b( z8 H
q( F+ F/ @3 F/ t V( Q4 y ! Z2 R3 H& R( v2 ?
% z; g6 j, z" z' l" Y4 j % F/ j0 _+ q. r
[color=rgb(153, 153, 153) !important]Java 6 n6 d+ L2 ]4 P' [8 ]) ^- u6 g/ S. w
" y# A' ?' F% @2 [3 ~' W, S* ^2 K
6 [. K% X) w' ]* }0 b7 L2 T1
: a+ I4 V( ]9 V[color=rgb(49, 124, 197) !important]2
. Q9 Z0 a" T" n! \4 o" C' }3 4 D9 y, n. B5 y- _$ T% i
! J$ h ^1 ?3 o8 n9 s | [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
# d0 R9 a3 G3 Y) a; j4 [[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
8 l+ \ H7 ?$ @3 L' T4 \[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
7 B! d. @8 {: K/ {! W" { 7 C) k: _: k" _
|
+ U( _& d( n. \4 [
( V0 s& M& M$ V) x这里给虚机的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服务
! K) O# I4 M5 X在两个虚机内部,通过dhclient命令获取子网卡IP地址。 [color=rgb(51, 51, 51) !important]
2 U& }# j! ]+ L
$ d( j/ W$ r0 `5 L
* ?9 Q( u# X. P4 Z" ?; s- \6 [ . m" R3 Q8 Z& Y+ k
$ C, I3 o5 I8 G
' [3 m& E* \ X. p0 V9 D
' c ~& T$ ?$ |- P: L! _; S4 ?! u : j8 o$ f2 i! u
7 m( T1 G3 \& t& u3 c5 c9 D
. D" r1 `9 t S& r. Y
[color=rgb(153, 153, 153) !important]Java
4 w$ I/ [9 ]5 l; k( w: d( y 8 B |: i0 {- n7 \6 x/ g
9 C+ }- d, u& P% e; G
1 3 u( C+ t: v. Q% W0 j+ `' y& M
[color=rgb(49, 124, 197) !important]2 % \, ?& }% D! s0 k) C
3 ' i8 I' `" D/ G% v: s/ r
[color=rgb(49, 124, 197) !important]4
" u: C o1 y' N2 F; u3 f5
/ d3 } T4 H/ L! ]" H$ n: L[color=rgb(49, 124, 197) !important]6
v6 F& o2 U2 H( [ $ h" f c" [" e K9 k$ k" D, 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, 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]
~- k8 N, O* o0 c9 y[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]) " |6 t0 _. A/ ?$ g8 k& [4 E) D; A
[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]) # [* c4 A h, k3 A/ G! V% P/ M
[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
' e) ?1 I. V- ~( p8 v[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 , y% s1 Y- d* V" r: M
[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].
: `. Z# H. S- u . @& n6 r2 l: u. b
|
$ L( [9 i. A' ]) q7 O 3 J7 }2 C% ^" o+ e
可以看到,子网卡也可以通过Neutron的DHCP服务获取IP地址。
& S0 Q& k# t& w; p/ m- b0 UVLAN互通
6 G$ S) L1 T, O: }" Y3 r6 ]在vm1内部,ping vm2. [color=rgb(51, 51, 51) !important]
/ a) b& i/ H' P) L' g" v : F- l J: f5 y3 L$ \# @$ ~( o
; W. N9 m! Y* t( I }
" g! r2 \$ Q0 p! h7 A7 o. y! h
0 {' }) R, u1 A3 N; Y
9 b/ o8 v" o$ h4 M; V
0 {% g( c( Z/ g0 E P& O0 H' Z- R- @. r
. Y. y$ s1 x5 n( K
?/ K/ G, K( e5 ^: H[color=rgb(153, 153, 153) !important]Java
$ k. _7 Z# w2 b4 @4 k/ l
2 m# W# U( J# y7 m! r1 W4 x8 m# Z, W9 N. j
1 : m! u/ \6 I0 Y2 L6 I- }
[color=rgb(49, 124, 197) !important]2
: ?1 j: P( m8 N: h5 q* R3
# u4 ^ v. ?+ q# l[color=rgb(49, 124, 197) !important]4 ( x! D' B" @6 P2 c$ r; k
5 5 c$ n8 d4 k" G
5 e6 V7 ]9 r4 h& Y" V | [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 ' p/ f7 i+ ^# ]0 J i( s, @% W
[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].
a$ c# S* G' g' v[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
7 I' X1 ^8 d) L# G[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
" ~" I6 \6 v! L. ]1 A[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 # l& R9 z v' c+ s
# D0 ^- H4 r: j9 t6 v8 G! H+ c |
3 Y/ l4 _4 T4 S2 i # U) e; n+ l! |/ ~4 H
在vm2内部,查看收到的包。前面讲过Linux VLAN Trunk的工作过程,Ethernet Frame发送到ens3.102时,已经剥离了VLAN标签。为了查看VLAN信息,所以我们这里直接监听ens3 [color=rgb(51, 51, 51) !important]
2 N% h" V4 m9 ^& _ 1 p8 X# G w- w5 M5 H
* t$ Q) a: b% U8 \( `2 V+ \( `
$ n% u; Y6 Q' m8 Z, F8 @* c3 e$ q+ ]; S$ u
) }# Y& R' F2 H* a& P" `
. F1 E9 `- ]3 z/ a# I ; Z: ]* a8 `/ ]+ c9 R4 y
3 S* y. l& @% l( h7 ^5 @
6 {- ?* v2 t/ c9 c {- S
[color=rgb(153, 153, 153) !important]Java 2 k0 U5 f- r$ H; z; P: d
8 @0 M& T( y4 j& V& o4 W1 ?. W3 w# `8 Y- i
1
1 {+ B6 R b% Y1 P- X' l& q[color=rgb(49, 124, 197) !important]2
" j# ^& j1 g! ~3 + O( L& z8 |8 O7 u% X9 X
+ \. U; M! N0 x3 k$ m, E/ I, w | [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
! X4 ]' G% x. X( Q[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] ) d! n" K) p- R5 V) F
[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
7 l+ r4 [& l# p' ?5 {) U ' Y% B+ T6 ]( X2 J8 ?' P
|
9 ]6 k9 I- n+ y3 R
9 J/ q1 y& [9 K! L可以看到,vm2收到的原始Ethernet Frame是带VLAN Tag的。 2.3 原理注:这部分内容假设你对OpenStack Neutron已经有一定的了解了。
- X' v% t) W1 ]1 t3 s" M! y1 H' G虽然上面完成了VLAN aware VMs的配置和Linux VLAN Trunk的验证,甚至虚机内的subport都可以使用Neutron的DHCP服务,但是这里留下了两个问题没有解答。 - 首先,不用在vSwitch和Physical switch上打开trunk模式,就能支持带VLAN Tag的帧的传递,这中间发生了什么?
- 其次,一个传输VLAN数据的subport如何能使用定义在VXLAN网络中的DHCP服务?
/ S6 b: G( D D; I
看完Neutron VLAN aware VMs的架构,这两个问题自然就能解决。首先我们看看计算节点上的OpenVSwitch网桥。可以发现,对每个Trunk port,对应的新增了一个网桥。
2 {/ f! r5 M; ~$ t% E/ w7 {
" O$ N: X, U# m4 Z在这个网桥的端口中,qvo端口是用来连接虚机的,剩下的端口中,一个是bridge对应的端口,剩下两个都是patch port。其中一个还带了VLAN Tag 102,正是我们配置的segmentation-id。patch port都是成对出现,这里的patch port peer都挂在br-int上。具体的网桥和端口的关系如下图所示:
; C1 D" K! C+ A2 s 8 `9 _0 {) O4 |- @# X5 c
左上角是正常的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]* w7 x* s7 _; V; C
$ R" H; z9 D1 H: ^2 _- K
$ ~9 M( c% l& \2 q! }0 X" x& b + T' R2 J+ U( A8 G) B% Q& E
3 l/ q# m3 ]+ v- L2 v" ~3 \2 W 4 D3 I. M$ D- h! T( `
2 S" G" {/ R2 [
8 Y: ~: s( g2 W+ c' r: F! L; p0 U1 I/ M) f; g- |
0 E. Z& ~+ V: E C, L& P+ m
[color=rgb(153, 153, 153) !important]Java
& T$ p5 k! a5 U3 D. o ! E+ f: W0 L( U% k7 X: y3 L
2 R0 A7 Y- E, }3 R _1 6 i% ]3 O% P7 w4 x: R u
[color=rgb(49, 124, 197) !important]2 3 n1 x, M7 G4 L" D' F2 P" a$ o
( @$ s7 ]8 I5 V2 u
| [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]
* K' v4 Y# W% F9 l" |; q+ Y5 t[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])
9 v' h3 h- |" P' O. p6 A: [ - A- o4 ^6 Y* ?7 v1 ]
|
& R9 S/ g* U& q
* ^" {3 T7 ^& `5 g+ x这里的REG6表明入口端口,METADATA用来识别网络,可见,在table0就已经完成了将虚机中一块网卡发出的Ethernet Frame根据VLAN Tag分成不同的通道,并识别相应的网络。之后的传输不需要区分究竟是不是子网卡的数据,就是当成普通的overlay tenant network传输。 在虚机的入口,添加下列流表: [color=rgb(51, 51, 51) !important]2 ?4 s# v: F8 i
* a) }! i; w' n" u l) o4 ]2 m2 u# U% Q) ^6 Y- L
' u) D6 d% A5 Z+ A5 k
& v) I0 J5 a( E. Z- h t% q$ b$ V1 `5 u4 \
% W6 s* c; {1 z: T* ^- _9 a# l& D
9 { o' t2 ?* B" K
: P( d& Q; ]0 x" B) a- r % H) Y# w% S( {% o+ l
[color=rgb(153, 153, 153) !important]Java ( `% T/ m: m9 z3 r
& O u/ H' L" g) B- w+ I) c- y5 G' H
1 9 K+ {8 E2 n, b" f0 n8 f5 q. f2 }
[color=rgb(49, 124, 197) !important]2 / k+ V. C1 m9 o% J: i
9 {1 W1 S: B2 `) U: e7 l- n | [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
; {' w" { ~ w" C! R! I) m[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
! X+ m3 r' g+ V% S0 g1 F
* P* o- M7 q' e4 l4 w+ ] |
# K& W8 O3 B Z/ |2 T+ d6 Z, m
4 e: G, n9 y3 p( g- a/ F" N“mod_vlan_vid:vlan_vid:0x10066”就是打上VLAN Tag102,可以看出不同网络的数据,打上不同的VLAN Tag(对于parent port不打VLAN Tag)发向了同一个端口183(虚机网卡)。0 Q. }" ~9 Q$ L4 ~% [5 f+ w+ r
没有多余的网桥,没有网桥上换来换去的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是可以动态删减的,这满足了子设备数据是不确定的要求。具体如下图所示:
/ |% f$ ?: o; e 5 E% S+ `% Y+ q$ ~
不论是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可以大大简化实现过程,又更进了一步。 |