|
|
楼主 |
发表于 2019-10-25 11:23:29
|
显示全部楼层
虽然大部分的OpenStack 部署环境中,都会使用 Open vSwitch 来作为虚拟交换机来实现二层网络功能,但是Neutron 仍然支持使用 Linux bridge 作为虚拟交换机来实现二层网络。本文就此做些分析和说明。 3 a- L- r# p, I. t
同时要指出的是,OpenStack 官方已经把 linux bridge 实现标记为 legacy 的了,文档从 2016 年后也没怎么更新了。这是因为,linux bridge 和 OVS 相比,只支持基本的网络功能即二层交换,但不支持VLAN 标签和隧道。因此,linux bridge agent 利用linux 内核功能(VLAN 子接口和 VXLAN 接口)来实现VLAN 标签和隧道。& m$ a; A# r% n+ Z
1 y; B7 A# k3 B, R" k2 s+ u
1. 测试环境( A# l0 k8 j0 A ~
以下面的环境为例(网络节点上):
7 k/ O" E3 R" P% r: ^% U(1)linux bridge9 @7 S/ X8 ^. M& |/ E
6 m- A. g y; M+ P3 W. ` J2 N
root@controller:/home/sammy# brctl show
* z; | g2 c# a/ b5 l( hbridge name bridge id STP enabled interfaces, t9 B' Q3 |7 y# y3 f
brq85925305-b4 8000.563534c8d02d no tap0bb8efeb-10
' |; W8 r% Z' [2 M7 e3 d tap798c87d1-a2
, p7 Y; Z7 z! \ vxlan-25
" c7 p* u, w5 N! A& X& W, Ibrq96609bfa-0e 8000.0050569c4d94 no ens224) B$ g, ~" p, m5 d: x9 n$ { b
tap60dbdc2f-a0
( \0 G ~; H2 V7 Pbrq971ffda2-e5 8000.a6acb08e4fd6 no tapb1eaae00-e5 g% e/ i& p: k! F! A: o, G% a
tapf70543dd-0f
8 {+ [% U: G0 ?6 V vxlan-104 J4 T7 E5 _- h$ y* p! f
- Q6 T6 j* l# H8 }4 q1 m: A
(2)OpenStack 网络和 network namespace:6 ^2 |& f6 V; e& ^- \
% H& F( g4 K. ?* W P
root@controller:/home/sammy# neutron net-list
) u7 I* k4 C. ~, ~+--------------------------------------+---------+-----------------------------------------------------++ h R2 B+ g/ c# C! s' R8 x9 R5 ?
| id | name | subnets |
1 n+ E( X3 r: }0 \0 C4 o0 R" v+--------------------------------------+---------+-----------------------------------------------------+. {8 Y) I. _$ Y* m, u
| 96609bfa-0e22-4bb7-8dba-6ef532ea6076 | extnet | afa7d205-3026-439f-aca7-295a9f9b2a71 10.62.227.0/24 |
* e* e9 f d# L9 J( A| 971ffda2-e567-40a0-a2c8-b31a577fd4d3 | appnet | 4c68eacb-bf3e-408a-a941-94e93eddb22b 11.0.0.0/24 |6 a- m' s: m8 A/ `- {
| | | 3d596991-de8f-4ae4-8913-89426a8abbd7 10.0.0.0/24 |
! k5 ]! U+ Q. v' P- X6 e! M( N| 85925305-b477-4cc6-9654-67d9bf1e7cd8 | appnet2 | 4575c7f1-7f08-4917-9904-ec65af38619b 20.0.0.0/24 |, V) B$ _$ G3 ]% c
+--------------------------------------+---------+-----------------------------------------------------+
( q" Q; \$ ^# groot@controller:/home/sammy# ip netns; w9 {* Y3 R% O7 \" i
qdhcp-85925305-b477-4cc6-9654-67d9bf1e7cd8 (id: 2)
8 m! p# K0 k; D- Q$ E W7 j- Kqdhcp-971ffda2-e567-40a0-a2c8-b31a577fd4d3 (id: 1)# }3 b) d* E- N; W% G. w' }
qrouter-39a77439-8a28-49c1-bf97-ac931510631b (id: 0)
, V% W# N7 F* c6 n( H2 W
1 {0 d6 o& X' L7 G" w# @(3)示意图:( E/ d6 m% [, E6 V0 K4 q
: T( C" Z4 F- J(4)说明:0 n( S( g/ N2 ^: M; v& g k
• qdhcp 和 qrouter 都是 linux network namespace 实例
* x3 n2 w; {5 G/ G- G4 Z8 M• qdhcp network namespace 的数量等于启用了 DHCP 的 Neutron network 的数量。$ b; K6 i" T5 |/ m6 X
o 当一个 network 中存在至少一个 subnet 启用了 DHCP 之后,会有一个 qdhcp network namespace 被创建出来;
8 X9 v7 [& {6 k! N3 Wo 当一个 network 中多个 subnet 启用了 DHCP 时,它们共用一个 qdhcp,以及 dnsmasq。
! @2 K0 d8 j W2 z3 ^o 其 name 使用 network id,比如 qdhcp-85925305-b477-4cc6-9654-67d9bf1e7cd8/ V" B4 D& c, w w9 K
• qrouter network namespace 的数目等于 router 的数目,也就是说,系统中一共有几个 router,那么就存在几个 qrouter network namespace: s9 } U5 f' ~4 {: T
• brq linux bridge 的数目等于 neutron network 的数目,其 name 是 network id 的前几位,比如 brq96609bfa-0e
; h5 X6 t: D6 q7 d6 Y• 一个 network 的 qdhcp network namespace 和其 brq linux bridge 一定有连接
( L6 v+ d; Q: _3 H• qrouter 之内的 network interface 分两种,一种是 qr 开头的,每个连接到 router 之上的 subnet 都有一个;还有一个是 qg,每个连接到 router 的 external subnetwork 有一个
4 s; V) R3 K$ ~7 W% W" C• qrouter 的每个 network interface 都通过 veth 连接到所在网络的 qbr linux bridge 上
" }7 ?5 a$ b- Y6 t8 y• qbr linux bridge 连连接两种物理设备,一种是 vxlan interface,每个 tenant network 有一个,另一种是在 physical network 对应的物理网卡上创建的子接口(sub-interface)
5 v! J* Q i. ~+ a( b6 A• 对于 physical network 的 qbr 来说,用户可以指定它,并且在linuxbridge_agent.ini 中通过 bridge_mappings = List of <physical_network>:<physical_bridge> 进行配置;也可以不指定,此时 agent 会创建它。当同时配置了 physical bridge 和 physical interface 时,前者优先。
. x3 y7 K3 g6 u0 |如果 external network 中有多个 subnet 的话:& v9 q- Y) o$ i( @8 G: u
(1)每个 qrouter 只允许有一个 External Gateway,也就是说它只有一个 qg network interface。当 external network 添加多个 subnet 之后,只有第一个被当作 external subnet,其余的都会被当作 internal subnet。
) L9 T+ B1 k% E4 M: c9 ~8 }(2)在 qrouter 的路由表之中,
5 J) G, b3 `6 O" {" ^ 8 l: P5 f% }9 w4 Z
root@controller:/home/sammy# ip netns exec qrouter-39a77439-8a28-49c1-bf97-ac931510631b route1 F! @3 r8 r; s8 ?4 M% x
Kernel IP routing table
4 C, e& _8 c9 N- iDestination Gateway Genmask Flags Metric Ref Use Iface4 l- O8 b0 E( ^, F
default 10.62.227.1 0.0.0.0 UG 0 0 0 qg-e09fce07-cd
8 k2 W o( }% u10.0.0.0 * 255.255.255.0 U 0 0 0 qr-b1eaae00-e5
; P( `$ a: o |+ M1 T6 B0 D10.62.227.0 * 255.255.255.0 U 0 0 0 qg-e09fce07-cd
) a: v* F5 U8 Z+ i2 U8 Z/ i D6 o10.62.228.0 * 255.255.255.0 U 0 0 0 qg-e09fce07-cd
+ V7 i4 D. h5 P3 S- B" N10.62.228.0 * 255.255.255.0 U 0 0 0 qr-124ff148-b7
- k! i9 z5 S3 Q/ o: k( A7 V! A11.0.0.0 * 255.255.255.0 U 0 0 0 qr-16d9b0cc-38
: _! c: R" `' w8 x1 Q20.0.0.0 * 255.255.255.0 U 0 0 0 qr-0bb8efeb-102 i& ?* ^8 J# w5 C8 { v
4 |" j( ?) A% { 0 u* ^ v3 [* n# ~+ L' q. e
2. linux-bridge-agent 工作过程分析
9 d# C0 [7 Z$ N# S8 p& M+ |5 m8 t(1)linuxbridge-agent 会启动一个循环,不断扫描上面红框中的 tap 设备
6 o# }4 l" @5 j; y! o" p7 l 6 u$ t% L- A8 H8 z* R0 p4 i0 ]% a
def daemon_loop(self):
; D" n/ M$ j) _1 Z) j E...$ I" P9 {. u; O5 J% B
while True:
. R- Y" O& M/ T$ ?, L start = time.time()
6 G0 w, ]" B6 ~% {3 h: E. ..
5 Y% _, ~) V; V4 r1 J8 P5 E2 P
7 ]4 L. A# g# Z% @0 Q device_info = self.scan_devices(previous=device_info, sync=sync)
3 z( i. R# a: K0 u sync = False3 c4 R1 Y* n+ [. O9 [1 O
+ [) l$ C' q% L+ p G& w
if (self._device_info_has_changes(device_info): p8 Y Q0 R+ l- d/ t6 @3 Z
or self.sg_agent.firewall_refresh_needed()):- H" e3 M" M* V* G9 {" c. ~
LOG.debug("Agent loop found changes! %s", device_info)/ e; R* C- J! j/ O% ?1 T! O
try:
+ E1 {) a9 R$ }6 O: K) p) E- h2 ^ sync = self.process_network_devices(device_info)4 Q( e: I- o6 j
except Exception:
, s! c) v6 y* s' G LOG.exception(_LE("Error in agent loop. Devices info: %s"),; y4 E" [! F; h( O& L9 A7 F- I) A9 c
device_info)1 Y" k3 y5 E5 o( W& W
sync = True
6 F6 t4 `; D5 _# j: `+ j) E / @4 b( c$ V ~7 s
这是它首先找到的 devices:
) j0 n! ^+ ]9 o# c( w4 `7 j$ k1 q5 X(Pdb) p bridge_lib.get_bridge_names()5 m& T0 w( F# g& n9 ?2 V+ z& G
['brq85925305-b4', 'virbr0', 'brq971ffda2-e5', 'virbr0-nic', 'tapb1eaae00-e5', 'tapf70543dd-0f', 'vxlan-25', 'vxlan-10', 'tap0bb8efeb-10', 'lo', 'tap60dbdc2f-a0', 'tap795e6e86-94', 'ens224', 'ens192', 'ens160', 'tap798c87d1-a2']
6 Y+ c( c3 d9 F然后过滤出 tap 设备:! N* L% }6 k# l7 k# d- b
get_all_devices()->set(['tap0bb8efeb-10', 'tap60dbdc2f-a0', 'tap795e6e86-94', 'tap798c87d1-a2', 'tapb1eaae00-e5', 'tapf70543dd-0f'])1 k9 W' z( B7 d+ U2 y2 \
(2)根据 previous 中保存的历史数据,再接合服务器端和本地更新时间,计算出需要更新的tap设备列表:. X4 J# [+ n8 Y& M; a6 ~
{'current': set(['tapf70543dd-0f', 'tap60dbdc2f-a0', 'tapb1eaae00-e5', 'tap795e6e86-94', 'tap0bb8efeb-10', 'tap798c87d1-a2']), 'timestamps': {'tapf70543dd-0f': 1476956816.672447, 'tap60dbdc2f-a0': None, 'tapb1eaae00-e5': 1476956816.672447, 'tap795e6e86-94': None, 'tap0bb8efeb-10': 1476689797.1378036, 'tap798c87d1-a2': 1476689701.1349163}, 'removed': set([]), 'added': set(['tapf70543dd-0f', 'tap60dbdc2f-a0', 'tapb1eaae00-e5', 'tap795e6e86-94', 'tap0bb8efeb-10', 'tap798c87d1-a2']), 'updated': set([])}; J5 b; Z# k2 Y/ \; O3 b
(3) 通过 RPC 获取 tap 设备的详细信息
: _2 R0 r& o6 F% [" a
' M& ~0 R. O1 `$ Q; j(Pdb) p devices( K7 p) i& k. g" b2 O9 g
set(['tapf70543dd-0f', 'tap60dbdc2f-a0', 'tapb1eaae00-e5', 'tap795e6e86-94', 'tap798c87d1-a2', 'tap0bb8efeb-10'])
% R7 V! T) q0 U/ c, X
8 H3 O7 |% D* M& l$ j, F5 P* L6 y+ \0 Q/ ]' {6 k, r9 N
devices_details_list = self.plugin_rpc.get_devices_details_list
. ?) O" U( V" g1 n* t. o
5 Y' J, f+ S3 ~3 A. d Z(Pdb) p devices_details_list
5 E' T! w7 l' P2 |+ P[{u'profile': {}, u'network_qos_policy_id': None, u'qos_policy_id': None, u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'971ffda2-e567-40a0-a2c8-b31a577fd4d3', u'segmentation_id': 10, u'device_owner': u'network:dhcp', u'physical_network': None, u'mac_address': u'fa:16:3e:5c:bf:11', u'device': u'tapf70543dd-0f', u'port_security_enabled': False, u'port_id': u'f70543dd-0f1b-4e1d-93c7-33f4f3d7a709', u'fixed_ips': [{u'subnet_id': u'3d596991-de8f-4ae4-8913-89426a8abbd7', u'ip_address': u'10.0.0.10'}], u'network_type': u'vxlan', u'security_groups': []}, {u'profile': {}, u'network_qos_policy_id': None, u'qos_policy_id': None, u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'96609bfa-0e22-4bb7-8dba-6ef532ea6076', u'segmentation_id': None, u'device_owner': u'network:router_gateway', u'physical_network': u'provider', u'mac_address': u'fa:16:3e:77:78:86', u'device': u'tap60dbdc2f-a0', u'port_security_enabled': False, u'port_id': u'60dbdc2f-a01b-446d-bb5b-26ffac19a045', u'fixed_ips': [{u'subnet_id': u'afa7d205-3026-439f-aca7-295a9f9b2a71', u'ip_address': u'10.62.227.151'}], u'network_type': u'flat', u'security_groups': []}, {u'profile': {}, u'network_qos_policy_id': None, u'qos_policy_id': None, u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'971ffda2-e567-40a0-a2c8-b31a577fd4d3', u'segmentation_id': 10, u'device_owner': u'network:router_interface', u'physical_network': None, u'mac_address': u'fa:16:3e:81:1b:37', u'device': u'tapb1eaae00-e5', u'port_security_enabled': False, u'port_id': u'b1eaae00-e504-41f8-93a4-643687155bea', u'fixed_ips': [{u'subnet_id': u'3d596991-de8f-4ae4-8913-89426a8abbd7', u'ip_address': u'10.0.0.1'}], u'network_type': u'vxlan', u'security_groups': []}, {u'profile': {}, u'network_qos_policy_id': None, u'qos_policy_id': None, u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'96609bfa-0e22-4bb7-8dba-6ef532ea6076', u'segmentation_id': None, u'device_owner': u'network:dhcp', u'physical_network': u'provider', u'mac_address': u'fa:16:3e:5f:94:7d', u'device': u'tap795e6e86-94', u'port_security_enabled': False, u'port_id': u'795e6e86-94af-4b72-ae1a-5a324a017774', u'fixed_ips': [{u'subnet_id': u'afa7d205-3026-439f-aca7-295a9f9b2a71', u'ip_address': u'10.62.227.150'}], u'network_type': u'flat', u'security_groups': []}, {u'profile': {}, u'network_qos_policy_id': None, u'qos_policy_id': None, u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'85925305-b477-4cc6-9654-67d9bf1e7cd8', u'segmentation_id': 25, u'device_owner': u'network:dhcp', u'physical_network': None, u'mac_address': u'fa:16:3e:25:27:99', u'device': u'tap798c87d1-a2', u'port_security_enabled': False, u'port_id': u'798c87d1-a2d8-4df7-b7fc-5ab30918a0de', u'fixed_ips': [{u'subnet_id': u'4575c7f1-7f08-4917-9904-ec65af38619b', u'ip_address': u'20.0.0.100'}], u'network_type': u'vxlan', u'security_groups': []}, {u'profile': {}, u'network_qos_policy_id': None, u'qos_policy_id': None, u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'85925305-b477-4cc6-9654-67d9bf1e7cd8', u'segmentation_id': 25, u'device_owner': u'network:router_interface', u'physical_network': None, u'mac_address': u'fa:16:3e:9f:18:a9', u'device': u'tap0bb8efeb-10', u'port_security_enabled': False, u'port_id': u'0bb8efeb-108f-409a-82e7-c4c20f0d4f69', u'fixed_ips': [{u'subnet_id': u'4575c7f1-7f08-4917-9904-ec65af38619b', u'ip_address': u'20.0.0.1'}], u'network_type': u'vxlan', u'security_groups': []}]
# r" L" K; _2 I" ], U) V
/ D$ W: E& [( y0 @, {: Z(4) 对需要处理的设备,调用 self.process_network_devices(device_info) 函数进行处理. q; r1 g/ @/ L! r1 \
(5). 调用 plug_interface
* f. B6 N" A3 Y' ~$ z, m% x/ }interface_plugged = self.mgr.plug_interface(network_id, segment,device, device_details['device_owner'])" Q7 Z( Q8 _0 T; A6 F
(6). 需要的话,使用已经配置的或者新建 linux brige,并将 physical interface 设备加入其中8 X" P$ y1 v5 O% S. _
bridge_name = self.get_existing_bridge_name(physical_network) #获取为 physical network 配置的 linux bridge
7 F* O3 z+ }5 h! U) ~bridge_name = self.get_bridge_name(network_id) #或者根据 network id 生成 bridge name
1 l2 N% _) S$ D j+ }(7).根据不同的网络类型,分别处理 vxlan bridge,flat bridge 和 vlan bridge6 v4 J3 z( \! w
% G! b0 h9 p* ^2 b def ensure_physical_in_bridge(self, network_id,: x& |/ \/ c5 M; U$ |
network_type,* U6 d& i! Y6 b" _4 x5 ?
physical_network,
0 @7 Y% I4 E& C+ l8 ~ segmentation_id):* E+ V6 E8 S& G0 o, [; g; B+ N
if network_type == p_const.TYPE_VXLAN:
' R9 [+ r' c4 G if self.vxlan_mode == lconst.VXLAN_NONE:0 [& b# U1 x* H6 V
LOG.error(_LE("Unable to add vxlan interface for network %s"),' T) L4 H+ s, [0 K7 |
network_id)
5 T# q5 V* E) v% c1 x/ x return m6 r9 N) g0 {; S, i8 H
return self.ensure_vxlan_bridge(network_id, segmentation_id)
) I7 E; B" [4 I2 o% r# ?
# w, \: y) C9 r' v$ i G/ { # NOTE(nick-ma-z): Obtain mappings of physical bridge and interfaces
- ?4 r% L0 \9 ~/ E, Y7 { physical_bridge = self.get_existing_bridge_name(physical_network)6 b! \3 M; g' o' ^
physical_interface = self.interface_mappings.get(physical_network)
3 b9 q& `* S+ T, D. ` if not physical_bridge and not physical_interface:# E9 f- r1 p A3 L* f
LOG.error(_LE("No bridge or interface mappings"
1 {7 y+ n2 P& }/ j( V7 i6 K' G " for physical network %s"),6 j3 L( N0 Z' q0 G9 Q% }
physical_network)( X" w0 p$ f" s# d
return
! H, {" v* i$ T if network_type == p_const.TYPE_FLAT:
0 a5 P; C6 y# b9 a, q! W) b return self.ensure_flat_bridge(network_id, physical_bridge,
- U% w/ {0 j$ T physical_interface)
! N5 o: i0 J9 m. v4 d elif network_type == p_const.TYPE_VLAN:( c$ y( S0 A% H6 ?" |' [
return self.ensure_vlan_bridge(network_id, physical_bridge,1 ?2 k% z/ p# x3 j
physical_interface,
" Q% N( |* c' ~) y7 e segmentation_id)9 H, ^4 |9 N! E1 b
* M$ }" L3 C6 O+ z& z* i! v对于 flat 类型的网络,调用 ensure_physical_in_bridge. l! T" W' V) _& I
def ensure_physical_in_bridge(self, network_id,network_type,physical_network,segmentation_id)# c6 P# |+ o' g/ P. K
if network_type == p_const.TYPE_FLAT:3 l; E- @- w! F: K1 l5 G
return self.ensure_flat_bridge(network_id, physical_bridge,physical_interface)
& w) r. y2 H0 y M; w% |如果有配置 physical bridge 的话,使用它;否则创建 bridge,并将物理网卡配置的 ip 地址和 gateway 从网卡挪到 linux bridge2 [7 h$ ^4 G) w6 {' \% x
3 ~6 w% K/ G4 ~* ~# Z i5 O+ B
def ensure_flat_bridge(self, network_id, phy_bridge_name,physical_interface):# E9 N( c1 x3 k* B. x2 b
"""Create a non-vlan bridge unless it already exists."""1 A" Z" Q' n* O, e4 i* E
if phy_bridge_name:
/ o8 S& v) t7 I& q+ q return self.ensure_bridge(phy_bridge_name) #获取预先配置好的 linux bridge- l9 o5 n% h( }7 `6 r. T# R3 j
else:
+ h* X* H7 M# \) j8 t0 j bridge_name = self.get_bridge_name(network_id): o5 ]' S$ @8 C% T! T2 u
ips, gateway = self.get_interface_details(physical_interface)# p! _- k! S( ?' S& P
if self.ensure_bridge(bridge_name, physical_interface, ips,gateway): #创建 bridge# K5 f2 S, V" s
return physical_interface
0 `( @5 I3 P2 U8 e& U- x 1 x& G/ w1 x" e; t' q7 m1 R) P
对于 vxlan 类型的 network,需要创建 vxlan interface7 I9 F/ N% O1 {* S
( W! F* i% i |- B% @. a
def ensure_vxlan_bridge(self, network_id, segmentation_id):
( N* e( l6 |3 |; b; i, F5 s/ C& x """Create a vxlan and bridge unless they already exist.""". w# p* j8 F4 E9 u' P
interface = self.ensure_vxlan(segmentation_id)
: [/ y) M% f& ~+ z5 m if not interface: t6 Z# L9 |1 \# o' }( B
LOG.error(_LE("Failed creating vxlan interface for "1 A: g8 W. k" V
"%(segmentation_id)s"),8 m! U; b3 Q+ e( W- H
{segmentation_id: segmentation_id})
- r9 o }& ?( l4 T return0 [: i0 U( o$ k; l/ j
bridge_name = self.get_bridge_name(network_id)* p( I o6 u9 E- E5 d- s- } Y
self.ensure_bridge(bridge_name, interface)& e5 T: X E# l& J" x4 J% C
return interface
- x; M9 ~- S( @5 H: `
, E* T6 N6 ]! Z& ^* t- \/ p创建 vxlan interface:
- O) k3 W+ U. H( u" I; F& T . u& ]+ y& Q& x. q0 g/ o
def ensure_vxlan(self, segmentation_id):1 V$ |2 Z5 w/ J- Q3 }( O6 | |* D$ k
"""Create a vxlan unless it already exists."""
5 G; \# q8 R' W interface = self.get_vxlan_device_name(segmentation_id). \& j, q; y- ^0 U( ]
if not ip_lib.device_exists(interface):# D K2 H1 F9 U. K7 \) D
LOG.debug("Creating vxlan interface %(interface)s for "
2 T7 ]7 U9 C1 n2 |) ]" k "VNI %(segmentation_id)s",; \& r+ g( N6 Y+ \% F
{'interface': interface,
% G/ x7 Z+ n/ |# k/ \* X 'segmentation_id': segmentation_id})0 S$ O; t0 Y; A/ S& ^: K# @, B
args = {'dev': self.local_int}. N% o0 R' p9 y3 e6 m
if self.vxlan_mode == lconst.VXLAN_MCAST:' P0 @9 |5 c z6 V2 T8 ]- r s3 u
args['group'] = self.get_vxlan_group(segmentation_id)" W. b5 @! i7 {3 F0 N
if cfg.CONF.VXLAN.ttl:' ~9 L5 n! O4 J. M( \/ ^* e$ z
args['ttl'] = cfg.CONF.VXLAN.ttl
; K8 l+ I0 W3 C+ N* ^! H# S: j. U if cfg.CONF.VXLAN.tos:
# P; H9 w' J' [, H) J# M9 J args['tos'] = cfg.CONF.VXLAN.tos1 P5 s6 \1 N9 K% i/ }* N' R, [
if cfg.CONF.VXLAN.l2_population:
# U7 \1 G7 {* W" _ args['proxy'] = cfg.CONF.VXLAN.arp_responder# s# i0 d6 Z/ O' J
try:
; b3 K" F$ [; b int_vxlan = self.ip.add_vxlan(interface, segmentation_id,
2 [. ` F2 N1 {8 \8 X) M1 h **args)
. i6 K' w, I4 A; S! S9 C) y
" s) `6 n( k% p$ a" c( X& `(8). 将 tap 设备加入到 linux bridge 中
) Y) m5 q8 V) F3 ^2 _! Ebridge_lib.BridgeDevice(bridge_name).addif(tap_device_name)
, T! |* E2 G: s; `8 U(9). 如果将一个 tap 设备被删除,那么 linux-bridge-agent 会发现:1 s4 B4 K7 A- ^5 d k
2016-10-26 10:29:58.347 30219 INFO neutron.agent.securitygroups_rpc [req-e3264065-6414-4b5a-8d2b-dfafad6fdde8 - - - - -] Remove device filter for set(['tap60dbdc2f-a0'])
8 O4 B+ P& \0 `, \& @2016-10-26 10:29:58.433 30219 INFO neutron.plugins.ml2.drivers.agent._common_agent [req-e3264065-6414-4b5a-8d2b-dfafad6fdde8 - - - - -] Attachment tap60dbdc2f-a0 removed% R5 v% @# Z" S I: L
2016-10-26 10:29:58.536 30219 INFO neutron.plugins.ml2.drivers.agent._common_agent [req-e3264065-6414-4b5a-8d2b-dfafad6fdde8 - - - - -] Port tap60dbdc2f-a0 updated.
2 Q; W, o) _; A; F' U$ S3. 关于上述工作过程的简单结论/ p) H2 ]6 b( N: k) R2 Z) U+ R% K
3.1 简单结论5 U( u. }) O0 M' V
1. l3agent 和 dhcpagent 创建 network namespace 时创建 tap 设备,和 network namespace 中的 interface 是一对 veth pair。当手工删除 tap 设备时,相应的 veth endpoint 也会被删除。
3 s: a6 n/ E1 Q) `2. linuxbridgeagent 不断扫描服务器端和本地的 tap 设备
1 L3 O, M8 V- }5 B6 c3. linuxbridgeagent 获取需要增加和修改的tap设备列表
8 Q6 J" O! } F: d; z7 e4. 对于需要增加的 tap 设备,获取其详细信息,主要是 network_id,network_type,physical_network,segmentation_id,device_owner 等,然后根据这些信息,创建 linux bridge,并加入所需要的 interface# Q( t: u4 D. ?% V
5. 创建所需要的 linux bridge,并将 physical interface (provider network 的 physical interface 或者 tenant network 的 vxlan interface)加入 bridge,并且将 tap 设备也加入该 bridge
7 Y- I$ R: d" y& T! `% j" K6 v7 Z6. 如果发现某个 linux bridge 没有创建出来,首先需要查看有没有相应的 tap 设备存在;如果 tap 设备不存在,则查看相应的 qdhcp 或者 qrouter 中时候有interface D% l" s1 m' ~6 ^7 ^. q) f
7 [! C/ h- l8 C& M! S* c- t) W具有多个 VLAN 租户网络时候的网络元素示意图:
4 |: K. e# r5 j8 r 6 s1 ^. a$ T# M% {, m6 Z9 s2 A# K
, n% D8 d$ ], z
( l! x8 f! F/ T$ |5 ]
1 ^9 N: J- U6 { R, s 3.2 关于 unnumber interface
) Y3 F. [3 r( Z" A, LOpenStack 官方的 host networking 配置中,连接外网的 interface 可以是 unnumbered 的,从字面意思理解,就是该 interface 上不需要配置 IP 地址。
, Y6 g7 j9 t. K0 W6 k' ~9 L! f
3 i, i2 o3 s5 }配置的时候,修改 /etc/network/interfaces:
9 X9 A+ R* l5 S3 ?" }# The provider network interface
7 v1 I- b' A" q" c1 k+ f( O5 sauto ens2246 P, e+ l( u4 f& O% X, F( B
iface ens224 inet manual+ h+ ?. s/ l) X9 u
up ip link set dev $IFACE up ~+ s, B" [9 g1 p: `
down ip link set dev $IFACE down
* c) |& i3 z; x配置好以后:" L4 y0 b- o$ @- Z% S% t/ H; z4 ~
' Y) [( z* x4 m2 u6 d
root@controller:/home/sammy# ifconfig ens224
+ `- O- F, |; w7 D( F2 _ens224 Link encap:Ethernet HWaddr 00:50:56:9c:4d:94! ^" w( U9 b$ Z/ T. q1 q2 ?
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
3 A B _" Q8 y3 ~) U RX packets:27300737 errors:0 dropped:0 overruns:0 frame:0
/ L; e3 l- P% W# H TX packets:61547 errors:0 dropped:0 overruns:0 carrier:0
) h2 j N; m2 Q0 e; T collisions:0 txqueuelen:10003 X) T' ?- u+ q+ Y; X
RX bytes:31951077598 (31.9 GB) TX bytes:5966060 (5.9 MB)
3 t& X6 V; r2 t" Y" `
* L, m/ X% Y: q# o+ n: Aroot@controller:/home/sammy# ifconfig brq96609bfa-0e! p) b* _6 D& r" ~3 y% c p" b
brq96609bfa-0e Link encap:Ethernet HWaddr 00:50:56:9c:4d:94& M* H* s- Z; L2 k
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1' w- b' @' A! ]' Q
RX packets:32855 errors:0 dropped:0 overruns:0 frame:0
; G$ Z6 C9 w1 F. o2 X- h1 D2 s TX packets:2 errors:0 dropped:0 overruns:0 carrier:0! W+ `. y% |# i
collisions:0 txqueuelen:10006 C1 _ U5 ?: x; \5 A
RX bytes:2731030 (2.7 MB) TX bytes:84 (84.0 B)2 M4 H, c" ]& |% J9 R6 N: s
: K, y4 [6 j# C& p5 n# @
具体原理不详,但是应该是因为 qrouter 的 qg network interface 和物理网络中的路由器的网卡之间是网络二层,因此中间的设备都是属于二层的,因此不需要处于网络三层的 IP 地址。; V/ {/ x2 p; _; R& o
4. 使用 linux bridge 时的拓扑结构
, b+ p# P/ D7 ]1 [5 N4 e4.1 网络节点上- K5 b; f, b4 H( x2 h
为了更清楚,我们来对比着看 linux bridge 和 ovs 的两种方案:# C& l, r5 k& n5 v
linux 方案:
0 I5 K5 x5 D' v" N % p9 o& k) s+ R$ m8 ]' }
网络服务:
$ x5 ~, k. v4 Y$ H' m• Linux bridge agent$ k& J. n. z& `+ ?
• L3 agent
( d, O: |$ W: B q# g6 p* I• DHCP agent
, o9 H0 r7 V$ A8 D) N# G2 R9 f• Metadata agent
* y. I. \: |9 g5 ` i/ r( FLinux bridge agent 会为每个 VLAN 虚拟网络创建一个 VLAN Bridge,它连接多个网元:
, R' U K1 M. l$ o8 T• VLAN 子接口,从物理网卡(图中的 interface3)上创建,每个子接口对应一个VLAN ID,其名称格式为 device.sid,其中 device 是物理网卡名字比如 eth0,sid 是 vlan id。/ h3 `( U8 ?0 R8 h
• 连接虚拟机的 tap 接口4 ~- J6 u; r6 H2 C# m% @3 L
• 和 qrouter 连接的 tap 接口. f8 _" b1 U2 D" K
• 和该网络的 qdhcp 连接的 tap 接口
2 L4 m( Y: m" G. l如果同时有 VXLAN 虚拟网络的话(linux-bridge 不支持GRE 隧道模式),会为每个 VLAN 虚拟网络创建一个 Tunnel bridge。它连接多个网元:
4 |( j: q; g: X1 {8 I2 ]; b• vxlan interface,这种接口每个虚拟网络一个,名字格式为 vxlan-sid,其中 sid 是分段ID。9 A1 z9 w- A" ]: q2 j
• 连接虚拟机的 tap 接口
& o [" W* I% _( h O( z* y• 和 qrouter 连接的 tap 接口4 [# k: I ]( w, a( J# j
• 和该网络的 qdhcp 连接的 tap 接口
A2 b; W# d3 C- e1 I安全组规则在 tunnel bridge 和 vlan bridge 上。
6 ]! J2 \& \1 T* R2 X2 [( dOVS 方案:
/ L% m: t: D% ~4 n; @8 Z
, _1 Y7 Y P- b/ j4 Z' U' P这里面,br-int 会负责加本地 VLAN 标签,br-tun 会负责将 VLAN ID 转换为 VXLAN ID。
1 i( x. G0 O/ |; s4 k
' ]" B1 n! c6 D' n. b* p) m% w4.2 计算节点上
+ T" F- u& n3 g7 ]1 t% Q' ^同样来对比着看。
`4 Y8 i% K8 {3 N3 H A9 T" Y0 klinux bridge:
: S1 i) V/ F; ?7 a6 y j- P
7 T2 c% R; b4 J2 l) W5 F网络服务:
/ R/ {* i- V, U' [• Linux bridge agent; J$ t+ V5 m, g9 |( Z
和网络节点类似,只不过没有 qrouter 和 qdhcp,不在赘述。
) f: c& l- P9 q. B( d" |. _1 }OVS:! ^& }, P r) h4 ^
- j |9 M( V7 C0 p - {6 @1 X: l+ x9 r
OVS 放在在 br-int 上实现 VLAN 标签,在 br-tun 上实现隧道,在 qbr linux bridge 上实现安全组。
. R' O I9 \; n( F 0 ^; g6 g" t/ r9 M9 S/ E
4.3 网络路径 - 南北向网络流向% }6 }8 }# O0 |' t9 ~" J% e% [( n% D
- L& v/ ^7 w" S# a V0 O- ~) k: xVLAN 网络和VXLAN 网络井水不犯河水。这图上的配置中,计算节点和网络节点上的物理网卡都分开了。
$ T; u f8 g# N0 [! w$ C5 j0 D4.4 网络路径 - 东西向(不同网络)) C+ M7 E! k5 M* R, n
6 W) D9 D- K% y0 x, Y0 f' D4 z
4.5 网络路径 - 东西向(同一个网络)
7 Y: l$ C3 [! Q# Y; N 7 P5 O1 n# T: x# ^1 A4 |2 o9 }3 d4 k
, n% r9 q5 `" a Q; w T8 t& y P6 A请详细说明和配置,请参阅参考文档。8 c7 m' p: i) k
5. 一点结论 _" l7 l2 b. k/ H# p7 h
和基于 OVS 的二层网络相比,8 e9 e/ @1 ?. x1 O7 Y) m; q# ^
• 功能和架构上:基于 linux bridge 的实现还是有一些短处,比如每个虚拟网络就需要一个网桥,这在大规模环境中会带领资源使用和管理上的问题。其好处是本身架构比较清晰。
" r' \; a/ h4 y# T# J6 {• 性能上:基本上差不多,如下图所示,不管是 vxlan 还是 vlan。3 M1 [2 @4 `5 J, B6 w# W# c
! i- l+ W, v" G4 k* v' b
$ x1 G. d' J6 U8 G4 W; f |
|