openstack学习之neutron_linuxbridge_agent分析

  • Post author:
  • Post category:linux

linuxbridge是和linuxbridge plugin匹配的core agent,主要实现L2层的功能和security group的功能。security group的功能逐渐会被neutron firewall取代。

linuxbridge的启动命令在linuxbridge_neutron_agent.py中
启动的时候需要提供neutron.conf和linuxbridge_conf.ini配置文件

主要配置项:
linuxbridge_conf.ini
[vlans]
network_vlan_ranges = physnet1,physnet2:1000:2999
tenant_network_type = vlan
[linux_bridge]
physical_interface_mappings = physnet1:eth0,physnet2:eth1

其中physnet1和physnet2表示该节点可用的物理网络名字(physical network, 名字可以随便定义),physical_interface_mappings用来把名字和该网络使用的物理网卡对应起来。

physical_interface_mappings的作用
physical_interface_mappings是linuxbridge中最重要的配置项。用来定义节点中的物理网络,可以有多个。openstack中的节点(按功能不同,可分为计算节点,dhcp节点,L3节点等)通过物理网络实现互联。这个物理网络用来实现neutron中定义的虚拟网络拓扑,和openstack的管理网络不是一个,是不同的概念。

虚拟网络的流量需要通过物理网络承载,而物理网络其实就是该节点上的网卡。在linuxbridge实现中,每个网络对应一个bridge,每个网络又会有一个物理网络(provider:physical_network属性)来承载,与该物理网络对应的网卡(physical_interface_mappings中配置,如physnet1对应eth1),会被加入这个bridge中,这样该网络就可以和外部系统通信了。

如果虚拟机中需要和外网相连(访问Internet),需要在L3节点(负责路由功能)上配置可以访问外部的物理网络,然后创建一个provider网络和这个物理网络对应起来。把该provider网络和需要访问外网的虚拟机所在网络加入同一个路由器,即可实现访问外网的功能。
例子:
创建provider网络,public01是该网络的名字,physnet1是物理网络的名字。physical_interface_mappings需要配置physnet1对应的物理网卡,如eth0。
$ neutron router-create router01
$ neutron net-create –tenant-id $tenant public01 \
          –provider:network_type flat \
          –provider:physical_network physnet1 \
          –router:external=True
$ neutron subnet-create –tenant-id $tenant –name public01_subnet01 \
          –gateway 10.64.201.254 public01 10.64.201.0/24 –disable-dhcp
$ neutron router-gateway-set router01 public01

创建可访问外网的网络net01(vlan类型),该网络的物理网络是physnet2。physical_interface_mappings需要配置physnet2对应的物理网卡,如eth1。
$ neutron net-create –tenant-id $tenant net01 \
          –provider:network_type vlan \
          –provider:physical_network physnet2 \
          –provider:segmentation_id 101
$ neutron subnet-create –tenant-id $tenant –name net01_subnet01 net01
192.168.101.0/24
$ neutron router-interface-add router01 net01_subnet01

创建另外一个可访问外网的网络net02 
$ neutron net-create –tenant-id $tenant net02 \
          –provider:network_type vlan \
          –provider:physical_network physnet2 \
          –provider:segmentation_id 102
$ neutron subnet-create –tenant-id $tenant –name net02_subnet01 net02
192.168.102.0/24
$ neutron router-interface-add router01 net02_subnet01

这两个网络中的VM就可以访问外网,通过SNAT方式。如果需要外部网络直接访问VM,需要给VM分配一个floating IP地址。

关于网络的概念可以参考博文《openstack学习之白话Openstack》中关于网络的介绍。

linuxbridge agent功能
主要有三个任务:
1)报告状态。
2)处理RPC API。
3)在本节点实现neutron中定义的网络拓扑。

1)报告状态
在def _report_state(self)中实现,这个函数被周期调用:
            heartbeat = loopingcall.FixedIntervalLoopingCall(
                self._report_state)
            heartbeat.start(interval=report_interval)

_report_state主要是通过REST API将自己的状态发送给core plugin。可以参看代码。

2)处理RPC API

处理RPC的代码在LinuxBridgeRpcCallbacks中,主要有2个API:

def network_delete(self, context, **kwargs):
def port_update(self, context, **kwargs):

network_delete主要用来删除该节点上的bridge设备。
port_update处理对port的属性更新:segmentation_id,network_type和physical_network。

这里边还有和FDB相关的API,实现population功能。

3)实现网络拓扑。
实现网络拓扑的主要功能就是:
a)创建bridge,将相应物理网络的网卡接口加入该bridge。
b)将TAP设备加入到bridge中。每个neturon port会有一个tap设备创建,port是一个逻辑概念,tap是port的物理实现。openstack中使用port的设备主要有:虚拟机,DHCP agent和L3 agent。
虚拟机上每个网卡对应一个port,也就是一个tap设备。
dhcp agent针对每个服务网络(使用该agent提供DHCP服务)都会创建一个port。
L3 agent上的每个路由器(router)也会有相应的port接入不同的网络。

每种设备会针对每个port创建一个tap设备。linuxbridge agent负责将这些tap设备接入到相应的bridge中。

代码实现主要在def daemon_loop(self)中。
代码的主要流程是:
a 扫描该节点上的TAP设备:device_info = self.br_mgr.update_devices(devices)
b 处理扫描的TAP设备:process_network_devices(device_info)

扫描设备通过遍历目录/sys/devices/virtual/net实现。
处理设备主要有两种情况:增加和删除。(更新操作由前面的RPC API处理)
treat_devices_added
treat_devices_removed

在treat_devices_added中,会把port的状态更新成ACTIVE;在treat_devices_removed会把port的状态变成DOWN。状态更新会发给core plugin。在nova boot后,VM PORT是DOWN状态,只有当相应的linux bridge将其port状态变成ACTIVE时,boot才会成功。
boot过程中会等待port变成ACTIVE状态:wait_for_instance_event

某些类型的Hypervisor driver会将tap设备直接加入到bridge(也会创建相应的bridge)中,如libvirt的driver。这个不影响linuxagent的处理。


创建bridge的代码:
        if network_type == p_const.TYPE_FLAT:
            return self.ensure_flat_bridge(network_id, physical_interface)
        elif network_type == p_const.TYPE_VLAN:
            return self.ensure_vlan_bridge(network_id, physical_interface,
                                           segmentation_id)

流程比较清晰,可以参考代码实现。

其他
linuxbridge的配置不是持久化(persistent),每次重启OS后,所有的配置都会消失。

linuxbridge只有在设备使用了某个port时,才会在该节点上创建相应的bridge并加入tap设备。如果只是创建了网络或者该节点上没有设备使用该网络,并不会有bridge创建出来。这就是所说的”OpenStack provisions networks “on demand”。

源自网络的2张图:第一张是计算节点;第二张是DHCP + L3节点




版权声明:本文为zhengleiguo原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。