Neutron主要配置项解析




本文基于Mitaka版本neutron进行源码分析。

neutron插件机制很灵活,因此使用了Stevedore库来动态加载各种插件,可以参考这篇博文:A Look at two Python Plugin Managers: Stevedore and Pike,或者官方文档(博文中有链接)来了解Stevedore库的原理和用法。

/etc/neutron/neutron.conf

[DEFAULT] core_plugin = ml2

ml2是neutron的核心插件,所有neutron内置API请求都会被它处理(内置是与extension API相对而言的,主要包含network、subnet、port等资源的操作API,而像lbaas、vpn、fwaas等资源的操作API则需要借助相关extension来完成),因此必须配置,ml2更多的是作为一个参考实现便于其它extension的编写和提交,也可以起到规范其它extension的功能实现的用途。ml2 plugin的部分代码分析可以参考:neutron安全组相关代码分析

[DEFAULT] service_plugins

= neutron.services.l3_router.l3_router_plugin.L3RouterPlugin, neutron.services.metering.metering_plugin.MeteringPlugin, neutron.services.qos.qos_plugin.QoSPlugin,neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2

service plugin主要是用来支持除core plugin之外的其他资源的操作API的,neutron核心资源上面已经讲过,就包含很少的几个(network、subnet、port等),其他资源如qos、router、floatingips、fwaas、lbaas、vpnaas等的操作API都需要通过相应的plugin来支持,有部分老版本的plugin的实现是在neutron项目中(services目录下),而新版本的资源一般都是在各自独立的项目中,如neutron_lbaas、neutron_fwaas、neutron_vpnaas,减少与neutron主项目的耦合,便于各自独立快速的发展更新。

至于各个plugin怎么注册到WSGI的controller,关联到HTTP请求的method和URL的,这部分得分析neutron-server的启动流程,大致看了下代码,应该是在neutron.pecan_wsgi.startup.initialize_all这个方法里面注册的,这个方法的前半部分注册core plugin的resources(network、port等)的controller,后半部分注册extensions的resources(router、floatingip等)的controller。总体来说都是在neutron.api.v2.base.Controller这个入口处根据HTTP请求的method和URL转发到各个plugin的。

service plugin需要根据部署环境的需要来配置,比如采用VLAN模式则不需要router这种plugin,如果不需要防火墙,则不需要配置firewall plugin,其他也是类似。不启用某项配置,就表示该部署环境不支持相关的neutron扩展API,neutron API文档参考:https://developer.openstack.org/api-ref/network/index.html

[DEFAULT]notification相关

dhcp_agent_notification = True
notify_nova_on_port_status_changes = True
notify_nova_on_port_data_changes = True

dhcp_agent_notification、notify_nova_on_port_data_changes

dhcp_agent_notification是在发送HTTP请求给neutron-server之后,通知dhcp agent网络信息变更的,而notify_nova_on_port_data_changes则是在port信息变更后通知nova的。

这两个流程和用途比较类似,上面的after方法是pecan WSGI框架的hook实现,hook是在pecan的WSGI app初始化的时候配置的,after是在正常返回响应给请求方之前也就是请求处理完成后被调用的hook,before则是WSGI收到请求但还没有转发给controller之前被调用,关于pecan hook机制介绍,可以参考其文档:https://pecan.readthedocs.io/en/latest/hooks.html

notify_nova_on_port_status_changes

这个是注册在数据库的port表变更事件上的notify回调开关,port表有插入或更新或status字段变动就会发送通知给nova,也就是新建port、删除port、或者更新port状态都会发送通知。

上述几个notification,并不是通过MQ发送RPC消息给nova的,而是通过novaclient发送HTTP请求给nova服务,也就是说neutron不会通过MQ跟nova交互,仍然保持RestFul HTTP API来交互,这部分功能是新增的,之前的版本只有nova调用neutron API,但nova不知道neutron那边的port信息变更,有时候port都被删除或者状态更新了,nova却不知道,导致两边状态不一致,产生了很多的问题,因此加入了这个反向通知流程,具体提交的commit是:https://review.openstack.org/#/c/75253/

neutron.conf的配置项很多,但其他配置项的意义和用途都比较明确,尤其是区分section之后就更加清晰易懂了,因此不多做解析。接下来分析ml2 plugin的配置项。

/etc/neutron/plugins/ml2/ml2_conf.ini

[ml2]type_drivers = vlan

[ml2]tenant_network_types = vlan

[ml2_type_vlan]network_vlan_ranges = physnet1:1:4094

以简单的VLAN模式为例,上面两个配置项需要搭配使用。

tenant_network_types这个配置项可以参考:http://www.aboutyun.com/thread-16476-1-1.html,还有这篇:https://www.bbsmax.com/A/xl563Kk0dr/,VLAN模式的网络都是物理网络,必须在物理网络设备上被网络管理员提前配置好,neutron中的网络也要云平台的管理员根据物理网络配置信息来进行相应配置,如果配置的VLAN段在物理网络上没有配置好,那么neutron中的网络肯定是不可用的。普通租户创建网络不能指定VLAN ID,neutron会从network_vlan_ranges配置项里面挑选,而管理员则可以任意指定VLAN ID进行neutron网络的创建。

network_vlan_ranges配置项作用验证:

创建wp project,wp user,把wp user加入到wp project下,role为__member__,最后用openstack role assignment list命令查看wp user+wp project是否为非admin role。修改neutron ml2 plugin配置文件:/etc/neutron/plugins/ml2/ml2_conf.ini:network_vlan_ranges = physnet1:3456:3457,确保只有2个VLAN ID可用,最后重启neutron-server服务。

