|
|
楼主 |
发表于 2019-10-25 11:23:29
|
显示全部楼层
虽然大部分的OpenStack 部署环境中,都会使用 Open vSwitch 来作为虚拟交换机来实现二层网络功能,但是Neutron 仍然支持使用 Linux bridge 作为虚拟交换机来实现二层网络。本文就此做些分析和说明。 + s8 y3 W# d" d2 F
同时要指出的是,OpenStack 官方已经把 linux bridge 实现标记为 legacy 的了,文档从 2016 年后也没怎么更新了。这是因为,linux bridge 和 OVS 相比,只支持基本的网络功能即二层交换,但不支持VLAN 标签和隧道。因此,linux bridge agent 利用linux 内核功能(VLAN 子接口和 VXLAN 接口)来实现VLAN 标签和隧道。
* Y! J d- u# p4 j
) D* o0 \$ _4 O7 A& k 1. 测试环境
9 [3 m: W$ v& t以下面的环境为例(网络节点上):) J0 |3 R% }' x: G+ B8 `+ n# v
(1)linux bridge
/ Y+ v7 A: ^! K$ m" R7 y * `6 G" Z1 Q2 Z! O' Q: l
root@controller:/home/sammy# brctl show' L5 a. u: i: e- E( a b; r
bridge name bridge id STP enabled interfaces
9 K; a! J7 [, H; c7 e* nbrq85925305-b4 8000.563534c8d02d no tap0bb8efeb-105 e" K5 |- \: |6 |" A' V
tap798c87d1-a2
( L) _5 k5 U* }) j vxlan-252 t+ }0 D* ` e( b4 J* N
brq96609bfa-0e 8000.0050569c4d94 no ens224 N: P( h# ?/ o+ j
tap60dbdc2f-a0
$ m% |, o6 i( x3 Gbrq971ffda2-e5 8000.a6acb08e4fd6 no tapb1eaae00-e5
9 x9 B6 o/ c# @) N* G tapf70543dd-0f- c5 s1 Y6 r4 ]) L2 p: w5 \
vxlan-10+ I1 }. k: I* M8 `1 M/ J; d) B
: b8 f) A2 w# L
(2)OpenStack 网络和 network namespace:
& ]: i D, b9 l9 h6 U$ J- A) v % a* J( Q+ K; l0 v! W0 ^
root@controller:/home/sammy# neutron net-list7 A6 w- h" W8 [% j
+--------------------------------------+---------+-----------------------------------------------------+% t9 z0 y# F9 J: k$ H- m% j
| id | name | subnets |
) A9 z' v" H- ?! t; a+--------------------------------------+---------+-----------------------------------------------------+
$ U: y3 E) v$ D| 96609bfa-0e22-4bb7-8dba-6ef532ea6076 | extnet | afa7d205-3026-439f-aca7-295a9f9b2a71 10.62.227.0/24 | Z8 n' x" a1 Z( t W& {0 D5 a2 N0 p& Y
| 971ffda2-e567-40a0-a2c8-b31a577fd4d3 | appnet | 4c68eacb-bf3e-408a-a941-94e93eddb22b 11.0.0.0/24 |, n( P* M' n8 C; Q. C
| | | 3d596991-de8f-4ae4-8913-89426a8abbd7 10.0.0.0/24 |, l* \7 i/ I( L1 P. e
| 85925305-b477-4cc6-9654-67d9bf1e7cd8 | appnet2 | 4575c7f1-7f08-4917-9904-ec65af38619b 20.0.0.0/24 |+ E+ G* H& R; ]4 T0 e7 N
+--------------------------------------+---------+-----------------------------------------------------+
. v' ~$ T4 ]( @4 m( ~) xroot@controller:/home/sammy# ip netns( Q) V, z: ?" A/ G: i
qdhcp-85925305-b477-4cc6-9654-67d9bf1e7cd8 (id: 2)
+ K7 ^4 E/ Z; n- A8 ^qdhcp-971ffda2-e567-40a0-a2c8-b31a577fd4d3 (id: 1)
; q( ]% j# L7 S; G& p( F( v; J- ~qrouter-39a77439-8a28-49c1-bf97-ac931510631b (id: 0)
* x1 K" Z7 n$ N+ f; H4 t ; j, m: u3 ^$ @/ L
(3)示意图:4 |* b# R" @; m8 w# ~) y- ]1 I
+ E+ d7 C( B2 }(4)说明:* f! B9 {0 V3 e% ?; H0 s# r& k( ?
• qdhcp 和 qrouter 都是 linux network namespace 实例
0 x/ o8 L/ M0 B• qdhcp network namespace 的数量等于启用了 DHCP 的 Neutron network 的数量。7 _1 r$ |( Y! q: [- f. ]% n. v4 C% D2 z
o 当一个 network 中存在至少一个 subnet 启用了 DHCP 之后,会有一个 qdhcp network namespace 被创建出来;, {# e- s" {& R
o 当一个 network 中多个 subnet 启用了 DHCP 时,它们共用一个 qdhcp,以及 dnsmasq。" x4 o! d3 l8 t. g: `- g/ d6 p
o 其 name 使用 network id,比如 qdhcp-85925305-b477-4cc6-9654-67d9bf1e7cd8
0 s0 l M2 F' l" @. D/ T# T• qrouter network namespace 的数目等于 router 的数目,也就是说,系统中一共有几个 router,那么就存在几个 qrouter network namespace; v- z. K% q% k1 S S8 Z6 \9 K4 \
• brq linux bridge 的数目等于 neutron network 的数目,其 name 是 network id 的前几位,比如 brq96609bfa-0e
' N8 _( I1 \6 q8 t• 一个 network 的 qdhcp network namespace 和其 brq linux bridge 一定有连接3 T6 }5 z+ J0 \ q7 t
• qrouter 之内的 network interface 分两种,一种是 qr 开头的,每个连接到 router 之上的 subnet 都有一个;还有一个是 qg,每个连接到 router 的 external subnetwork 有一个6 p _4 |) v4 l1 u' v
• qrouter 的每个 network interface 都通过 veth 连接到所在网络的 qbr linux bridge 上+ g' A$ N: i1 A
• qbr linux bridge 连连接两种物理设备,一种是 vxlan interface,每个 tenant network 有一个,另一种是在 physical network 对应的物理网卡上创建的子接口(sub-interface)+ y" a; b9 Q0 w. s9 _
• 对于 physical network 的 qbr 来说,用户可以指定它,并且在linuxbridge_agent.ini 中通过 bridge_mappings = List of <physical_network>:<physical_bridge> 进行配置;也可以不指定,此时 agent 会创建它。当同时配置了 physical bridge 和 physical interface 时,前者优先。2 d# L: d0 r0 u# W
如果 external network 中有多个 subnet 的话:
0 P7 G- u: b, h+ J3 K u) ]2 ?(1)每个 qrouter 只允许有一个 External Gateway,也就是说它只有一个 qg network interface。当 external network 添加多个 subnet 之后,只有第一个被当作 external subnet,其余的都会被当作 internal subnet。! x: l: M; E" g" ]
(2)在 qrouter 的路由表之中,
9 K3 q: a2 q0 G7 }- ?+ m& s
5 q) L* k" R! f) i% @. ~" G3 Uroot@controller:/home/sammy# ip netns exec qrouter-39a77439-8a28-49c1-bf97-ac931510631b route
+ e5 z, Z! p* w2 oKernel IP routing table5 X; [6 z% a6 }0 v0 ^
Destination Gateway Genmask Flags Metric Ref Use Iface& a) Z: H4 Z4 e3 G$ d" @4 E" B( P
default 10.62.227.1 0.0.0.0 UG 0 0 0 qg-e09fce07-cd9 W" a9 e% w) F3 l' d3 v N; Q4 e$ e
10.0.0.0 * 255.255.255.0 U 0 0 0 qr-b1eaae00-e5
: V) A4 |% b0 T. m10.62.227.0 * 255.255.255.0 U 0 0 0 qg-e09fce07-cd
! W6 F# }, ?$ V( P p! b0 O10.62.228.0 * 255.255.255.0 U 0 0 0 qg-e09fce07-cd
5 D- P" K1 q6 Q1 O1 n1 q10.62.228.0 * 255.255.255.0 U 0 0 0 qr-124ff148-b7
+ |, g5 {$ j' Y, y7 y! u( S. U11.0.0.0 * 255.255.255.0 U 0 0 0 qr-16d9b0cc-38; s/ E @& {& p
20.0.0.0 * 255.255.255.0 U 0 0 0 qr-0bb8efeb-10
! J5 w4 q2 ]0 x. ~! J : R5 ]0 b% a7 K* n) u0 V
( O, ]$ B; ^- @% W9 t' G2. linux-bridge-agent 工作过程分析
2 u5 s2 o; {, U! k5 Y# _3 m(1)linuxbridge-agent 会启动一个循环,不断扫描上面红框中的 tap 设备+ k3 o, B {! H9 S% y9 Z
3 |/ \# f- j d4 u7 c def daemon_loop(self):* L( n! y% {9 u+ P, a
...
: J }2 ]# k3 A2 X while True:
# x, D7 L/ \6 y4 G W' o1 Y# k* v( i start = time.time()! \$ a! t }) P$ g. y# _, T
. ..
3 ^. ]8 {: F$ Q5 J
* Z1 V+ @: h' S/ V+ f" F device_info = self.scan_devices(previous=device_info, sync=sync)
, N- S: y0 O, J sync = False
' K0 H& M! u: Y; B2 ?
' b1 `" D: f8 U# J7 ~ if (self._device_info_has_changes(device_info)" m, z. [3 N8 ~6 F( m! f f
or self.sg_agent.firewall_refresh_needed()):# W) Q) W \% c0 p8 W9 t7 `5 F
LOG.debug("Agent loop found changes! %s", device_info)/ w' D. E1 P9 |( v$ F
try:
: z2 n0 Z" |8 `) J5 L% d# q- u* e sync = self.process_network_devices(device_info)
1 f7 M5 g" Y1 w9 B# z except Exception:# _! `, L1 ?* b
LOG.exception(_LE("Error in agent loop. Devices info: %s"),
4 l) p# c: ~7 Q9 @3 { device_info)
; J! T( X- z; `! L4 D sync = True
' I$ n( W0 u7 O, F 9 `* ~7 [7 T7 r3 \% I* F" E4 U
这是它首先找到的 devices:
3 F5 Y4 ~- u% p& ^8 M. F/ f) \0 v |(Pdb) p bridge_lib.get_bridge_names()) |3 m4 h' M0 F
['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']
: E1 _* U$ ^3 Q0 S7 E' p然后过滤出 tap 设备:
# J/ @1 ~) m; c$ p5 Xget_all_devices()->set(['tap0bb8efeb-10', 'tap60dbdc2f-a0', 'tap795e6e86-94', 'tap798c87d1-a2', 'tapb1eaae00-e5', 'tapf70543dd-0f'])
6 m6 V; Q" X2 N/ \8 U. l; j! Y* A4 i(2)根据 previous 中保存的历史数据,再接合服务器端和本地更新时间,计算出需要更新的tap设备列表:. ] ]3 ?, @8 [; N+ m
{'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([])}! |0 {' Y3 n( @0 m, w2 m$ F3 `5 _
(3) 通过 RPC 获取 tap 设备的详细信息
* V8 N9 Y* w; |3 U9 B; B . g# }" X( J$ F2 t% w' a5 z
(Pdb) p devices2 a. A2 T. N2 b
set(['tapf70543dd-0f', 'tap60dbdc2f-a0', 'tapb1eaae00-e5', 'tap795e6e86-94', 'tap798c87d1-a2', 'tap0bb8efeb-10'])
2 B+ ?) `' I. j5 b* N/ J* |
3 }. p& H' Y" _
+ u+ D) g9 F3 |6 l" k2 {devices_details_list = self.plugin_rpc.get_devices_details_list Y1 i5 |: h, l& `" P! c
# a2 u; M# ^- w& G' X( X& q. V
(Pdb) p devices_details_list
, `3 U4 y- W7 d; ][{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': []}]. Q9 h: p' p8 J8 B+ `3 a
0 N; ~5 E! v0 r
(4) 对需要处理的设备,调用 self.process_network_devices(device_info) 函数进行处理
! e) f6 ]. t9 r. E. k(5). 调用 plug_interface
* Y \+ F6 Z% y. R- @5 P! J) \interface_plugged = self.mgr.plug_interface(network_id, segment,device, device_details['device_owner'])- P( h: V2 {3 s' t8 g2 ]; t
(6). 需要的话,使用已经配置的或者新建 linux brige,并将 physical interface 设备加入其中) H/ l7 K, L6 l3 o% K! c
bridge_name = self.get_existing_bridge_name(physical_network) #获取为 physical network 配置的 linux bridge
* s r: S" n# k& K3 Nbridge_name = self.get_bridge_name(network_id) #或者根据 network id 生成 bridge name
' Z1 K! f( a* F0 n2 ^(7).根据不同的网络类型,分别处理 vxlan bridge,flat bridge 和 vlan bridge" G/ B2 M$ l' R9 ~0 T' h
' A+ X+ _& I- \6 b ?! u2 M5 @
def ensure_physical_in_bridge(self, network_id,& j. ]. q; I7 ~" o6 x! i5 C
network_type,
* S5 B# L8 T$ _ physical_network,
, Q' |0 e0 ^0 C1 j* C( W- H6 t segmentation_id):
% u0 S4 U, Q D! r5 n2 C1 k+ [. g if network_type == p_const.TYPE_VXLAN:3 ~ }# q1 c9 K) b& T0 U/ q5 T1 Q
if self.vxlan_mode == lconst.VXLAN_NONE:
( s3 L8 L+ g L% F' S* x' b/ h& D LOG.error(_LE("Unable to add vxlan interface for network %s"),' n! e" x+ I) x) ^' k, } Z; [ S
network_id)9 z& N$ C* R" a
return6 Q0 q' W7 S, k' r
return self.ensure_vxlan_bridge(network_id, segmentation_id)
; [) Z0 b- ~# i/ S/ ^" Q% I" p H( r* T! J) L$ ?
# NOTE(nick-ma-z): Obtain mappings of physical bridge and interfaces: M7 }8 ?- C$ |6 P+ o# p; P
physical_bridge = self.get_existing_bridge_name(physical_network)- y x' a/ v9 F3 G
physical_interface = self.interface_mappings.get(physical_network)" f3 m; D, ?' s2 ~; ?+ @
if not physical_bridge and not physical_interface:
7 v* b+ V0 Y$ \/ i2 _3 ? LOG.error(_LE("No bridge or interface mappings"0 A& w9 w5 d+ u, F9 N2 L
" for physical network %s"),
5 o" k! y' T5 x2 L+ Z( V9 f physical_network)
5 [$ u: A+ }& @5 q! o3 Y/ H7 ~ return
- V3 Q' H7 d3 v8 {3 [8 A if network_type == p_const.TYPE_FLAT:
# t: k: F7 |/ [ return self.ensure_flat_bridge(network_id, physical_bridge, X5 E- v* D* ]6 U
physical_interface): o- P9 D, k1 @- J
elif network_type == p_const.TYPE_VLAN:( z. `7 f* Y& O" f) A5 g6 C+ p
return self.ensure_vlan_bridge(network_id, physical_bridge,& s9 f0 W \6 o- `! w
physical_interface,2 R3 j6 P; j% L8 |9 k' X
segmentation_id)
" E3 f5 Q3 o y+ C: W6 z, j , `; ^* C8 L5 D$ B( V
对于 flat 类型的网络,调用 ensure_physical_in_bridge
! h% K3 o9 K# E7 ^7 Bdef ensure_physical_in_bridge(self, network_id,network_type,physical_network,segmentation_id)
+ i. N k0 A& {* ? if network_type == p_const.TYPE_FLAT:6 ]2 M, f* ^ o# i
return self.ensure_flat_bridge(network_id, physical_bridge,physical_interface)
$ `" Y7 G8 h# o4 P+ W) @ k如果有配置 physical bridge 的话,使用它;否则创建 bridge,并将物理网卡配置的 ip 地址和 gateway 从网卡挪到 linux bridge
0 T0 n) r* B/ e! ]% q7 Q9 v9 _* `
" K0 R3 ]# i0 C0 Z* ~def ensure_flat_bridge(self, network_id, phy_bridge_name,physical_interface):, D1 q( F2 V# {- j! t4 B7 H0 P
"""Create a non-vlan bridge unless it already exists."""8 g5 f6 b. A/ v6 L, O5 f
if phy_bridge_name: _# w- c. }8 o5 [. L O% s& H
return self.ensure_bridge(phy_bridge_name) #获取预先配置好的 linux bridge1 a! }' h2 n3 e. ]3 `$ I; {. _
else:: b, l0 |0 H( q# S
bridge_name = self.get_bridge_name(network_id)$ K. T5 [: j6 T# Z
ips, gateway = self.get_interface_details(physical_interface)
' g& A8 V8 ^2 ~3 z if self.ensure_bridge(bridge_name, physical_interface, ips,gateway): #创建 bridge
% H! r7 ?, G4 q0 w+ [" p return physical_interface! `; `; Q6 T2 O% D# s8 r
) E4 h+ q k# u对于 vxlan 类型的 network,需要创建 vxlan interface
5 G& y# I+ y" J4 B6 N( r2 t9 ]
) R4 z q( i7 q5 d' c2 z9 a7 w* e def ensure_vxlan_bridge(self, network_id, segmentation_id):
0 |2 _5 o9 T! y """Create a vxlan and bridge unless they already exist."""5 i( a8 W+ x) a/ P6 Q S
interface = self.ensure_vxlan(segmentation_id): e6 Z8 { F. v* k4 F
if not interface:5 i+ Y- K/ n! [% b
LOG.error(_LE("Failed creating vxlan interface for "
/ ~. L$ g3 K! t1 J+ L+ x+ Y "%(segmentation_id)s"),4 u* U& Y8 u) l F* r
{segmentation_id: segmentation_id}), I: g6 x' [0 Z( }8 V
return$ G8 N) _; Q1 n0 G
bridge_name = self.get_bridge_name(network_id)
% A- F- h2 ~+ b, k! Q( X" `; i$ q self.ensure_bridge(bridge_name, interface)/ D; `9 \5 x6 w8 _4 R
return interface) n# k( q6 X* F6 M+ Z! s
( ~( ^+ l0 [- K' Q
创建 vxlan interface:
8 X0 f* |* G# \ O2 B
* i- x' I6 j8 p/ {* W def ensure_vxlan(self, segmentation_id): \7 ~; E& D. f- N+ k9 C" I
"""Create a vxlan unless it already exists."""$ Q' Z/ H! b4 c3 U
interface = self.get_vxlan_device_name(segmentation_id)% `9 U) }/ [4 R0 r9 t3 `
if not ip_lib.device_exists(interface):
4 j) `* e+ I* ?/ \; A/ A; V% ~, q LOG.debug("Creating vxlan interface %(interface)s for "
; P* C8 [. g0 p4 ]9 K "VNI %(segmentation_id)s",* k+ W$ H6 B% V8 [4 i/ {/ y: _) h
{'interface': interface,
- _2 N6 k+ |2 A/ k/ P& } 'segmentation_id': segmentation_id})# Z2 ~1 b4 F, c- R' R, J3 }
args = {'dev': self.local_int}. D2 j: e0 m* J: C3 z7 i
if self.vxlan_mode == lconst.VXLAN_MCAST:
2 P1 x; h1 x8 x1 W args['group'] = self.get_vxlan_group(segmentation_id). x/ x# p" [- h8 B: [( ^" I% U' F- Q- F2 X
if cfg.CONF.VXLAN.ttl:* ~* r; F& W v* d, q% T- g. a" }
args['ttl'] = cfg.CONF.VXLAN.ttl
8 k6 j2 D; X* k$ c! V2 o, j: ] if cfg.CONF.VXLAN.tos:& w) A, r) ]/ ]3 j- s3 x$ f# s
args['tos'] = cfg.CONF.VXLAN.tos
4 j* v" J6 ]) I* N9 M; Z if cfg.CONF.VXLAN.l2_population:
8 ?/ w! H0 y' `+ p$ F2 [0 q args['proxy'] = cfg.CONF.VXLAN.arp_responder
. V6 _ [+ \2 f try:7 `! B Y! N# r, F" z; h
int_vxlan = self.ip.add_vxlan(interface, segmentation_id,
* R8 ?% K/ F" I2 x; u0 u **args)
' E) t, [, T- r" q ) j& m3 J3 Q" G1 _
(8). 将 tap 设备加入到 linux bridge 中' a1 h' r" _' h" K1 N
bridge_lib.BridgeDevice(bridge_name).addif(tap_device_name)
- }+ w( {& m5 k8 p" p2 a+ ]7 }(9). 如果将一个 tap 设备被删除,那么 linux-bridge-agent 会发现:
- S/ H# p8 R2 l6 ^4 w2016-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'])
, f: d& ?) r+ |) B2016-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: i8 g8 y+ Q8 j8 Q
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.
n7 ~3 j8 g6 w# [. p- P3. 关于上述工作过程的简单结论
4 {) M( m3 B2 |3.1 简单结论. n y t4 f) G) }% s2 C- o/ s* Z
1. l3agent 和 dhcpagent 创建 network namespace 时创建 tap 设备,和 network namespace 中的 interface 是一对 veth pair。当手工删除 tap 设备时,相应的 veth endpoint 也会被删除。
; b& r" o- A( Y9 i2. linuxbridgeagent 不断扫描服务器端和本地的 tap 设备
5 t. n0 H3 O7 e* `* b, y6 d3. linuxbridgeagent 获取需要增加和修改的tap设备列表
& G; Z8 m5 n- v) N! z# T4. 对于需要增加的 tap 设备,获取其详细信息,主要是 network_id,network_type,physical_network,segmentation_id,device_owner 等,然后根据这些信息,创建 linux bridge,并加入所需要的 interface
3 f5 t- e- S+ W2 T8 }5. 创建所需要的 linux bridge,并将 physical interface (provider network 的 physical interface 或者 tenant network 的 vxlan interface)加入 bridge,并且将 tap 设备也加入该 bridge
- w2 f6 j! t F. ]. d8 F6. 如果发现某个 linux bridge 没有创建出来,首先需要查看有没有相应的 tap 设备存在;如果 tap 设备不存在,则查看相应的 qdhcp 或者 qrouter 中时候有interface
, ~6 E3 d: p& A! |7 N$ l ) @7 ?, `$ O2 D$ ]7 O! S& t
具有多个 VLAN 租户网络时候的网络元素示意图:# [$ r! P6 W) y; { G+ v
- @0 n/ ~! S- W: {3 B: k
* @7 ?7 S( _' a& T2 V
* C1 f& x! K( l1 o
, w0 V" |6 K/ P7 q6 @" t( c2 l 3.2 关于 unnumber interface8 d- O* r1 N/ A1 R8 i; r# o
OpenStack 官方的 host networking 配置中,连接外网的 interface 可以是 unnumbered 的,从字面意思理解,就是该 interface 上不需要配置 IP 地址。
) i5 ^5 J% f1 ]2 F # M% }& q2 v+ |' r8 ^. a. X! y
配置的时候,修改 /etc/network/interfaces:3 V; H8 }8 } C( ]
# The provider network interface7 G3 q( C. o; o: x6 X
auto ens224) S% ^, u3 X+ n7 B
iface ens224 inet manual& r O K m; O% j3 Y
up ip link set dev $IFACE up
& c$ l9 v7 U- P1 U0 E$ k* Xdown ip link set dev $IFACE down% F8 T4 S$ @$ G0 q" z; {* ?
配置好以后:
8 w; C3 }0 {" m ' x) |8 q! z. d$ p8 I
root@controller:/home/sammy# ifconfig ens224
3 J) }- e: L9 c3 q' P: A- mens224 Link encap:Ethernet HWaddr 00:50:56:9c:4d:945 c; U! E0 e& r9 Q4 i$ z
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
3 R4 p' H6 O+ y* q, P RX packets:27300737 errors:0 dropped:0 overruns:0 frame:0
* n) B& b1 t; x$ w8 m TX packets:61547 errors:0 dropped:0 overruns:0 carrier:0- H. [ A2 R1 f7 O
collisions:0 txqueuelen:1000
. T, ]+ M+ M0 J3 \; B) s) ` RX bytes:31951077598 (31.9 GB) TX bytes:5966060 (5.9 MB)
1 ]2 Y h5 q2 _7 H" m1 K- H" i1 ?4 }1 m
root@controller:/home/sammy# ifconfig brq96609bfa-0e
3 s) t' N$ S6 l7 Xbrq96609bfa-0e Link encap:Ethernet HWaddr 00:50:56:9c:4d:949 d+ w' u5 H6 g3 s4 j
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1) b" L C1 M0 W
RX packets:32855 errors:0 dropped:0 overruns:0 frame:0( k4 u, C* h! g# }& w
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
' r) o2 [( q5 n. S1 a; q; N collisions:0 txqueuelen:1000
. L8 X% o( F7 }5 z( j RX bytes:2731030 (2.7 MB) TX bytes:84 (84.0 B)& x: B4 _% w3 G8 B6 `
3 }& t: Z3 Y3 R+ X/ o9 ?* I" h具体原理不详,但是应该是因为 qrouter 的 qg network interface 和物理网络中的路由器的网卡之间是网络二层,因此中间的设备都是属于二层的,因此不需要处于网络三层的 IP 地址。
9 b: j) t, k' B+ G8 {4. 使用 linux bridge 时的拓扑结构
& b. H7 K& R( I- y4.1 网络节点上$ G# _- [3 t( C# z5 @6 i
为了更清楚,我们来对比着看 linux bridge 和 ovs 的两种方案:
% r5 z( }9 r* ?* \8 Slinux 方案:
7 S8 |, I- M: E9 w3 y5 z% U 5 E8 |! ^, B8 _0 J* t* ?
网络服务:
; y2 q K. C: Y, W• Linux bridge agent
u% s/ W5 f, ~4 Y. }5 z• L3 agent
# k3 R8 E# B) X0 H7 w• DHCP agent
& ?, t! h2 S/ ]$ G• Metadata agent
( |9 Q/ x1 r2 a/ vLinux bridge agent 会为每个 VLAN 虚拟网络创建一个 VLAN Bridge,它连接多个网元:4 ~, N' E! Z6 T, Y* `8 I
• VLAN 子接口,从物理网卡(图中的 interface3)上创建,每个子接口对应一个VLAN ID,其名称格式为 device.sid,其中 device 是物理网卡名字比如 eth0,sid 是 vlan id。
0 f3 J- ~- J! n n5 E& Q1 @; c• 连接虚拟机的 tap 接口
) ~0 M h" S4 g• 和 qrouter 连接的 tap 接口
, }! P9 H* }9 \' c$ ?• 和该网络的 qdhcp 连接的 tap 接口5 H& n. g. V8 o# c. E0 ~. Q
如果同时有 VXLAN 虚拟网络的话(linux-bridge 不支持GRE 隧道模式),会为每个 VLAN 虚拟网络创建一个 Tunnel bridge。它连接多个网元:, f7 J" \' z& ^- m4 i
• vxlan interface,这种接口每个虚拟网络一个,名字格式为 vxlan-sid,其中 sid 是分段ID。
3 r$ j0 M7 b5 z N• 连接虚拟机的 tap 接口
v+ K6 p2 O8 h* u9 B• 和 qrouter 连接的 tap 接口
, g; |: [* T) \, X) y• 和该网络的 qdhcp 连接的 tap 接口7 r& g) ]/ J! i8 a u- Q
安全组规则在 tunnel bridge 和 vlan bridge 上。
2 w6 L' w1 f& ?; Y+ c) r1 COVS 方案:
: m0 \' A! A! o5 G# j6 G# G2 h! a 9 C" U! i3 y) a* [- h' R
这里面,br-int 会负责加本地 VLAN 标签,br-tun 会负责将 VLAN ID 转换为 VXLAN ID。
1 [6 t# w) ~3 \+ P " P2 m' ~" U7 h8 [. ?
4.2 计算节点上/ j& r0 h9 D4 C9 G; w1 O9 g7 b! O
同样来对比着看。- Y- T$ e- M) `( K, ~3 l
linux bridge:% q8 J% h0 F6 w( b1 }/ ]: D
" T' ~3 \3 E$ ~( n; W3 ?4 S网络服务:
7 v2 |. g! o( u, k( M2 l• Linux bridge agent
" O( c1 q, L# l" I' \和网络节点类似,只不过没有 qrouter 和 qdhcp,不在赘述。
4 i, ]: k/ H' U6 Y# M, `& W. ^1 {6 ?OVS: S" i: Q' c, w! A0 F
5 \$ V7 g$ \2 Y1 {4 o7 p
' n" b4 b# s4 V) ?! w- M3 J1 A
OVS 放在在 br-int 上实现 VLAN 标签,在 br-tun 上实现隧道,在 qbr linux bridge 上实现安全组。
! S% ^' Z+ l) P 3 _0 _3 E) H3 h3 J) M
4.3 网络路径 - 南北向网络流向
" Q3 e7 |0 u- A
/ b- y( T' f7 O% Y7 wVLAN 网络和VXLAN 网络井水不犯河水。这图上的配置中,计算节点和网络节点上的物理网卡都分开了。) v: p7 \* l. c* g9 F
4.4 网络路径 - 东西向(不同网络)
1 v6 j' w9 z. K A# v) R) h5 q% g
* A1 J+ k- i2 }' X9 k& b1 L: e3 H4 e0 c4.5 网络路径 - 东西向(同一个网络)% Z7 k! p, P3 e5 d4 [/ \( t2 G) G
5 _8 V$ m' {" P; B# R. A
1 G9 @1 ^: Y$ B/ z1 b请详细说明和配置,请参阅参考文档。
4 a( z$ D3 y% F, S# }: {5. 一点结论& @! |" a9 E+ c/ W5 A" k
和基于 OVS 的二层网络相比,
" F3 N* s8 y; \) w! }+ n8 z5 p. {• 功能和架构上:基于 linux bridge 的实现还是有一些短处,比如每个虚拟网络就需要一个网桥,这在大规模环境中会带领资源使用和管理上的问题。其好处是本身架构比较清晰。& i& v; o# o$ v( c* U
• 性能上:基本上差不多,如下图所示,不管是 vxlan 还是 vlan。
) [8 \& d- s' O0 Z
; S/ K u* {5 T# o* N6 l! W1 A6 r; v9 Y [
|
|