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

楼主 |
发表于 2019-10-25 11:23:29
|
显示全部楼层
虽然大部分的OpenStack 部署环境中,都会使用 Open vSwitch 来作为虚拟交换机来实现二层网络功能,但是Neutron 仍然支持使用 Linux bridge 作为虚拟交换机来实现二层网络。本文就此做些分析和说明。
1 I! d( R6 O6 m: l% S1 ~# a% t同时要指出的是,OpenStack 官方已经把 linux bridge 实现标记为 legacy 的了,文档从 2016 年后也没怎么更新了。这是因为,linux bridge 和 OVS 相比,只支持基本的网络功能即二层交换,但不支持VLAN 标签和隧道。因此,linux bridge agent 利用linux 内核功能(VLAN 子接口和 VXLAN 接口)来实现VLAN 标签和隧道。
' B3 r2 E& J" L7 a$ Y' ~ . |! W7 B0 P/ e( @* Y
1. 测试环境
3 g- F7 w' _2 U% Y) X7 N以下面的环境为例(网络节点上):9 [' \5 T- i0 s3 A9 o3 r! ^- v. i) p
(1)linux bridge5 h d) \) j, D% ~7 s1 e$ B, U4 i1 t) N
0 ]# Y5 C- S o! `5 H5 Y( {root@controller:/home/sammy# brctl show
& E/ C5 e/ y3 Mbridge name bridge id STP enabled interfaces$ f3 I# G& F! c/ `6 `
brq85925305-b4 8000.563534c8d02d no tap0bb8efeb-10
; n. ~# i9 T+ K1 u tap798c87d1-a23 V) o E: d, \, M7 O# w
vxlan-25
9 ]1 @; ?( m+ N! ibrq96609bfa-0e 8000.0050569c4d94 no ens224
& M9 s: [) h0 H6 V tap60dbdc2f-a0
/ M! t: @- B5 \$ Q1 Vbrq971ffda2-e5 8000.a6acb08e4fd6 no tapb1eaae00-e5, w2 a5 I4 R3 O" ~; h3 ~# v- P
tapf70543dd-0f
8 O) H+ z8 m# o- O. V0 ~ vxlan-10
& J/ b- Q) d. y* G3 D ' z3 N& y9 t4 s
(2)OpenStack 网络和 network namespace:9 U" k- v; y2 s& B. n6 O: ^
% w2 ^. t. _, J- i, A
root@controller:/home/sammy# neutron net-list
! d( \5 x% e5 b4 f" g4 a( m+ i% f+--------------------------------------+---------+-----------------------------------------------------+
# g* J1 {( c6 S( {2 Q+ A| id | name | subnets |
/ e k2 V0 b( W) E$ Z$ _+--------------------------------------+---------+-----------------------------------------------------+
* Y3 P3 |/ L( v! I| 96609bfa-0e22-4bb7-8dba-6ef532ea6076 | extnet | afa7d205-3026-439f-aca7-295a9f9b2a71 10.62.227.0/24 |, H% b( Y0 y5 |7 H$ d
| 971ffda2-e567-40a0-a2c8-b31a577fd4d3 | appnet | 4c68eacb-bf3e-408a-a941-94e93eddb22b 11.0.0.0/24 |
& r! @# j5 ~& Y- U1 y| | | 3d596991-de8f-4ae4-8913-89426a8abbd7 10.0.0.0/24 | G8 e$ e/ p4 y8 Q0 w4 |
| 85925305-b477-4cc6-9654-67d9bf1e7cd8 | appnet2 | 4575c7f1-7f08-4917-9904-ec65af38619b 20.0.0.0/24 |
5 n; E: C8 ] ?+--------------------------------------+---------+-----------------------------------------------------+
# b e. T4 _: Z! |" D: Y2 ]root@controller:/home/sammy# ip netns
# f- G& ]9 ` ], g* gqdhcp-85925305-b477-4cc6-9654-67d9bf1e7cd8 (id: 2)1 S' y5 I$ ^2 p0 I* D
qdhcp-971ffda2-e567-40a0-a2c8-b31a577fd4d3 (id: 1)
. v5 k( T, z$ Y: \ [qrouter-39a77439-8a28-49c1-bf97-ac931510631b (id: 0)
- p) I* t/ |" ?0 I* W ! a! t* h- m" D. J
(3)示意图:; c' d. `3 c0 T. h8 p3 j
$ V3 z( J7 F O5 Q
(4)说明:
9 l1 T( v7 T( h6 Y, s, Z• qdhcp 和 qrouter 都是 linux network namespace 实例
I4 o! E% @: X6 c0 R1 u• qdhcp network namespace 的数量等于启用了 DHCP 的 Neutron network 的数量。7 X7 L/ P6 ]$ s; V& i0 o$ D
o 当一个 network 中存在至少一个 subnet 启用了 DHCP 之后,会有一个 qdhcp network namespace 被创建出来;
' a8 n7 ?, _% A8 J+ y3 xo 当一个 network 中多个 subnet 启用了 DHCP 时,它们共用一个 qdhcp,以及 dnsmasq。) h7 x) l; j# M5 X& w
o 其 name 使用 network id,比如 qdhcp-85925305-b477-4cc6-9654-67d9bf1e7cd8$ C2 z5 R% t/ o8 f/ S+ C/ k
• qrouter network namespace 的数目等于 router 的数目,也就是说,系统中一共有几个 router,那么就存在几个 qrouter network namespace2 M, _0 B# m0 m5 x# [8 b9 h- ^" P
• brq linux bridge 的数目等于 neutron network 的数目,其 name 是 network id 的前几位,比如 brq96609bfa-0e E! ?1 U7 E/ t; k
• 一个 network 的 qdhcp network namespace 和其 brq linux bridge 一定有连接' `. F' u/ K5 L$ ]$ c
• qrouter 之内的 network interface 分两种,一种是 qr 开头的,每个连接到 router 之上的 subnet 都有一个;还有一个是 qg,每个连接到 router 的 external subnetwork 有一个
( b' M% g G, I+ _+ W• qrouter 的每个 network interface 都通过 veth 连接到所在网络的 qbr linux bridge 上; A0 _# b" d+ \, U7 r" _+ ~* r/ [
• qbr linux bridge 连连接两种物理设备,一种是 vxlan interface,每个 tenant network 有一个,另一种是在 physical network 对应的物理网卡上创建的子接口(sub-interface)
~: @- ^4 K$ t1 ?! r• 对于 physical network 的 qbr 来说,用户可以指定它,并且在linuxbridge_agent.ini 中通过 bridge_mappings = List of <physical_network>:<physical_bridge> 进行配置;也可以不指定,此时 agent 会创建它。当同时配置了 physical bridge 和 physical interface 时,前者优先。
) G8 X2 l$ s& Q5 K5 n如果 external network 中有多个 subnet 的话:
/ q/ P1 ^4 M/ H3 s4 }' v! g5 R9 E(1)每个 qrouter 只允许有一个 External Gateway,也就是说它只有一个 qg network interface。当 external network 添加多个 subnet 之后,只有第一个被当作 external subnet,其余的都会被当作 internal subnet。
9 J( y& G* f. p, v2 s$ o0 _ [5 E(2)在 qrouter 的路由表之中,
: ^ z; B. e. l. J6 A6 b b * ]- G# \. s1 g, G* i2 Q
root@controller:/home/sammy# ip netns exec qrouter-39a77439-8a28-49c1-bf97-ac931510631b route
% h9 a: O% _" vKernel IP routing table9 J8 Q5 W W* q, K/ f( q% l' O
Destination Gateway Genmask Flags Metric Ref Use Iface. x8 h* O- N# w, n" ~: q' k5 y1 k
default 10.62.227.1 0.0.0.0 UG 0 0 0 qg-e09fce07-cd) Y! T% s% y5 d) ~$ e1 G3 J5 ~0 w* e
10.0.0.0 * 255.255.255.0 U 0 0 0 qr-b1eaae00-e5) D9 g8 w- C! ?2 f
10.62.227.0 * 255.255.255.0 U 0 0 0 qg-e09fce07-cd; F. k3 m, E* ?+ ?' C. t
10.62.228.0 * 255.255.255.0 U 0 0 0 qg-e09fce07-cd
3 z0 T& g" N. v, a2 M( W10.62.228.0 * 255.255.255.0 U 0 0 0 qr-124ff148-b7
) y G, {7 V# J( Q9 D# l5 N0 S11.0.0.0 * 255.255.255.0 U 0 0 0 qr-16d9b0cc-380 T; y! I! R2 H. Z0 q7 F8 V$ ?0 G# q0 c+ ?
20.0.0.0 * 255.255.255.0 U 0 0 0 qr-0bb8efeb-10& s* y0 j+ V6 ]9 f, n: |9 }4 g9 I
7 q, |- C; N& ~; n0 }
" T) |% ?! O; W: j" M7 n& w2. linux-bridge-agent 工作过程分析
/ \" C) P8 S9 e% m- ^(1)linuxbridge-agent 会启动一个循环,不断扫描上面红框中的 tap 设备
. `4 L: v p8 p- T+ e& ?5 j! r - w6 a- X: r& S3 u
def daemon_loop(self):
* a) Z5 V5 j' P9 G0 v. j...
; {4 c( l5 T5 N& _# r9 y O while True:6 n# N3 s* b6 w; J" Z
start = time.time()( P1 G2 }7 o, i# C
. ..+ c7 }* m+ Y: I9 v Q
! o3 u9 W$ U2 ~1 V; N d
device_info = self.scan_devices(previous=device_info, sync=sync)7 A& V8 S/ X# G& a: k
sync = False' L& `3 m+ @$ X; `% Z4 q
+ o/ p- p/ i5 v7 }1 C, w( j' M* L
if (self._device_info_has_changes(device_info)' B) a8 {0 L2 ~4 ~" k: ?0 @" @9 z
or self.sg_agent.firewall_refresh_needed()):: c4 Q6 n, G; t; |+ K
LOG.debug("Agent loop found changes! %s", device_info)' V7 K. l( g, k
try:. Z. G5 q$ V% ?0 ^% ~& v3 m
sync = self.process_network_devices(device_info)
/ U& m8 H% Y5 I' W- }& a except Exception: f& W. M: k. e5 I
LOG.exception(_LE("Error in agent loop. Devices info: %s"),
/ {% a) s! ^, J6 N4 L7 x) q( i device_info)' ~ `; Q2 ]0 W
sync = True! j: h: U: {1 P) |: T
) y- y/ u w- ~; x( I" r9 {8 @! D2 T
这是它首先找到的 devices:
2 T$ z% N$ x: O% {(Pdb) p bridge_lib.get_bridge_names()
& i# W" K1 e w; `0 h['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']
& [ P- _6 R# B, @然后过滤出 tap 设备:; Z6 Q: n( ~3 i& T5 J% L# Q
get_all_devices()->set(['tap0bb8efeb-10', 'tap60dbdc2f-a0', 'tap795e6e86-94', 'tap798c87d1-a2', 'tapb1eaae00-e5', 'tapf70543dd-0f'])
. e3 P! w' ^! o4 Z) r d(2)根据 previous 中保存的历史数据,再接合服务器端和本地更新时间,计算出需要更新的tap设备列表:& w- E! ~; v$ f6 i
{'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([])}9 J( Z2 K) Z+ r% \4 v) u2 }0 {
(3) 通过 RPC 获取 tap 设备的详细信息/ I: }$ u6 h; q) j% k
: ~2 s0 z- v9 U. Y5 V. d
(Pdb) p devices
4 @6 b8 e) o: a' \& u$ Rset(['tapf70543dd-0f', 'tap60dbdc2f-a0', 'tapb1eaae00-e5', 'tap795e6e86-94', 'tap798c87d1-a2', 'tap0bb8efeb-10'])8 v. {- S( E# q1 t
( i; a' k5 a n% m7 C- `
" U/ X# i3 [6 n7 }; R
devices_details_list = self.plugin_rpc.get_devices_details_list; }0 i4 g. o- d; D
; I+ t" q5 x) T. ]) i2 A
(Pdb) p devices_details_list/ {& @$ s; J9 U
[{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': []}]
4 j& |; Z- V8 [
$ A" g+ p/ W+ v2 l. \+ B(4) 对需要处理的设备,调用 self.process_network_devices(device_info) 函数进行处理
- S; }5 H8 b) N1 O7 v(5). 调用 plug_interface
' l; W4 W" C' C( S9 X! {3 q/ zinterface_plugged = self.mgr.plug_interface(network_id, segment,device, device_details['device_owner'])
! E0 D, D9 P. c' \4 \* p(6). 需要的话,使用已经配置的或者新建 linux brige,并将 physical interface 设备加入其中4 f/ w1 k3 ^/ N3 \% o8 Z3 R
bridge_name = self.get_existing_bridge_name(physical_network) #获取为 physical network 配置的 linux bridge: `" `$ H! D7 E; w2 B/ m
bridge_name = self.get_bridge_name(network_id) #或者根据 network id 生成 bridge name7 x, ]# [$ O7 T# h/ p5 k" a0 M
(7).根据不同的网络类型,分别处理 vxlan bridge,flat bridge 和 vlan bridge
1 [5 r1 d" K0 i 4 }: f ? F5 Q
def ensure_physical_in_bridge(self, network_id,& _. d- F9 R, C6 G' F$ \9 z6 @
network_type,
8 m4 p8 R0 a9 f- q" `2 q. ^, u: q physical_network,# O1 t6 v* ^# ^9 f- M
segmentation_id):
" s6 B6 X3 f" W8 V, G if network_type == p_const.TYPE_VXLAN:
, i( R1 `& G! h i+ m if self.vxlan_mode == lconst.VXLAN_NONE: [3 n2 b6 v S' P' E
LOG.error(_LE("Unable to add vxlan interface for network %s"),; S w& ~: e9 F7 S- G' N, R' s
network_id)
+ i# }1 k# w$ ^ n: @% J9 J return+ f% P' q9 d' W: o$ D
return self.ensure_vxlan_bridge(network_id, segmentation_id)# v8 h: O b2 x, x" p* f
9 ~: M4 J B+ K* t' F t
# NOTE(nick-ma-z): Obtain mappings of physical bridge and interfaces
* n! v3 D+ x4 C physical_bridge = self.get_existing_bridge_name(physical_network)
7 B7 d c; }/ F; t1 C; } physical_interface = self.interface_mappings.get(physical_network)
2 A8 v6 Z9 R+ P$ c/ H9 K if not physical_bridge and not physical_interface:) ^. {+ z' R- L# y& N4 L- m6 F5 K
LOG.error(_LE("No bridge or interface mappings"
# o# t- F. w, C& S, C2 V* f' x " for physical network %s"),% `! v% s- v( b
physical_network)
" V5 G* e5 B1 v$ E* G- ]0 h5 v return
9 k5 t6 r9 `. k! h" l4 P if network_type == p_const.TYPE_FLAT:! f+ o! |. G5 ~% E
return self.ensure_flat_bridge(network_id, physical_bridge,
9 K# c8 _: t. \) D; E3 f P physical_interface): s; b8 z$ P1 G& V; G1 x2 ^( R# Q5 q1 Z
elif network_type == p_const.TYPE_VLAN:
& u! W: A2 f, |# ?4 f; { return self.ensure_vlan_bridge(network_id, physical_bridge,9 d8 l+ _2 O; `8 `
physical_interface,8 T' y4 K6 F9 ^, A$ @
segmentation_id)
2 c6 D e z7 v+ x
5 E* @- b; a: L5 P/ W) [/ q1 f对于 flat 类型的网络,调用 ensure_physical_in_bridge
: I# u, A$ g' A& H9 O. pdef ensure_physical_in_bridge(self, network_id,network_type,physical_network,segmentation_id). \5 D3 c( V' T7 p% ?6 T9 { v/ O, V
if network_type == p_const.TYPE_FLAT:6 E. ]# W4 U) S4 L, E1 i: R
return self.ensure_flat_bridge(network_id, physical_bridge,physical_interface)
) ]; \8 t- F& U% s8 T7 `/ j( I如果有配置 physical bridge 的话,使用它;否则创建 bridge,并将物理网卡配置的 ip 地址和 gateway 从网卡挪到 linux bridge1 p0 ^/ o3 l; b$ V& V
1 p' H' y m2 U2 C' j' V0 h( H" ? X
def ensure_flat_bridge(self, network_id, phy_bridge_name,physical_interface):
$ P4 m- F) `* _- R9 Q% [ """Create a non-vlan bridge unless it already exists."""
& ~ Q* `6 f" n if phy_bridge_name:
' |* O# N0 T7 W; G% e; c return self.ensure_bridge(phy_bridge_name) #获取预先配置好的 linux bridge* A& V8 G4 W8 L' e
else:
9 X$ |+ }$ }5 e+ A O8 I+ g9 H bridge_name = self.get_bridge_name(network_id)5 M8 I1 P2 P, d& F" m
ips, gateway = self.get_interface_details(physical_interface)8 x1 w1 M8 l0 P
if self.ensure_bridge(bridge_name, physical_interface, ips,gateway): #创建 bridge5 X1 I$ ], f: h& Y
return physical_interface' c1 ~* r* J0 x$ \& S: Q
$ d& q7 ^% H [2 o+ }5 H
对于 vxlan 类型的 network,需要创建 vxlan interface
: Q1 E V: ]1 I: t; V4 i& Y
Q c1 E- Y# N- ^" b ?0 l- e1 V def ensure_vxlan_bridge(self, network_id, segmentation_id):
( I& S* t: @. {3 F6 {$ m3 } """Create a vxlan and bridge unless they already exist."""
) |/ `0 j" g. ^3 r% {7 r1 c interface = self.ensure_vxlan(segmentation_id)0 f9 w2 p1 N" E5 Z- l" f
if not interface:1 X' L* F6 Z" l+ ^5 D
LOG.error(_LE("Failed creating vxlan interface for ", v4 `+ f: D- J# u' P
"%(segmentation_id)s"),
2 H; Q) k& v; e) U: Z! O [ {segmentation_id: segmentation_id}); U3 j7 f8 @8 x1 A$ f
return
8 ~* c" V4 M b+ D5 o bridge_name = self.get_bridge_name(network_id), W m- r4 i0 T* M) [
self.ensure_bridge(bridge_name, interface)6 W" H6 k$ V* G7 S
return interface9 m: X1 d0 l* m+ w' u4 d: x: P
" \) F b. {8 E! x. ?3 _6 I2 Q4 S/ m4 Y H
创建 vxlan interface:
7 Z# H7 N5 z0 g0 J- ?- ]
+ D# f% N- T- m1 w* a def ensure_vxlan(self, segmentation_id):$ x9 j* i9 n( | v. [6 a
"""Create a vxlan unless it already exists."""5 Q. G- I G. K4 Z7 |
interface = self.get_vxlan_device_name(segmentation_id)
' g8 x: \( q' {- n3 s if not ip_lib.device_exists(interface):$ p- G. }( |5 {. K' @6 }+ j
LOG.debug("Creating vxlan interface %(interface)s for "
5 I U8 d& I2 q6 h "VNI %(segmentation_id)s", K9 l+ ]: F! V8 U
{'interface': interface,0 i( A; x) S: ?3 {7 G5 D
'segmentation_id': segmentation_id})+ B5 U. Q& o S) T6 r) b' L
args = {'dev': self.local_int}3 H& t) n( o4 U: A( S
if self.vxlan_mode == lconst.VXLAN_MCAST:1 ?* e9 L" F0 C' w. ]/ H
args['group'] = self.get_vxlan_group(segmentation_id)
2 L _& } }, G4 ?; J if cfg.CONF.VXLAN.ttl:. v$ o; D" M- `
args['ttl'] = cfg.CONF.VXLAN.ttl: A( [* m1 R% h
if cfg.CONF.VXLAN.tos:' e) H8 N! o- V6 ]4 S0 z- F% E
args['tos'] = cfg.CONF.VXLAN.tos
3 o. J8 M4 w- T: E) _2 ^ if cfg.CONF.VXLAN.l2_population:
) g3 s- v( ^. h( W, p args['proxy'] = cfg.CONF.VXLAN.arp_responder5 C4 i. P( Q+ Q. p8 Z
try:7 t! e; U* u; g( R
int_vxlan = self.ip.add_vxlan(interface, segmentation_id,1 l) i: f7 M1 V. G* }/ N: O
**args)
9 |& N( N" V& P
3 W4 Y: W2 G' i0 {(8). 将 tap 设备加入到 linux bridge 中
0 Y) l! C2 O/ c5 obridge_lib.BridgeDevice(bridge_name).addif(tap_device_name) R! }4 J( l( T3 G) Z# h* m, \
(9). 如果将一个 tap 设备被删除,那么 linux-bridge-agent 会发现:
% d" T; u- c& y- ^3 |2 y2016-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'])
3 ]$ @$ }. W7 p% D# F2016-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: |6 @8 g4 M ^' K
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.
. f. W4 U" R0 ~4 g, V; q3. 关于上述工作过程的简单结论
8 T- P7 H- ]2 D1 f* j3.1 简单结论& W( ~9 t$ ]) [
1. l3agent 和 dhcpagent 创建 network namespace 时创建 tap 设备,和 network namespace 中的 interface 是一对 veth pair。当手工删除 tap 设备时,相应的 veth endpoint 也会被删除。
: ?8 B j& ]' u3 A' G; e2. linuxbridgeagent 不断扫描服务器端和本地的 tap 设备2 V# H k$ r6 @) a% J
3. linuxbridgeagent 获取需要增加和修改的tap设备列表& w+ \6 e) _$ s* ^3 c
4. 对于需要增加的 tap 设备,获取其详细信息,主要是 network_id,network_type,physical_network,segmentation_id,device_owner 等,然后根据这些信息,创建 linux bridge,并加入所需要的 interface2 s) R5 Z! C# ^+ f
5. 创建所需要的 linux bridge,并将 physical interface (provider network 的 physical interface 或者 tenant network 的 vxlan interface)加入 bridge,并且将 tap 设备也加入该 bridge/ d' M& N7 b0 S6 {* K
6. 如果发现某个 linux bridge 没有创建出来,首先需要查看有没有相应的 tap 设备存在;如果 tap 设备不存在,则查看相应的 qdhcp 或者 qrouter 中时候有interface' a7 @5 s% J3 M0 ?" f! L
/ n, c8 g7 `5 M o具有多个 VLAN 租户网络时候的网络元素示意图:
. a# }4 ], Y' g! ]% }# d
. X# e! g/ T; ~( Q1 a3 c/ x ^. S 7 L, e% p c) E0 B# I
' j2 M/ }! R; m. E 8 F( g# F0 _ }; v4 h0 h( {
3.2 关于 unnumber interface
9 o- K+ s2 b$ `; W! S jOpenStack 官方的 host networking 配置中,连接外网的 interface 可以是 unnumbered 的,从字面意思理解,就是该 interface 上不需要配置 IP 地址。' L w- T3 C- U, A) l
! Z3 M7 T. }( ~# Q0 r. X7 ~) ]( n
配置的时候,修改 /etc/network/interfaces:* u2 R- w! S3 \' h9 o' L
# The provider network interface
9 M+ h- R# s$ T0 h% m! cauto ens224
1 x Z3 i2 W+ S) u! _" giface ens224 inet manual1 e& x4 K. i& Q1 _
up ip link set dev $IFACE up9 @6 K2 K7 V H& |# K: R: B
down ip link set dev $IFACE down0 n! b8 G2 R$ \9 ?# B# @
配置好以后:3 A3 Y: i5 U, g6 b, a. ~5 y, B+ W
2 R f; q& Y% h i9 V3 x5 ^. T
root@controller:/home/sammy# ifconfig ens224 v" [' ^+ l# s/ q4 g
ens224 Link encap:Ethernet HWaddr 00:50:56:9c:4d:94 t6 _6 e. |8 t b- s D4 Z# [
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:15 k2 q+ l, A6 s; V9 ^! m
RX packets:27300737 errors:0 dropped:0 overruns:0 frame:0
. s3 F9 }* |8 w TX packets:61547 errors:0 dropped:0 overruns:0 carrier:00 G" F2 c" z, q" {" d
collisions:0 txqueuelen:1000
8 b$ ]' m8 l/ R: X% d RX bytes:31951077598 (31.9 GB) TX bytes:5966060 (5.9 MB)! [( `# T, R: g8 ~% g
' K6 p H$ Q4 K5 n% O
root@controller:/home/sammy# ifconfig brq96609bfa-0e
6 F7 X" V8 Q+ V7 }9 ~brq96609bfa-0e Link encap:Ethernet HWaddr 00:50:56:9c:4d:94
) f2 K1 R- U! w7 l5 }) C4 a5 a9 x UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1( n4 Z& O4 m3 N* N6 i0 x
RX packets:32855 errors:0 dropped:0 overruns:0 frame:0' Y# |* O4 l8 @0 a3 P) t/ L$ J" L- [) H( H
TX packets:2 errors:0 dropped:0 overruns:0 carrier:03 D" M J4 r! n3 o Z6 a8 v
collisions:0 txqueuelen:1000
; ~+ G7 i0 `' s RX bytes:2731030 (2.7 MB) TX bytes:84 (84.0 B)
8 E" _$ p, h" U9 U W - D3 ]: L( n7 U e6 t
具体原理不详,但是应该是因为 qrouter 的 qg network interface 和物理网络中的路由器的网卡之间是网络二层,因此中间的设备都是属于二层的,因此不需要处于网络三层的 IP 地址。% Z3 c' g6 H# w# \3 m7 Q
4. 使用 linux bridge 时的拓扑结构
- l' W* U7 e; |5 V4 l! j7 r0 J# o- @4.1 网络节点上
' _0 ?( p4 c# Q; W: e为了更清楚,我们来对比着看 linux bridge 和 ovs 的两种方案:; B/ `! _; s2 T0 X4 o# |3 d
linux 方案:
- D. F; m6 w- }! p& Q 3 E$ I5 Y, ^, l7 p6 v
网络服务:% ?- W( u& b9 P
• Linux bridge agent
& T. r8 n4 [/ o3 V• L3 agent
) j% W/ H% U% _. n$ g! s• DHCP agent+ U4 X% J* o w( u8 Q
• Metadata agent
8 m8 B) h9 k6 X4 cLinux bridge agent 会为每个 VLAN 虚拟网络创建一个 VLAN Bridge,它连接多个网元:
( m( ~1 u- s( m7 V, J8 [• VLAN 子接口,从物理网卡(图中的 interface3)上创建,每个子接口对应一个VLAN ID,其名称格式为 device.sid,其中 device 是物理网卡名字比如 eth0,sid 是 vlan id。& k' F3 g$ B# c" z" ~
• 连接虚拟机的 tap 接口" ]& j/ w' }; J( U
• 和 qrouter 连接的 tap 接口$ v7 N% i6 Q$ R. Y2 w
• 和该网络的 qdhcp 连接的 tap 接口
6 G' A7 o& }( w/ }* o0 M如果同时有 VXLAN 虚拟网络的话(linux-bridge 不支持GRE 隧道模式),会为每个 VLAN 虚拟网络创建一个 Tunnel bridge。它连接多个网元:& [. O/ c0 e: N2 |% ?& x
• vxlan interface,这种接口每个虚拟网络一个,名字格式为 vxlan-sid,其中 sid 是分段ID。
! ]; u! |' ~8 l# M l• 连接虚拟机的 tap 接口; j* T* c% p" A* O4 f
• 和 qrouter 连接的 tap 接口4 M3 ~- t$ f8 [/ Q% T2 N
• 和该网络的 qdhcp 连接的 tap 接口/ f& R) N+ ?0 F
安全组规则在 tunnel bridge 和 vlan bridge 上。( ^. C; N, [% d+ H& ^
OVS 方案:
; X. E! D3 h& s" x3 M, x/ e
! }, u, [0 i/ y- X3 V这里面,br-int 会负责加本地 VLAN 标签,br-tun 会负责将 VLAN ID 转换为 VXLAN ID。* k: O" ^" D1 o' x7 y
" z, u) `- ~" b+ ?7 D# p! M4.2 计算节点上
8 `, _4 Z! `* S同样来对比着看。! g9 V4 k6 y, F5 m
linux bridge:
" d3 C& Z2 B* B% m
- _1 D1 v/ X1 p+ L% Z+ s+ w% k# s$ H网络服务:1 q. W0 o) Z% i
• Linux bridge agent
/ C5 z" U4 L) q! j- B和网络节点类似,只不过没有 qrouter 和 qdhcp,不在赘述。- L& y- C/ K8 {1 j; V/ V* {8 X
OVS:6 l2 w7 g, d! i# ^3 |, b
; T V. w) ~. x/ t, J M; E6 f / _8 u% g1 T4 d Q4 [% _
OVS 放在在 br-int 上实现 VLAN 标签,在 br-tun 上实现隧道,在 qbr linux bridge 上实现安全组。0 m+ `$ |2 b" ?( ?
( m7 J: R; ^; I+ x6 b7 `4.3 网络路径 - 南北向网络流向
, v; \) ]9 `' m s+ G
, ?% c- O% H; Q: AVLAN 网络和VXLAN 网络井水不犯河水。这图上的配置中,计算节点和网络节点上的物理网卡都分开了。) i9 e$ _6 ^6 _0 @
4.4 网络路径 - 东西向(不同网络)" B" f, E4 ^+ h
7 p$ b8 K9 _" F T4.5 网络路径 - 东西向(同一个网络)
7 b) P# F8 o: f; z$ H9 z$ c9 x5 M# n * Z o3 G9 u* z/ u. L) M3 E! C
1 q3 l1 p" g. z! c
请详细说明和配置,请参阅参考文档。1 |% `" ?, E; W) M4 t
5. 一点结论
" y2 B: _* d2 z; I% l5 h2 ^& L和基于 OVS 的二层网络相比,
( g% s0 M# h1 \2 s, s6 y$ s• 功能和架构上:基于 linux bridge 的实现还是有一些短处,比如每个虚拟网络就需要一个网桥,这在大规模环境中会带领资源使用和管理上的问题。其好处是本身架构比较清晰。
$ o H6 b/ V2 B( X• 性能上:基本上差不多,如下图所示,不管是 vxlan 还是 vlan。
6 H' K. K! W! U5 @9 ?3 x% F 0 ?1 F+ n. M0 G7 k$ N! w
+ M+ q6 K" g5 q3 Q
|
|