|
|
楼主 |
发表于 2019-10-25 11:23:29
|
显示全部楼层
虽然大部分的OpenStack 部署环境中,都会使用 Open vSwitch 来作为虚拟交换机来实现二层网络功能,但是Neutron 仍然支持使用 Linux bridge 作为虚拟交换机来实现二层网络。本文就此做些分析和说明。
7 c: M" P- ` \1 `3 v1 |$ V同时要指出的是,OpenStack 官方已经把 linux bridge 实现标记为 legacy 的了,文档从 2016 年后也没怎么更新了。这是因为,linux bridge 和 OVS 相比,只支持基本的网络功能即二层交换,但不支持VLAN 标签和隧道。因此,linux bridge agent 利用linux 内核功能(VLAN 子接口和 VXLAN 接口)来实现VLAN 标签和隧道。
, g4 @/ Y3 M7 ^ `$ R. q
) F4 U( z& J3 H 1. 测试环境1 [3 Y( F1 o3 H7 S. H" c
以下面的环境为例(网络节点上):8 z: m6 z' Z! N
(1)linux bridge1 V' d+ j+ E. @% {5 T
- v1 i! u6 F* v$ {( N% d+ z/ _2 qroot@controller:/home/sammy# brctl show
6 m9 n. M2 C# x5 R/ f+ Y) Xbridge name bridge id STP enabled interfaces
7 @0 s" ` m0 n; I' b1 I7 K1 Nbrq85925305-b4 8000.563534c8d02d no tap0bb8efeb-10
: j4 i8 y& U; k& G tap798c87d1-a21 H4 A4 L: q4 R
vxlan-250 R' l U2 X$ z2 p
brq96609bfa-0e 8000.0050569c4d94 no ens224
: u2 H! k6 }- B/ n tap60dbdc2f-a0$ t8 L0 W6 H. R) K3 L: a( [
brq971ffda2-e5 8000.a6acb08e4fd6 no tapb1eaae00-e5& ^3 l# B+ I# c7 ]* M, F8 r
tapf70543dd-0f
; w/ a6 i3 }0 ^3 R! D) Q vxlan-10
7 A& V) {( ^+ i0 ]2 R9 S y- v2 s/ X, T8 N
(2)OpenStack 网络和 network namespace:% _# U8 @! U0 `$ Q; A5 K
0 u! ?7 ?1 F+ b0 K7 ^& @
root@controller:/home/sammy# neutron net-list6 M& Y2 W# M' T r7 D' t6 m) l
+--------------------------------------+---------+-----------------------------------------------------+
. q1 f3 i% X" {7 m* n| id | name | subnets |
; t" ]" l: L' ]: o+ i+--------------------------------------+---------+-----------------------------------------------------+
% A0 F) F" l# D6 S- N& J: p* P5 D| 96609bfa-0e22-4bb7-8dba-6ef532ea6076 | extnet | afa7d205-3026-439f-aca7-295a9f9b2a71 10.62.227.0/24 |
$ N& f* J% D& P. O( z+ o" m: || 971ffda2-e567-40a0-a2c8-b31a577fd4d3 | appnet | 4c68eacb-bf3e-408a-a941-94e93eddb22b 11.0.0.0/24 |4 ?9 T- g1 O7 I- ?3 K: T
| | | 3d596991-de8f-4ae4-8913-89426a8abbd7 10.0.0.0/24 |0 A$ P! x8 D7 d, j: T# G% e
| 85925305-b477-4cc6-9654-67d9bf1e7cd8 | appnet2 | 4575c7f1-7f08-4917-9904-ec65af38619b 20.0.0.0/24 |
, e3 g2 G2 E) G$ C, E+--------------------------------------+---------+-----------------------------------------------------+
r7 s% ]2 `% m5 ^* M7 p3 croot@controller:/home/sammy# ip netns+ K( R3 k7 y5 u
qdhcp-85925305-b477-4cc6-9654-67d9bf1e7cd8 (id: 2)9 S+ N* r) u9 p/ p
qdhcp-971ffda2-e567-40a0-a2c8-b31a577fd4d3 (id: 1)' U, B( R# O! k+ J, C
qrouter-39a77439-8a28-49c1-bf97-ac931510631b (id: 0), d2 u) R5 t( v
0 S2 v1 U; Z( }7 q" f" J2 ^5 C+ f& }4 r
(3)示意图:' l: B6 F; c3 J" s/ y% l6 q% {, S9 i
9 ^6 h9 }% K8 u5 i# Y(4)说明:# j4 k# ^$ T( N. M8 n* h2 c
• qdhcp 和 qrouter 都是 linux network namespace 实例
/ e, u, z- R k# R1 d9 f• qdhcp network namespace 的数量等于启用了 DHCP 的 Neutron network 的数量。; A' d& z* B3 l8 y6 u
o 当一个 network 中存在至少一个 subnet 启用了 DHCP 之后,会有一个 qdhcp network namespace 被创建出来;
5 a+ w; L& ^/ h4 j/ X& j5 Vo 当一个 network 中多个 subnet 启用了 DHCP 时,它们共用一个 qdhcp,以及 dnsmasq。: B1 U$ `# E, T5 V ]- ?) g
o 其 name 使用 network id,比如 qdhcp-85925305-b477-4cc6-9654-67d9bf1e7cd8( n9 J1 R6 c/ n5 g8 T7 o( P2 Y
• qrouter network namespace 的数目等于 router 的数目,也就是说,系统中一共有几个 router,那么就存在几个 qrouter network namespace
# r7 |0 a. O; n• brq linux bridge 的数目等于 neutron network 的数目,其 name 是 network id 的前几位,比如 brq96609bfa-0e) s2 F4 d+ |2 M; q! m* H0 z- u
• 一个 network 的 qdhcp network namespace 和其 brq linux bridge 一定有连接7 }0 ^5 c% o1 E
• qrouter 之内的 network interface 分两种,一种是 qr 开头的,每个连接到 router 之上的 subnet 都有一个;还有一个是 qg,每个连接到 router 的 external subnetwork 有一个7 }9 h% Z3 ^' `" q2 n
• qrouter 的每个 network interface 都通过 veth 连接到所在网络的 qbr linux bridge 上
# p5 q% W+ @* a% \! p. P. ^• qbr linux bridge 连连接两种物理设备,一种是 vxlan interface,每个 tenant network 有一个,另一种是在 physical network 对应的物理网卡上创建的子接口(sub-interface)/ o7 ]$ u8 a: q% T
• 对于 physical network 的 qbr 来说,用户可以指定它,并且在linuxbridge_agent.ini 中通过 bridge_mappings = List of <physical_network>:<physical_bridge> 进行配置;也可以不指定,此时 agent 会创建它。当同时配置了 physical bridge 和 physical interface 时,前者优先。
& O% a1 m( W$ T r( u7 D- ~如果 external network 中有多个 subnet 的话:
, D: k6 {5 K& X2 K: `. @+ A(1)每个 qrouter 只允许有一个 External Gateway,也就是说它只有一个 qg network interface。当 external network 添加多个 subnet 之后,只有第一个被当作 external subnet,其余的都会被当作 internal subnet。
8 x+ ^( m% q6 D5 c y(2)在 qrouter 的路由表之中,, u/ U5 S3 G9 q6 }' G3 D$ q
+ s1 v+ n) u6 I/ q) k6 P. {) R, Kroot@controller:/home/sammy# ip netns exec qrouter-39a77439-8a28-49c1-bf97-ac931510631b route
, q# F( ~) W" }4 B+ h# K5 w' n0 IKernel IP routing table0 `' S0 d: s1 Z* A& k
Destination Gateway Genmask Flags Metric Ref Use Iface
' @2 i, F: v" o* z. q5 edefault 10.62.227.1 0.0.0.0 UG 0 0 0 qg-e09fce07-cd
. z& p% z& f$ [7 J. J6 J10.0.0.0 * 255.255.255.0 U 0 0 0 qr-b1eaae00-e5
" I' j9 ^) C. b- S F10.62.227.0 * 255.255.255.0 U 0 0 0 qg-e09fce07-cd0 q6 p- Q2 x+ G- ^! S7 _
10.62.228.0 * 255.255.255.0 U 0 0 0 qg-e09fce07-cd
6 f+ L7 Z, G8 H% r0 X" d( S1 _10.62.228.0 * 255.255.255.0 U 0 0 0 qr-124ff148-b7
2 r# Q3 G3 L. s$ A# w H$ [11.0.0.0 * 255.255.255.0 U 0 0 0 qr-16d9b0cc-38
4 j% p# }: x5 D4 u- R) M20.0.0.0 * 255.255.255.0 U 0 0 0 qr-0bb8efeb-10" w0 R8 r: J: u6 k0 a0 G2 {* U& B) s
/ I1 y2 U- J! ]- g
9 d1 Q( t- o1 E; {* z0 B6 U2. linux-bridge-agent 工作过程分析
& c3 q4 V6 J: B6 s+ H4 ^8 l(1)linuxbridge-agent 会启动一个循环,不断扫描上面红框中的 tap 设备
, H; z+ ?* v/ ?
7 K! r1 x3 S2 N; R. ^3 z def daemon_loop(self):
5 S, B1 R+ m7 f/ I3 L }...# y. i7 p d* @1 v) h) x) z
while True:
+ Q' D# U* r! Y c0 T% R4 k5 x0 l start = time.time()% F( J' Z) Y/ O9 e+ s, E5 n
. ..+ ]: B% X z5 N6 c
! }6 y, ]/ }) q5 ]0 {% m8 n device_info = self.scan_devices(previous=device_info, sync=sync)- Z" c1 d, V g% J
sync = False
6 A* f0 f8 F- y$ j; m7 B4 D, R5 k& E q# }! |1 v G4 X
if (self._device_info_has_changes(device_info)
) r6 V# Y. N6 X, b* f7 L# q" ` or self.sg_agent.firewall_refresh_needed()):" e# L5 |, P; j1 f9 y
LOG.debug("Agent loop found changes! %s", device_info)
) g* \1 |. `, ~# [) y* ~% M try:
& U- k- @: X* a' h0 d sync = self.process_network_devices(device_info) ?7 K# M( U% L% l/ w
except Exception:
6 x# u* r& b. U- L) o LOG.exception(_LE("Error in agent loop. Devices info: %s"),! ^6 }- C- F& K/ _/ Z
device_info)7 x7 R' w/ b$ P: D
sync = True2 z0 Q& a$ F5 a6 l+ g
; L! ~% ]: |- G: ~" Y9 u5 o这是它首先找到的 devices:7 c6 o# s6 e; |8 C4 o2 X1 H
(Pdb) p bridge_lib.get_bridge_names()
6 h$ _- w7 a$ H2 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']+ @" A7 Q! @7 R8 E
然后过滤出 tap 设备:* O3 x6 r% c1 {: r% G
get_all_devices()->set(['tap0bb8efeb-10', 'tap60dbdc2f-a0', 'tap795e6e86-94', 'tap798c87d1-a2', 'tapb1eaae00-e5', 'tapf70543dd-0f'])0 z; y/ N' I% Y# N# |! K
(2)根据 previous 中保存的历史数据,再接合服务器端和本地更新时间,计算出需要更新的tap设备列表:
- H' B6 q4 g/ `% m3 X2 q6 z{'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([])}
1 _, x) H' c# v (3) 通过 RPC 获取 tap 设备的详细信息9 f- b& _2 X* p1 t: c' S
8 j; `7 ~* J$ u! U7 R' g
(Pdb) p devices
. S8 h. h* Y) }. |6 W& H# ?set(['tapf70543dd-0f', 'tap60dbdc2f-a0', 'tapb1eaae00-e5', 'tap795e6e86-94', 'tap798c87d1-a2', 'tap0bb8efeb-10'])8 H F+ H; m8 g1 O# I, ?- C
, X' e2 @5 Q6 d+ U: o& |
4 C3 h- c7 w3 J+ E; n; ^% _+ D Mdevices_details_list = self.plugin_rpc.get_devices_details_list8 g- @( [% m4 L+ v
! `4 F) B% h- W9 f
(Pdb) p devices_details_list, L+ K6 e% f5 n& i7 }
[{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': []}]
3 i# Q% D2 E+ D' m# l ( g1 M# u' v2 U
(4) 对需要处理的设备,调用 self.process_network_devices(device_info) 函数进行处理
$ X5 R8 m" R) m8 s(5). 调用 plug_interface% _1 y! V" @: ^5 h+ S8 ^
interface_plugged = self.mgr.plug_interface(network_id, segment,device, device_details['device_owner'])8 @! o) u2 h- q
(6). 需要的话,使用已经配置的或者新建 linux brige,并将 physical interface 设备加入其中; _! O: v; G* p* }
bridge_name = self.get_existing_bridge_name(physical_network) #获取为 physical network 配置的 linux bridge
) C4 G2 r6 q& I/ Dbridge_name = self.get_bridge_name(network_id) #或者根据 network id 生成 bridge name
0 n; ?9 i$ S$ d(7).根据不同的网络类型,分别处理 vxlan bridge,flat bridge 和 vlan bridge: a+ C8 K! A( C2 u
' D$ m/ @( l. K: i8 [5 C def ensure_physical_in_bridge(self, network_id,+ }( J. d8 w" N; @2 l
network_type,
) q2 P2 O6 W9 d2 U& c physical_network,* M$ L# U7 b/ h* y8 _8 m
segmentation_id):
3 b6 ?( q# [: J# D8 l. F if network_type == p_const.TYPE_VXLAN:
: p% _8 U- m1 ~6 [' H if self.vxlan_mode == lconst.VXLAN_NONE:$ u b, h9 U8 j7 h3 h/ c
LOG.error(_LE("Unable to add vxlan interface for network %s"),8 Q6 u2 d! n0 q$ V9 Z/ l; C
network_id): O; W p% b4 _; j+ v" f6 e f) j
return$ u; v& K- G* H
return self.ensure_vxlan_bridge(network_id, segmentation_id)
* }" f$ x! t. O7 b- M$ v, V1 ]
- {5 e7 i6 v T. l/ ]8 | @' t6 X( u # NOTE(nick-ma-z): Obtain mappings of physical bridge and interfaces6 T* }8 w/ ]8 M5 w7 _% l
physical_bridge = self.get_existing_bridge_name(physical_network)
- K. h0 v* M- `' A. p7 }4 j# H physical_interface = self.interface_mappings.get(physical_network)
7 j; t9 v' O% G( J! f+ ` if not physical_bridge and not physical_interface:
4 L% V0 \0 f6 ]" M5 ~ LOG.error(_LE("No bridge or interface mappings"
/ r* h4 y' o, L, W& Y+ y, T " for physical network %s"),
4 _+ {) A! B' n5 C- Q physical_network)8 F4 v* ]! P; I% Q' T$ |
return+ L# c( o5 ?; Y9 ?
if network_type == p_const.TYPE_FLAT:
) R7 L P8 V0 a, L return self.ensure_flat_bridge(network_id, physical_bridge,
* c+ U, y0 A( K; w3 C) } physical_interface)0 z( t( d3 N m- |7 O7 |& `2 Y
elif network_type == p_const.TYPE_VLAN:
- [/ |+ L y6 W! O6 v6 G% [ return self.ensure_vlan_bridge(network_id, physical_bridge,
$ M0 C: S |0 H N2 V9 G& @2 A- e physical_interface,
" @) }( n$ ~0 \$ o$ h segmentation_id)
: F! V# S+ }6 y# k
; y# Z; T( t7 A* j对于 flat 类型的网络,调用 ensure_physical_in_bridge' R* P: v5 e& w: j& U
def ensure_physical_in_bridge(self, network_id,network_type,physical_network,segmentation_id)1 g# g7 [: h( E( L
if network_type == p_const.TYPE_FLAT:
7 V( c1 S& z/ `* D! e1 a$ J5 q5 }; e# E return self.ensure_flat_bridge(network_id, physical_bridge,physical_interface)+ r/ M6 u- y* J$ ]/ g
如果有配置 physical bridge 的话,使用它;否则创建 bridge,并将物理网卡配置的 ip 地址和 gateway 从网卡挪到 linux bridge
0 R. E! v1 q% p8 l: k1 }5 \4 ~ + U. k! u" J" N6 ]4 q
def ensure_flat_bridge(self, network_id, phy_bridge_name,physical_interface):
/ R: x4 B$ o. Z% u; w% Q7 M# h """Create a non-vlan bridge unless it already exists."""
$ E: d9 {: h+ C* n if phy_bridge_name:
; c9 p' D0 j3 Y7 o! s9 q return self.ensure_bridge(phy_bridge_name) #获取预先配置好的 linux bridge) g7 n" X; i4 l2 V( B! Y
else:
$ D' M- v; \( l" m, h6 x i0 t. | bridge_name = self.get_bridge_name(network_id)
2 G; |% T6 }9 [: k: h" p' ]5 i ips, gateway = self.get_interface_details(physical_interface)" d, h! x/ P3 v! d. n( S ]/ o
if self.ensure_bridge(bridge_name, physical_interface, ips,gateway): #创建 bridge; a, V5 _ e( L# V; ?5 k/ J. _
return physical_interface! V) c2 ]5 f* F$ G3 [) h4 w& y o8 s# I
: | ]1 k& t2 h% b( F4 ]/ m
对于 vxlan 类型的 network,需要创建 vxlan interface
1 r6 G! N* f& D0 Z' t & J8 t/ d$ B ]6 k3 i: X' \1 ?
def ensure_vxlan_bridge(self, network_id, segmentation_id):
1 T3 u- A1 L" i """Create a vxlan and bridge unless they already exist."""
! O1 g c* g, R interface = self.ensure_vxlan(segmentation_id)& X) | B! F& e
if not interface:
& v( h# T( b: f* k% d2 R/ p LOG.error(_LE("Failed creating vxlan interface for "
& A7 s' t, ^& {5 G& @ "%(segmentation_id)s"),) P1 f% T1 u* h
{segmentation_id: segmentation_id})
# K4 Q" k) l) B' b return! @6 B( S; a, g0 A( s n5 _# K
bridge_name = self.get_bridge_name(network_id)
7 z$ ^' }! q& Z, B* d- B self.ensure_bridge(bridge_name, interface)% m$ s& ^5 V) Y G
return interface
2 p! X5 ~" m/ C
) N! R- e4 A1 A" q, C( d创建 vxlan interface:
, W. S: ]6 z( Q
: ?* h0 A6 r9 M! |& ?4 X) Y+ N3 V% M8 n def ensure_vxlan(self, segmentation_id):9 U) W( g ` G) L9 l) h
"""Create a vxlan unless it already exists."""
: q. u& B. W& q( @ interface = self.get_vxlan_device_name(segmentation_id)
4 y6 s8 Q( h4 K; @0 @, D( { if not ip_lib.device_exists(interface):: A" h7 T' w6 T! c: X& C6 ]
LOG.debug("Creating vxlan interface %(interface)s for ") c0 y- R( t) k0 H* q& p
"VNI %(segmentation_id)s",9 b; [* Q1 R. I
{'interface': interface,5 G# ^' b! |/ s1 a
'segmentation_id': segmentation_id})
/ D# x `3 O3 V* J args = {'dev': self.local_int}9 R# U9 j' J* N, H) R# b2 r& u. }6 G
if self.vxlan_mode == lconst.VXLAN_MCAST:
& P, X: T; o' t* m5 _/ E args['group'] = self.get_vxlan_group(segmentation_id)6 `2 Y. a# w& c
if cfg.CONF.VXLAN.ttl:
; j& I( Q( b- f! r! T3 b args['ttl'] = cfg.CONF.VXLAN.ttl
1 { s: X# D& R$ H+ H1 K. C if cfg.CONF.VXLAN.tos:! ?2 s5 O# x6 h4 d4 ^
args['tos'] = cfg.CONF.VXLAN.tos+ o' V% h9 W1 B& I! i" R
if cfg.CONF.VXLAN.l2_population:
* f6 ^+ P; l, b$ W4 d0 z3 _ args['proxy'] = cfg.CONF.VXLAN.arp_responder
" ]& b4 x9 S! r' d try:
5 s- j6 O0 i9 D a8 J t9 j int_vxlan = self.ip.add_vxlan(interface, segmentation_id,
, b+ A* w3 t' B2 L **args)
' X" t6 t, i% o3 [! w
2 M( @: j7 @. H4 e0 g6 Y- t(8). 将 tap 设备加入到 linux bridge 中1 H, j, ]# t) g( ]$ V
bridge_lib.BridgeDevice(bridge_name).addif(tap_device_name)
$ n' {( Q* v# _. H' \(9). 如果将一个 tap 设备被删除,那么 linux-bridge-agent 会发现:8 }9 [8 e# F# C) a- }
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']) ?6 F; r* W' x. q) D5 H6 c
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' i2 M4 {! M* E( j: I4 ?! q$ M
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.
l8 ~2 z9 @( l8 C6 R3 k+ k3. 关于上述工作过程的简单结论$ l* v8 M, r0 \0 J+ g
3.1 简单结论
! z$ |8 `* i- h1. l3agent 和 dhcpagent 创建 network namespace 时创建 tap 设备,和 network namespace 中的 interface 是一对 veth pair。当手工删除 tap 设备时,相应的 veth endpoint 也会被删除。2 G( i3 e+ e3 _
2. linuxbridgeagent 不断扫描服务器端和本地的 tap 设备/ f. k7 T/ c) d5 i: d H& X; ?
3. linuxbridgeagent 获取需要增加和修改的tap设备列表( R0 D% Z8 Q9 }1 D7 [$ U' a5 ~
4. 对于需要增加的 tap 设备,获取其详细信息,主要是 network_id,network_type,physical_network,segmentation_id,device_owner 等,然后根据这些信息,创建 linux bridge,并加入所需要的 interface; o5 g a) s5 U
5. 创建所需要的 linux bridge,并将 physical interface (provider network 的 physical interface 或者 tenant network 的 vxlan interface)加入 bridge,并且将 tap 设备也加入该 bridge' u7 d. H0 d- u5 i; ^" D6 p$ k# _ j$ O0 I
6. 如果发现某个 linux bridge 没有创建出来,首先需要查看有没有相应的 tap 设备存在;如果 tap 设备不存在,则查看相应的 qdhcp 或者 qrouter 中时候有interface
6 u# v' {0 o% Y# m- O " E- e, P5 u% @. w5 \2 f5 }! f- e U
具有多个 VLAN 租户网络时候的网络元素示意图:
/ I/ q; O& o7 W6 u% C+ T4 ]6 z
! C. u% X# j, q6 A
4 {5 Z, [3 y; c' O7 e4 m6 n 2 P: q4 v* ]7 a
& q* d& Y/ ?4 K" ~ 3.2 关于 unnumber interface
7 ?! y8 o n! v3 VOpenStack 官方的 host networking 配置中,连接外网的 interface 可以是 unnumbered 的,从字面意思理解,就是该 interface 上不需要配置 IP 地址。
, y* a" \1 g; H6 N+ X ?6 h8 s2 W, |, ?$ V N
配置的时候,修改 /etc/network/interfaces:
# A n1 j$ W4 T0 u# The provider network interface
. ~& S% c2 c* M% ?' p9 D* E0 tauto ens2243 z" @# u& p9 ? E: p }
iface ens224 inet manual! F# D8 O6 j, y
up ip link set dev $IFACE up
b B2 @3 F- w6 k% jdown ip link set dev $IFACE down
) W0 p6 E, n# l+ j9 F' }7 ~配置好以后:* b8 W/ `8 ?3 b0 n1 \9 l* ]: M
5 Q, v3 h+ t. j! _ j `% M
root@controller:/home/sammy# ifconfig ens224" S6 ~7 ]* G6 i! U4 d" ?
ens224 Link encap:Ethernet HWaddr 00:50:56:9c:4d:94; ^' Z5 n0 P& ]
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1% `" d: ~: [( m, O
RX packets:27300737 errors:0 dropped:0 overruns:0 frame:0
: b1 }+ K8 N: a; }& A. \ TX packets:61547 errors:0 dropped:0 overruns:0 carrier:0$ {( u, l: H( s3 w! g8 N3 u& e0 v, K* T
collisions:0 txqueuelen:10001 M9 z- S9 h$ W7 I
RX bytes:31951077598 (31.9 GB) TX bytes:5966060 (5.9 MB)
7 T. x: h+ u% |; U) u! V9 {2 W2 M' ^6 L4 e- H: I5 \0 t! G
root@controller:/home/sammy# ifconfig brq96609bfa-0e/ {( n( k- n. S# [
brq96609bfa-0e Link encap:Ethernet HWaddr 00:50:56:9c:4d:949 M' l* f- J8 v+ f* U* n; v3 z/ q
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:19 C- ^$ A8 i9 R5 x* l
RX packets:32855 errors:0 dropped:0 overruns:0 frame:0: z0 V# s& l! f9 L9 X
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
7 [4 @/ N O$ ?; k% K7 [ collisions:0 txqueuelen:1000( N3 L6 m/ i, A* K. V
RX bytes:2731030 (2.7 MB) TX bytes:84 (84.0 B)4 Q+ ~7 y: S2 X: s
# e g8 o7 o0 n/ W4 A; E具体原理不详,但是应该是因为 qrouter 的 qg network interface 和物理网络中的路由器的网卡之间是网络二层,因此中间的设备都是属于二层的,因此不需要处于网络三层的 IP 地址。
4 Q/ x; X6 I, x0 H* K( x4. 使用 linux bridge 时的拓扑结构
; A1 H1 c. b( k4.1 网络节点上3 x: ]( \. M) J+ O. Q* S u8 F' X- y
为了更清楚,我们来对比着看 linux bridge 和 ovs 的两种方案:, w. o' Z" z2 x; ]$ b
linux 方案:
" v+ k1 K! ~" R) l- H 0 k$ J; `: T7 }6 F, a: K ~
网络服务: Z G2 c: N! I7 f& u6 X$ I
• Linux bridge agent. J) ^1 U! B+ O; r) _/ t$ m& Z
• L3 agent! i# b( \- c8 x3 g, r" h
• DHCP agent6 y# }: | X7 L! b
• Metadata agent( G- P" P! |" {" A. W6 z
Linux bridge agent 会为每个 VLAN 虚拟网络创建一个 VLAN Bridge,它连接多个网元:) ~; \0 u% e) f' h2 L0 H/ G; K. z1 o
• VLAN 子接口,从物理网卡(图中的 interface3)上创建,每个子接口对应一个VLAN ID,其名称格式为 device.sid,其中 device 是物理网卡名字比如 eth0,sid 是 vlan id。
' N& t: ~$ @/ C• 连接虚拟机的 tap 接口
1 K4 u5 h6 G1 a) w+ ~) R• 和 qrouter 连接的 tap 接口
% R: Y+ {) B0 N& y# N, J• 和该网络的 qdhcp 连接的 tap 接口
- N1 }) T# H/ f1 b2 g如果同时有 VXLAN 虚拟网络的话(linux-bridge 不支持GRE 隧道模式),会为每个 VLAN 虚拟网络创建一个 Tunnel bridge。它连接多个网元:
& {6 p( W" P2 g. |* y1 ]0 v0 o• vxlan interface,这种接口每个虚拟网络一个,名字格式为 vxlan-sid,其中 sid 是分段ID。
4 O& r8 b- Q: l' ^) {9 H! W. T( P' s• 连接虚拟机的 tap 接口
# D% D }3 ~1 I" z• 和 qrouter 连接的 tap 接口6 Z# u, C; ?( N8 o5 b v5 { G% X
• 和该网络的 qdhcp 连接的 tap 接口# p! C D" t8 e8 |
安全组规则在 tunnel bridge 和 vlan bridge 上。' t8 {! r: q8 p; [9 w
OVS 方案:" Y0 t! f k: `# }' H4 Y) Q
3 g$ |/ m7 w3 {" H O5 y这里面,br-int 会负责加本地 VLAN 标签,br-tun 会负责将 VLAN ID 转换为 VXLAN ID。
, A; p. a6 Q8 ? * T4 S' I; i4 p' W+ i
4.2 计算节点上4 Y. M" _! ^ W1 ^/ w0 P) S1 w9 y
同样来对比着看。
! r& N/ z" Q, l2 R( y% P1 ]linux bridge:3 Y$ s8 a9 B! M
- B3 Z5 w% B# a L; N) R
网络服务:! h6 M8 w& l: n. P" A) _
• Linux bridge agent1 u( T6 j! G) Q( x3 ^3 r
和网络节点类似,只不过没有 qrouter 和 qdhcp,不在赘述。
; L& c: [6 t0 ]OVS:
& u$ a; p2 E: I7 O
$ |/ x/ k6 J; C/ p 2 v( ~' P! C% Q$ c5 B
OVS 放在在 br-int 上实现 VLAN 标签,在 br-tun 上实现隧道,在 qbr linux bridge 上实现安全组。/ M0 W8 u1 Z1 V9 W9 ~, r: M7 S
8 @& t/ ~, P! E# p. d4 e: `3 j4.3 网络路径 - 南北向网络流向' M9 B6 N/ Y+ D% O
' q6 T) T5 o' T7 k5 u
VLAN 网络和VXLAN 网络井水不犯河水。这图上的配置中,计算节点和网络节点上的物理网卡都分开了。
- j! x/ a1 w4 ^ e/ y! o. S4.4 网络路径 - 东西向(不同网络)3 g& O& l+ z* n
, a7 \# ~ g9 k, q4.5 网络路径 - 东西向(同一个网络)4 `- w* C- D6 u* R1 ^1 X+ b
2 P z& r9 ^" h# ^# P
- ~% H% a' F8 i4 [4 D请详细说明和配置,请参阅参考文档。* q0 u% z9 n8 s- K1 Q, @
5. 一点结论, z5 h0 P+ g. ^9 R
和基于 OVS 的二层网络相比,8 L. |5 e$ K: T* i* d9 O
• 功能和架构上:基于 linux bridge 的实现还是有一些短处,比如每个虚拟网络就需要一个网桥,这在大规模环境中会带领资源使用和管理上的问题。其好处是本身架构比较清晰。# E2 G e2 c+ G! l9 `( M; o1 U
• 性能上:基本上差不多,如下图所示,不管是 vxlan 还是 vlan。/ E$ V; c: x) u( J. n+ Y
( T% n$ y/ h/ `4 i
- P7 l* j% _5 M8 P0 P' n0 ` |
|