- 积分
- 16843
在线时间 小时
最后登录1970-1-1
|

楼主 |
发表于 2019-10-25 11:23:29
|
显示全部楼层
虽然大部分的OpenStack 部署环境中,都会使用 Open vSwitch 来作为虚拟交换机来实现二层网络功能,但是Neutron 仍然支持使用 Linux bridge 作为虚拟交换机来实现二层网络。本文就此做些分析和说明。
( \( g; c8 [/ W. N: s2 V. c) p同时要指出的是,OpenStack 官方已经把 linux bridge 实现标记为 legacy 的了,文档从 2016 年后也没怎么更新了。这是因为,linux bridge 和 OVS 相比,只支持基本的网络功能即二层交换,但不支持VLAN 标签和隧道。因此,linux bridge agent 利用linux 内核功能(VLAN 子接口和 VXLAN 接口)来实现VLAN 标签和隧道。3 b G! x/ P/ d& M# d
, T8 ]9 C# M. }. I4 A! q' E3 i 1. 测试环境
+ O- M& w3 k" P% X6 y8 G4 Y以下面的环境为例(网络节点上):
+ N. L/ {0 V" w* ?( y( u: ~4 T(1)linux bridge
! ]# d0 P9 j. E' {9 h% [' j: N 6 l; j# _( X' s4 P$ A6 c
root@controller:/home/sammy# brctl show- y. A5 E& E6 u1 a
bridge name bridge id STP enabled interfaces1 s! X O5 a- o* F7 t; g: t
brq85925305-b4 8000.563534c8d02d no tap0bb8efeb-10
" }( q9 {" l3 \: G5 R tap798c87d1-a2* H7 ~1 t1 T% u; q# J9 j4 L4 W) l
vxlan-25
( Z/ m- C/ m8 B8 Wbrq96609bfa-0e 8000.0050569c4d94 no ens224
5 X% J; p/ M% G, H; ^ tap60dbdc2f-a0
; u; x- J% Y" m, P* t" dbrq971ffda2-e5 8000.a6acb08e4fd6 no tapb1eaae00-e5
* i* V& x1 |3 d tapf70543dd-0f* l7 m6 W. m# q" f
vxlan-10
9 T: h2 C2 Q0 w. a) R
, [ u3 \! }6 W4 w4 f* ?1 ?(2)OpenStack 网络和 network namespace:
1 i' N; N7 ?/ ]: A. j$ H
+ S0 ~, M, `0 Q1 yroot@controller:/home/sammy# neutron net-list
- ^' x* C6 x( _: E X6 M+--------------------------------------+---------+-----------------------------------------------------+! ^. [; t4 L; o7 h9 S" \+ Z! `
| id | name | subnets |8 e% B$ T9 C: N
+--------------------------------------+---------+-----------------------------------------------------+
: Y% T: d8 H9 e. V6 ~; a1 O6 S! Q8 N| 96609bfa-0e22-4bb7-8dba-6ef532ea6076 | extnet | afa7d205-3026-439f-aca7-295a9f9b2a71 10.62.227.0/24 |
* G7 R2 p3 F- _+ f| 971ffda2-e567-40a0-a2c8-b31a577fd4d3 | appnet | 4c68eacb-bf3e-408a-a941-94e93eddb22b 11.0.0.0/24 |0 C) ?. K2 j9 A
| | | 3d596991-de8f-4ae4-8913-89426a8abbd7 10.0.0.0/24 |6 b _4 a& k( z7 f, m
| 85925305-b477-4cc6-9654-67d9bf1e7cd8 | appnet2 | 4575c7f1-7f08-4917-9904-ec65af38619b 20.0.0.0/24 |
/ ]2 z$ C3 h7 G2 ^1 a5 n/ b, [+--------------------------------------+---------+-----------------------------------------------------+
- I( T8 ], L) i+ groot@controller:/home/sammy# ip netns
( V, @ E& H5 Eqdhcp-85925305-b477-4cc6-9654-67d9bf1e7cd8 (id: 2)8 o+ Z7 H/ S: G% r
qdhcp-971ffda2-e567-40a0-a2c8-b31a577fd4d3 (id: 1)
& u/ Y9 N/ P" p" u8 Aqrouter-39a77439-8a28-49c1-bf97-ac931510631b (id: 0)4 y6 b6 x+ r0 E% Z& [3 d8 c# P
& |' w0 Z- V6 W* ?+ @(3)示意图:
7 Y! x- ^$ I: W/ Y1 c
) X* e& i* f( @- s9 W(4)说明:
! W) N9 a2 C% n# h4 g• qdhcp 和 qrouter 都是 linux network namespace 实例
% U1 m4 ^$ s0 B: m" L$ W7 K• qdhcp network namespace 的数量等于启用了 DHCP 的 Neutron network 的数量。' d6 W' v7 A* q$ w4 |
o 当一个 network 中存在至少一个 subnet 启用了 DHCP 之后,会有一个 qdhcp network namespace 被创建出来;
" C' }* ]# L4 {, h: y, Y2 s% \o 当一个 network 中多个 subnet 启用了 DHCP 时,它们共用一个 qdhcp,以及 dnsmasq。
` b- c& n5 O f# C5 [, K' D$ ko 其 name 使用 network id,比如 qdhcp-85925305-b477-4cc6-9654-67d9bf1e7cd8 K! w- ^( b: n' q: }$ x
• qrouter network namespace 的数目等于 router 的数目,也就是说,系统中一共有几个 router,那么就存在几个 qrouter network namespace
: q8 c3 f8 k9 o8 ~% n- o• brq linux bridge 的数目等于 neutron network 的数目,其 name 是 network id 的前几位,比如 brq96609bfa-0e$ z3 ^) L3 O6 J* ]. t- n
• 一个 network 的 qdhcp network namespace 和其 brq linux bridge 一定有连接# B' b& ]' ?' v
• qrouter 之内的 network interface 分两种,一种是 qr 开头的,每个连接到 router 之上的 subnet 都有一个;还有一个是 qg,每个连接到 router 的 external subnetwork 有一个( W6 N! U" G( N! o/ J
• qrouter 的每个 network interface 都通过 veth 连接到所在网络的 qbr linux bridge 上
$ c: e0 X/ M, w• qbr linux bridge 连连接两种物理设备,一种是 vxlan interface,每个 tenant network 有一个,另一种是在 physical network 对应的物理网卡上创建的子接口(sub-interface)
' s" j# k* f) ~- ]: d; N' G• 对于 physical network 的 qbr 来说,用户可以指定它,并且在linuxbridge_agent.ini 中通过 bridge_mappings = List of <physical_network>:<physical_bridge> 进行配置;也可以不指定,此时 agent 会创建它。当同时配置了 physical bridge 和 physical interface 时,前者优先。' J+ \8 g2 @: R/ ?! o, E9 n
如果 external network 中有多个 subnet 的话:
, T1 |+ F# E8 S: [& L: z(1)每个 qrouter 只允许有一个 External Gateway,也就是说它只有一个 qg network interface。当 external network 添加多个 subnet 之后,只有第一个被当作 external subnet,其余的都会被当作 internal subnet。4 J" a# Q% z# Q' V' l8 r
(2)在 qrouter 的路由表之中,
' Q0 a+ ^" M4 J: C0 \
( H# z% |: B9 U W# V, _4 b* d! L7 L; {root@controller:/home/sammy# ip netns exec qrouter-39a77439-8a28-49c1-bf97-ac931510631b route1 \ f9 I: n9 R) c @) n* O
Kernel IP routing table
- _% g# h/ B+ u" j; S7 Y+ W# WDestination Gateway Genmask Flags Metric Ref Use Iface6 y% |7 Z% |% e" B
default 10.62.227.1 0.0.0.0 UG 0 0 0 qg-e09fce07-cd0 J+ j! ]; [) \5 M8 [+ B3 h
10.0.0.0 * 255.255.255.0 U 0 0 0 qr-b1eaae00-e5
) p X; K ^7 E0 d: }10.62.227.0 * 255.255.255.0 U 0 0 0 qg-e09fce07-cd4 o |' O7 P# r" Q4 D0 F
10.62.228.0 * 255.255.255.0 U 0 0 0 qg-e09fce07-cd
1 U0 O* d' Y7 S10.62.228.0 * 255.255.255.0 U 0 0 0 qr-124ff148-b7
- v9 p. c; b9 w. C11.0.0.0 * 255.255.255.0 U 0 0 0 qr-16d9b0cc-38; e) ~2 C7 @6 m( W5 o B2 u" y5 C5 M
20.0.0.0 * 255.255.255.0 U 0 0 0 qr-0bb8efeb-10
- R+ e& w3 D- O# c2 P
/ W) |8 S( h4 D C P) w G
6 q5 K! q8 X( s3 \2. linux-bridge-agent 工作过程分析" }% t# L9 }( U P) @; s4 g& M, o n
(1)linuxbridge-agent 会启动一个循环,不断扫描上面红框中的 tap 设备 M% L" @3 u1 {
@& e3 R& B) H z( i9 t, q) v def daemon_loop(self):
3 E. }" v' _% {0 u' O1 u..., P1 Y" d# B7 J8 ]( l1 y! h
while True:
4 M! Q+ z# b0 d& h. x start = time.time()
: x' q4 b2 P( k' |8 Q. .., u3 M7 D! g$ Q8 P9 f
/ k b$ c! t8 i* }3 [' N
device_info = self.scan_devices(previous=device_info, sync=sync). m2 `7 |2 t% O5 x$ e3 S% a4 v8 z
sync = False
. z, m ^' B3 y5 m! r! f o& r# J5 H: U' y/ Y
if (self._device_info_has_changes(device_info)
u) R; b* I, o3 K& } or self.sg_agent.firewall_refresh_needed()):( y9 L3 t' r, g \
LOG.debug("Agent loop found changes! %s", device_info)
. n. C) q, w5 B# V try:# t- g) B: X5 ]% O
sync = self.process_network_devices(device_info)5 j2 h4 y$ J# ?" l4 {5 F
except Exception:8 c7 N1 q' X9 m9 |9 [) O0 P8 I
LOG.exception(_LE("Error in agent loop. Devices info: %s"),' b& S+ m; H' Z9 \
device_info)7 l. H2 v" P) B* b2 y6 R/ o2 v
sync = True- y3 E. M7 \9 p2 L$ A* g) }
# x% _9 L3 V" o: ]
这是它首先找到的 devices:0 D9 W0 ^8 b. t9 ^4 C& \3 E$ |
(Pdb) p bridge_lib.get_bridge_names()
; H! n8 |! L/ g' N0 r['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']3 U" P% r: E H* D" o
然后过滤出 tap 设备:
2 E) w) g. L4 y/ ?& C o8 Oget_all_devices()->set(['tap0bb8efeb-10', 'tap60dbdc2f-a0', 'tap795e6e86-94', 'tap798c87d1-a2', 'tapb1eaae00-e5', 'tapf70543dd-0f'])
' }3 @+ {2 V% f2 H$ j(2)根据 previous 中保存的历史数据,再接合服务器端和本地更新时间,计算出需要更新的tap设备列表:+ }! {. ^1 n5 {9 x8 ? i H1 C7 A! X
{'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([])}
+ r% U' f' g# K* m- ]" j& L: \% W2 K (3) 通过 RPC 获取 tap 设备的详细信息
$ U+ X7 ^5 x+ A" t1 x) L
( y7 V& I5 o1 m( i(Pdb) p devices
! s: a& l/ Y4 ~6 g: Lset(['tapf70543dd-0f', 'tap60dbdc2f-a0', 'tapb1eaae00-e5', 'tap795e6e86-94', 'tap798c87d1-a2', 'tap0bb8efeb-10'])
$ [0 Z1 T( V; ~, Y0 E) \' u/ u
/ V+ U3 U7 L9 w7 h6 b+ _ B' R5 q' j2 |5 g
devices_details_list = self.plugin_rpc.get_devices_details_list T+ H. s, Z2 B& b+ V5 F( b( n
( \( V$ m4 Z0 ~; m; J8 p(Pdb) p devices_details_list1 T, w+ l+ |, k7 D, G
[{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': []}]. j1 p; r# C/ o( K' {% R
$ w7 b' ^+ @; x8 h( S4 r
(4) 对需要处理的设备,调用 self.process_network_devices(device_info) 函数进行处理2 d1 S; d5 s! s4 B8 Q
(5). 调用 plug_interface
; [' Z. W7 k1 C3 Q% g$ dinterface_plugged = self.mgr.plug_interface(network_id, segment,device, device_details['device_owner'])
3 D. a1 l3 z( p3 V6 |7 H4 ](6). 需要的话,使用已经配置的或者新建 linux brige,并将 physical interface 设备加入其中 p. v% P2 j6 p, o
bridge_name = self.get_existing_bridge_name(physical_network) #获取为 physical network 配置的 linux bridge' G! W v' @/ w9 g2 x8 y
bridge_name = self.get_bridge_name(network_id) #或者根据 network id 生成 bridge name
1 c1 Z: o' e; u5 g! J$ U(7).根据不同的网络类型,分别处理 vxlan bridge,flat bridge 和 vlan bridge
5 x: b4 I. E5 }) @( Z
! ~4 s! \6 }, F) V. Z+ ]7 J def ensure_physical_in_bridge(self, network_id,& V# s- d& V6 @$ i
network_type,
: G; `/ I5 b! P+ ?9 Q physical_network,* L$ D3 Y, {9 _4 E- n: \
segmentation_id):
) A' k1 L8 c7 `0 ]: y if network_type == p_const.TYPE_VXLAN:8 ^8 v: o9 M; _, p0 b
if self.vxlan_mode == lconst.VXLAN_NONE:" w5 L5 g7 A* z/ e; t F
LOG.error(_LE("Unable to add vxlan interface for network %s"),
3 y: h% D m& G2 I0 J( i network_id)( x" N- z' F8 D1 v8 g# {
return
7 f5 x& Y5 _& d! O5 _# W return self.ensure_vxlan_bridge(network_id, segmentation_id)
( a" Y4 r3 z+ |& Y! ?7 D! f; w0 g3 P4 C8 E: y R/ P
# NOTE(nick-ma-z): Obtain mappings of physical bridge and interfaces' d) y- L( R4 }2 S
physical_bridge = self.get_existing_bridge_name(physical_network)% p3 D! m& h6 N; N. j& E, q
physical_interface = self.interface_mappings.get(physical_network)2 K5 O# W0 m9 O; k! O/ h
if not physical_bridge and not physical_interface:0 H/ t6 b E6 [! z: M8 h
LOG.error(_LE("No bridge or interface mappings"
6 w" S" @) Y- e8 c9 n J% h " for physical network %s"),
) e' t) D* T* {4 d7 D3 Q physical_network)5 f' G# i" ]3 S y. O O
return; V. Z; I2 \; V1 D
if network_type == p_const.TYPE_FLAT:& \5 u8 {, A7 f" a; H- p+ b
return self.ensure_flat_bridge(network_id, physical_bridge,& I) l9 T# j, L! T
physical_interface)
4 [! G& o. O* }: B4 O4 Z elif network_type == p_const.TYPE_VLAN:
4 X% g/ L4 ^" X' S0 W9 N& Z return self.ensure_vlan_bridge(network_id, physical_bridge,1 B9 M/ `& W: S2 y! D8 p( g
physical_interface,
, G) I/ M/ q8 G segmentation_id)
0 `- H7 F+ D* a - K' D5 J* C: }7 _8 ^
对于 flat 类型的网络,调用 ensure_physical_in_bridge
" c# J5 z2 d' [def ensure_physical_in_bridge(self, network_id,network_type,physical_network,segmentation_id)6 N1 ]& |8 ?& A+ h; g9 Q4 `6 p
if network_type == p_const.TYPE_FLAT:
) G7 g: z- N) C5 C return self.ensure_flat_bridge(network_id, physical_bridge,physical_interface)
+ x. o4 o1 L' n* P+ r2 S& y. K* n如果有配置 physical bridge 的话,使用它;否则创建 bridge,并将物理网卡配置的 ip 地址和 gateway 从网卡挪到 linux bridge% k! F: @8 U* _
( n( a3 r% p7 P$ A, I/ F: b1 u
def ensure_flat_bridge(self, network_id, phy_bridge_name,physical_interface):1 m: Z; D! x# b, q
"""Create a non-vlan bridge unless it already exists."""
5 G/ f, v" W1 R9 E/ P if phy_bridge_name:; n$ ?! ]; f' q8 [* {
return self.ensure_bridge(phy_bridge_name) #获取预先配置好的 linux bridge! Y1 M4 |" z0 ]7 V1 |0 L
else:
2 V) o# t) g* ?7 M! E% f7 m bridge_name = self.get_bridge_name(network_id)
- V9 O* d- U: T) n, W0 Z2 V ips, gateway = self.get_interface_details(physical_interface)$ f. f4 ?. k; h* h9 N& u
if self.ensure_bridge(bridge_name, physical_interface, ips,gateway): #创建 bridge( n: Q/ F: _6 |/ }8 Z. A. i. n8 U
return physical_interface3 H; d! c0 t+ ^3 r+ y _7 f3 s; \
+ e* C5 a$ E* Y6 i2 a3 [& g& |
对于 vxlan 类型的 network,需要创建 vxlan interface2 k+ v: m1 ~$ ^- w' g. m
% [9 ]. F+ F3 S3 d* e
def ensure_vxlan_bridge(self, network_id, segmentation_id):) c6 r# t7 Q5 w, t
"""Create a vxlan and bridge unless they already exist."""
3 L6 D0 F; ]8 T! n4 M interface = self.ensure_vxlan(segmentation_id)7 A2 k2 ~, S4 m$ Q) p
if not interface:' L( r' G1 K& o. x
LOG.error(_LE("Failed creating vxlan interface for "
0 @0 D# ]$ [& b/ c0 ]/ f "%(segmentation_id)s"),
8 G9 T. n" w: A$ D {segmentation_id: segmentation_id})
* T( m( o4 Z% `' v, A! l% L" b$ i0 | return' }& C. E$ I# F
bridge_name = self.get_bridge_name(network_id)' B+ L! o; H+ i+ h
self.ensure_bridge(bridge_name, interface)5 l+ ~ p. P* g) k1 R
return interface
) B" i! j5 Y9 E+ a" ^1 l! @+ B
4 X4 i0 N! K# [6 y' ]创建 vxlan interface:# A0 ]3 s6 t; J, p
. c! p9 w: T$ d& b- G" e$ r1 m def ensure_vxlan(self, segmentation_id):
, e( B) F& @0 ^) l """Create a vxlan unless it already exists.""") C. X7 c+ j) w" B
interface = self.get_vxlan_device_name(segmentation_id)
, @; U; c' N& i/ S* e if not ip_lib.device_exists(interface):, n$ y; S" A2 d g
LOG.debug("Creating vxlan interface %(interface)s for "+ U6 @/ `6 a$ L/ p# u6 B
"VNI %(segmentation_id)s", G/ u5 |! z% @6 N& O8 S ~
{'interface': interface,
& F8 z, c8 X, b) `0 U 'segmentation_id': segmentation_id})
$ w: T% | c1 j3 U args = {'dev': self.local_int}
/ o9 j; F; h8 b& Z0 q0 m) M if self.vxlan_mode == lconst.VXLAN_MCAST:1 t' f. H4 N1 S8 w4 K. ^; Y
args['group'] = self.get_vxlan_group(segmentation_id)3 E. `6 Y4 J& B. Q3 I( q
if cfg.CONF.VXLAN.ttl:
2 V) m0 u- V- Q+ E) t; f5 ? args['ttl'] = cfg.CONF.VXLAN.ttl& t1 x& H Y: G" r }0 \; C
if cfg.CONF.VXLAN.tos:
4 M$ W' l. M: z+ a* p' b9 ? j args['tos'] = cfg.CONF.VXLAN.tos# g' N0 K# r8 E: d
if cfg.CONF.VXLAN.l2_population:
% x& i2 h1 {3 ?" a; a; w- Z4 N: S) u args['proxy'] = cfg.CONF.VXLAN.arp_responder: I# ^# M7 }6 `- q4 Y8 f8 S
try:
& U" n4 g9 k+ X! E% d, c# ]: V6 m int_vxlan = self.ip.add_vxlan(interface, segmentation_id,4 S$ j2 e4 Y* a$ a; _
**args), n9 y2 r$ x) u/ _6 @
- w# U7 v, E) q4 `6 p# ?% W; Z& Y(8). 将 tap 设备加入到 linux bridge 中! o4 l t- i& F
bridge_lib.BridgeDevice(bridge_name).addif(tap_device_name)% @* b8 y0 q# u8 o
(9). 如果将一个 tap 设备被删除,那么 linux-bridge-agent 会发现:; x- l+ v* r' f5 D5 y$ N
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'])
/ l& Y6 k3 ?& F; o' n& U# K( w2016-10-26 10:29:58.433 30219 INFO neutron.plugins.ml2.drivers.agent._common_agent [req-e3264065-6414-4b5a-8d2b-dfafad6fdde8 - - - - -] Attachment tap60dbdc2f-a0 removed2 y- a6 t& U+ w: L. X0 y0 G
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.
4 U4 r1 e% D$ m, |2 j3. 关于上述工作过程的简单结论. ?* P( K, b/ O# ]( S: q, X
3.1 简单结论3 R' Y0 g& Y3 t; k8 F/ E
1. l3agent 和 dhcpagent 创建 network namespace 时创建 tap 设备,和 network namespace 中的 interface 是一对 veth pair。当手工删除 tap 设备时,相应的 veth endpoint 也会被删除。; e c! Y q: v# g# g* a
2. linuxbridgeagent 不断扫描服务器端和本地的 tap 设备& v5 f2 S+ c8 \ P% K: K
3. linuxbridgeagent 获取需要增加和修改的tap设备列表
* |1 x1 Y( I6 U: m4. 对于需要增加的 tap 设备,获取其详细信息,主要是 network_id,network_type,physical_network,segmentation_id,device_owner 等,然后根据这些信息,创建 linux bridge,并加入所需要的 interface
- V- I, T# }8 m. y5 _5 m; `5. 创建所需要的 linux bridge,并将 physical interface (provider network 的 physical interface 或者 tenant network 的 vxlan interface)加入 bridge,并且将 tap 设备也加入该 bridge2 S' t/ i; n$ z- P! A6 K
6. 如果发现某个 linux bridge 没有创建出来,首先需要查看有没有相应的 tap 设备存在;如果 tap 设备不存在,则查看相应的 qdhcp 或者 qrouter 中时候有interface
2 U F& K. K$ h7 R% O
& s. W9 N9 b7 H) ]具有多个 VLAN 租户网络时候的网络元素示意图:' M* j$ @& x" r. I. g. |
3 y- |# k* E {7 x9 Z4 j: z
. e6 T% k4 A3 g
9 e; P- F/ L+ O( R
4 `+ j7 V8 U2 b# C9 S* c2 `' z) g
3.2 关于 unnumber interface# ]- U8 V( J m
OpenStack 官方的 host networking 配置中,连接外网的 interface 可以是 unnumbered 的,从字面意思理解,就是该 interface 上不需要配置 IP 地址。0 Z, S# k6 [$ p3 C
& j- @7 v3 \# ]5 b1 `8 B2 P
配置的时候,修改 /etc/network/interfaces:. ~- A& ~8 {" p& \; ?% P& U5 ?
# The provider network interface
8 I$ e, _: ^2 u# x# v% A" vauto ens2249 E; b2 C4 Y; M% B3 @
iface ens224 inet manual
1 E/ K0 O6 j z. q hup ip link set dev $IFACE up- w6 I" t9 f0 M5 g
down ip link set dev $IFACE down" u. ~( y0 h6 _- u
配置好以后:" N, a I5 p) R& J
' Y& S+ k% Q- _ j; f: ^
root@controller:/home/sammy# ifconfig ens224
! x3 C$ X$ c' U$ c7 Q/ y# C+ Iens224 Link encap:Ethernet HWaddr 00:50:56:9c:4d:94
4 G9 m) |0 F# K5 m5 k2 h$ A UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
9 L; ?* K$ L$ ^3 l/ X1 a# g RX packets:27300737 errors:0 dropped:0 overruns:0 frame:06 _% e% p# T: v0 N
TX packets:61547 errors:0 dropped:0 overruns:0 carrier:0" I8 g1 G0 N' Z5 Y! ~# y1 }
collisions:0 txqueuelen:1000* |) d! K2 E u# \. x
RX bytes:31951077598 (31.9 GB) TX bytes:5966060 (5.9 MB)# T: b: V$ ^. x4 L1 X) Y
' \* m+ w& W- M3 P! f9 a0 D" z
root@controller:/home/sammy# ifconfig brq96609bfa-0e0 l4 ~ z8 z2 i
brq96609bfa-0e Link encap:Ethernet HWaddr 00:50:56:9c:4d:94
- i) C# Q- r- J6 L9 } UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1/ S% l' L/ ?7 U% k5 i1 }
RX packets:32855 errors:0 dropped:0 overruns:0 frame:0( h' n0 N8 w6 t/ x( u
TX packets:2 errors:0 dropped:0 overruns:0 carrier:06 Z3 t. r, T6 b5 Z3 a. R
collisions:0 txqueuelen:1000% N( W5 r& [8 b4 |8 c8 I
RX bytes:2731030 (2.7 MB) TX bytes:84 (84.0 B)/ d! g+ c* k) w4 k# j$ G
) j3 j. e7 V, F4 o2 }* y0 N( O具体原理不详,但是应该是因为 qrouter 的 qg network interface 和物理网络中的路由器的网卡之间是网络二层,因此中间的设备都是属于二层的,因此不需要处于网络三层的 IP 地址。$ {8 G) ]8 S0 H2 s; R* y9 H, b6 ]
4. 使用 linux bridge 时的拓扑结构5 U8 X& [2 Q0 a1 ^
4.1 网络节点上
; }( |7 H4 F7 j. r. F为了更清楚,我们来对比着看 linux bridge 和 ovs 的两种方案: s/ g$ w* ~- I
linux 方案:" G; P" w% d/ d% |1 [; x. z* l* P
' G& W" g5 }; |5 T
网络服务:
/ B+ b p$ F; U# ?( M, L+ {8 y• Linux bridge agent& Q/ M0 e& `$ _* e3 o' c! a
• L3 agent
2 g/ T4 p3 L3 {3 H* U: A• DHCP agent7 U$ t: o* I F2 E! B
• Metadata agent. g+ s6 b$ K K0 z
Linux bridge agent 会为每个 VLAN 虚拟网络创建一个 VLAN Bridge,它连接多个网元:
2 `4 t: h: [! \2 P• VLAN 子接口,从物理网卡(图中的 interface3)上创建,每个子接口对应一个VLAN ID,其名称格式为 device.sid,其中 device 是物理网卡名字比如 eth0,sid 是 vlan id。
9 K& ] m# N- y, M! c3 U) ]! F' q• 连接虚拟机的 tap 接口+ o! ^- g4 q. [" s9 S6 `" E6 [
• 和 qrouter 连接的 tap 接口
- `/ J7 Z( J, y8 j• 和该网络的 qdhcp 连接的 tap 接口% E) |$ x0 ]' ?, U r9 n! u
如果同时有 VXLAN 虚拟网络的话(linux-bridge 不支持GRE 隧道模式),会为每个 VLAN 虚拟网络创建一个 Tunnel bridge。它连接多个网元:
9 B2 O4 y# b! a% C. T• vxlan interface,这种接口每个虚拟网络一个,名字格式为 vxlan-sid,其中 sid 是分段ID。- p: r. d7 S$ S/ {" |) P
• 连接虚拟机的 tap 接口
( r! K9 Y7 }; z+ ]% D* ^• 和 qrouter 连接的 tap 接口
3 J# }4 f( D3 \1 Q• 和该网络的 qdhcp 连接的 tap 接口9 [" q: h) g* j- T
安全组规则在 tunnel bridge 和 vlan bridge 上。# V9 `/ }3 Q) b9 ~# \
OVS 方案:2 `3 e( V4 S" X) f" y
' P0 p5 V! w% C' l这里面,br-int 会负责加本地 VLAN 标签,br-tun 会负责将 VLAN ID 转换为 VXLAN ID。
3 J7 g+ G: H! e& a& ?! } 9 A/ ~5 P% c* v& k& w B6 {
4.2 计算节点上
0 m5 |& t! E0 p8 x( }) |" Y9 U同样来对比着看。9 t' ~6 n. t o$ i
linux bridge:3 ?5 t* b3 S5 W) R* z. s: m
0 A! P+ {2 Y' A0 _" b0 t网络服务:2 z6 ]' ~7 I+ ~1 J9 f, i* N- _
• Linux bridge agent4 v! b( Q! C+ K" U
和网络节点类似,只不过没有 qrouter 和 qdhcp,不在赘述。, e) ]% S* m8 A# Q) j# u9 [
OVS:
, J, @# |) P( O' U6 H# |! r
9 \- u- m; i0 y( }) Z
; b. Z k2 ?9 k0 v0 @2 {OVS 放在在 br-int 上实现 VLAN 标签,在 br-tun 上实现隧道,在 qbr linux bridge 上实现安全组。
& w: |3 K. {4 O
; B" q( r. ]% n& Y t6 m4.3 网络路径 - 南北向网络流向
- h( P" N7 A' d
5 y6 L- c$ u' e4 E- ]' oVLAN 网络和VXLAN 网络井水不犯河水。这图上的配置中,计算节点和网络节点上的物理网卡都分开了。
0 E2 r8 n% t; p5 w( e6 ~4.4 网络路径 - 东西向(不同网络)" |; m5 E* O0 `' ]& C7 Z' G1 H# w
j7 _% W4 `/ h5 E
4.5 网络路径 - 东西向(同一个网络): ~- Q9 ~- M. g5 v7 G3 F; S" \
/ k- ?2 l# x2 T' M 5 p6 S' S2 `) B8 {1 n9 m y# B) ^5 C
请详细说明和配置,请参阅参考文档。
! J9 Y" v" u& ^9 L; K1 ?5. 一点结论
, y$ {. M. h6 P和基于 OVS 的二层网络相比,
9 ]# p" ^$ t* Z( @) z! l• 功能和架构上:基于 linux bridge 的实现还是有一些短处,比如每个虚拟网络就需要一个网桥,这在大规模环境中会带领资源使用和管理上的问题。其好处是本身架构比较清晰。. U+ V; o, i# Q4 C
• 性能上:基本上差不多,如下图所示,不管是 vxlan 还是 vlan。
8 a. ?" a6 J$ }# }8 D
4 T# b: y' ~# C ]4 g6 }( F4 y( `
|
|