加载wp user、wp project认证配置之后分别执行如下命令:

切换到admin用户之后执行:

provider相关参数在vxlan type driver下不需要,具体可以参考neutron官方api文档。

type_drivers是配置neutron提供的网络类型(VLAN、VXLAN…),下面会讲到的mechanism_drivers则是配置实现该网络类型所采用的网络组件(openvswitch、Linux bridge…),二者并不是全部可以互相搭配使用的,官方文档给出了可用的搭配组合:https://docs.openstack.org/newton/networking-guide/config-ml2.html#ml2-driver-support-matrix

跟前面几个配置项类似,都是一样的在setup.cfg里定义了entry points,然后通过stevedore.named.NamedExtensionManager来加载相应的driver:

[ml2]
mechanism_drivers = openvswitch
extension_drivers = port_security, qos

mechanism_drivers可以做到让不同计算节点上的虚拟端口使用不同的底层物理网络类型,比如部分节点配置了SRIOV直通卡,可以配置上SRIOV的driver,不仅如此,它还能做到让同一个节点上的不同虚拟端口使用不同的底层物理网络,比如部分端口使用SRIOV,其他端口使用openvswitch。这也是neutron插件化灵活性的体现。

mechanism_drivers支持的类型有(定义在setup.cfg的[entry_points]):

实际可用的只有linuxbridge、macvtap、openvswitch、l2population、sriovnicswitch,上面提到过不同mechanism支持的type是不一样的,支持的type最全面的就是openvswitch了,也是最常用的一个。

mechanism driver主要在跟端口操作关联比较紧密,跟网络、子网关系不大,因为网络、子网操作主要是元数据的增删改,不涉及底层虚拟网络拓扑结构的变更,而端口操作如绑定到虚拟机或从虚拟机上解绑,则涉及到虚拟机所在物理机上虚拟端口(一般是tap设备)的创建、删除操作,这就要依赖openvswitch或者Linuxbridge来完成了,一般具体执行这个操作的服务都是对应物理机上的L2 agent如neutron-openvswitch-agent,毕竟这需要跟物理机上的ovs-vswitchd进程打交道。

想要了解mechanism driver的用途可以分析下update_port的流程,大致流程如下:

neutron.plugins.ml2.plugin.Ml2Plugin#update_port –> neutron.plugins.ml2.plugin.Ml2Plugin#_bind_port_if_needed –> neutron.plugins.ml2.plugin.Ml2Plugin#_attempt_binding –> neutron.plugins.ml2.plugin.Ml2Plugin#_bind_port –> neutron.plugins.ml2.managers.MechanismManager#bind_port –> neutron.plugins.ml2.managers.MechanismManager#_bind_port_level:

就算是这个流程,其实对于openvswitch mechanism driver来说,也是什么操作都没做,从该driver具体的实现来看neutron.plugins.ml2.drivers.openvswitch.mech_driver.mech_openvswitch.OpenvswitchMechanismDriver,其实现的方法很少,也就是说主要的操作,都是在L2 agent里面执行的。

而关于neutron-openvswitch-agent的处理update_port相关操作的流程,大致为(可部分参考之前写的nova添加安全组到云主机流程):

首先是注册MQ的rpc监听线程和相关回调,比如接收server端发送的port update、delete信息,并保存到OVSNeutronAgent的两个set中:

neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.main –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#__init__ –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#setup_rpc

之后是通过daemon_loop、rpc_loop轮询set是否有变动,并进行相应处理:

neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#daemon_loop –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#rpc_loop –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#_port_info_has_changes(检查port信息是否变更,update、add、remove这三种,满足条件之后调用) –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#process_network_ports –> …

type_drivers和mechanism_drivers的用途(Vlan type+ovs mechanism配置下,以create_network操作为例):

管理员指定provider信息情况,尝试按指定的进行分配:

/etc/neutron/plugins/ml2/openvswitch_agent.ini

[ovs]bridge_mappings = physnet1:br-eth7

这个配置项主要是设置provider网络对应的物理网络设备(根据mechanism不同一般是ovs bridge或者Linux bridge),这个bridge需要事先手工建好,然后还要把对应的物理网卡设备加入到bridge上,而br-int则不需要手工管理,br-int和虚拟机业务出口provider网络例如phynet1的br-eth7是通过patch port连接起来的。

这里只配置了一个phynet1使用的物理网络,其实可以配置多个provider网络,中间用“,”分开即可。

VLAN模式下该配置项用途解析:

首先是启动neutron-openvswitch-agent时检查配置项指定的bridge是否已创建,以及相关初始化操作:

neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#__init__ –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#setup_physical_bridges

其次是之后的rpc_loop过程中,发现port有变更时,进行ovs上该bridge相关流表信息的更新(比如ovs local vlan id 到物理vlan id的转换关系的维护等):

neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#daemon_loop –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#rpc_loop –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#_port_info_has_changes(检查port信息是否变更,update、add、remove这三种,满足条件之后调用) –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#process_network_ports –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#treat_devices_added_or_updated –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#treat_vif_port –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#port_bound –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#provision_local_vlan –> neutron.plugins.ml2.drivers.openvswitch.agent.ovs_neutron_agent.OVSNeutronAgent#_local_vlan_for_vlan –> neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl.br_phys.OVSPhysicalBridge#provision_local_vlan(添加流表)

结语

这篇和前面几篇neutron相关的文章,都是控制面API流程分析,这部分相对来说都是比较简单的,接下来我会继续尝试分析neutron的核心,东西向及南北向数据流,研究下在不同网络模式下数据包是怎么在虚拟机之间(同租户、跨租户)、虚拟机到物理机、虚拟机到外网等方向进行流转的。