Quality of Service
Quality of Service高级服务设计为一个服务插件。此服务在多个层级上与其与的Neutron代码解耦(见下文)。
QoS在没有使用继承自插件的mixins的情况下,通过使用ml2 extension 驱动程序,扩展了核心资源(ports,networks)。
关于DB models, API extension, and use cases的详细信息可在此链接查看 qos spec。
.
neutron.extensions.qos:
基础extension + API 控制器定义。注意规则是策略的子属性,所有嵌入在了它们的URIs中。
neutron.extensions.qos_fip:
基础extension + API 控制器定义。添加 qos_policy_id 到浮动IP地址,使用户可设置/更新浮动IP的绑定QoS策略。
neutron.services.qos.qos_plugin:
QoSPlugin,实现“qos”扩展的服务插件,接收和处理创建/修改策略和规则的API调用。
neutron.services.qos.drivers.manager:
管理器,传递对象动作到每个使能的QoS驱动,当任何驱动请求RPC 推送通知时,触发RPC调用。
neutron.services.qos.drivers.base:
可插QoS驱动的接口类,用来通知后端关于任何规则或策略改动的事件(创建、更新、删除),包括precommit事件,一些后端需要其来进行同步。此驱动也声明支持的QoS规则,VIF驱动和VNIC类型。
neutron.core_extensions.base:
包含实现核心资源(port/network)扩展的接口类。核心资源扩展很容易整合进感兴趣的插件。我们可能需要一个核心资源扩展管理器,来使用这些扩展,以避免为每一个新的核心资源扩展修改插件。
neutron.core_extensions.qos:
包含QoS核心资源扩展,其符合以上描述的接口。
neutron.plugins.ml2.extensions.qos:
包含ml2扩展驱动程序,其通过重用以上提到的core_extensions.qos模块处理核心资源的更新。将来,我们会看到一个不区分插件的核心资源扩展管理器,其可容易的整合进其他的插件中。
类neutron.extensions.qos.QoSPluginBase为与QoS策略规则相关的方法使用method proxies。每个这样的方法都是通用的,旨在处理任意的规则类型。例如,QoSPluginBase有一个方法“create_policy_rule”,而不是一个“create_policy_dscp_marking_rule”方法和一个“create_policy_bandwidth_limit_rule”方法。方法代理(method proxies)之后的逻辑对插件的“create_policy_dscp_marking_rule”的调用由方法“create_policy_rule”处理,其将接收到作为参数的“QosDscpMarkingRule”对象,以便执行特定于DSCP marking规则类型的操作。这种方式允许引入新的规则类型,而又不需要插件更改代码。可期望的,QoSPluginBase的子类必须覆盖基础类的“abc.abstractmethod”方法,即使是NotImplemented。
每个QoS驱动有一个属性名为“supported_rule_types”,其表示此驱动可支持规则。
所有规则类型的列表,可参见: neutron.services.qos.qos_consts.VALID_RULE_TYPES.
Neutron显示的支持的QoS规则列表只是所有活动的QoS驱动支持的规则的通用子集。
注意:核心插件报告的支持规则类型列表,在访问QoS规则资源时不是强制的。这主要是因为,如果某一个位于gate的QoS驱动不能支持我们正在测试的规则,我们将无法创建规则。
QoS的设计定义了以下两个概念资源,以应用QoS规则到: a port, a network 或者 a floating IP:
每个QoS策略包含空或多条QoS规则。策略之后应用到网络或端口,使得策略的所有规则应用与相应的Neutron资源。
当应用与一个网络关联时,策略规则可应用/不应用到Neutron内部的端口(比如,router, dhcp, load balancer, 等)。基于QosRule的对象一个默认的可被覆盖的方法:should_apply_to_port。将来我们打算在“QoSNetworkPolicyBinding”或者“QosRule”中增加一个标记,以强制此类型的应用(例如,当自动限制在外部网络上的router设备的所有ingress流量)。
每个project可最多一个默认QoS策略,但这不是强制的。如果定义了默认的QoS策略,此project内创建的所有新网络将被赋予此策略,前提是如果在创建流程中没有明确的关联其它的QoS策略。如果删除默认的QoS策略,不会对现存的网络造成任何改变。
从数据库的角度看,在schema中定义了以下的对象:
所有的数据库models定义在:
对于QoS, 实现了以下的 Neutron 对象:
这些定义在:
对于QosPolicy Neutron 对象, 实现了以下的公共方法:
除了属于QoS策略的数据库对象本身的字段外,表示策略的规则列表的对象也被添加了其它字段。要获得特定策略的所有规则列表,对象的消费者仅需通过以下的属性:
实现方式允许添加新的规则列表字段,而不修改或者少量修改策略对象本身。实现方式为内省现存可用的规则对象定义和在策略类中自动定义这些字段。
注意规则的加载不是lazy方式,这意味着在策略获取时,规则也都由数据库中获取出来。
对于QosRule对象,采用了可扩展的方式以允许容易的添加新规则类型的对象。为满足这一点,对所有类型通用的字段放入了一个基类中QoSRule,特定类型的规则继承了基类,只需实现额外的字段和一些其它小的变更。
注意QosRule基类没有注册到oslo.versionedobjects的注册表中,原因是不希望实例化“通用”的规则(建议,基础规则类标记为ABC)。
QoS对象依赖于一些原语数据库API方法,添加如下:
RPC通信在参考后端驱动的详细实现在OpenStack官网的<rpc_callbacks.html>中进行了讨论。
更新流程如下:
如果绑定到agent的port关联到QoS策略,ML2插件依赖ML2 QoS扩展驱动检测到此改变,通知agent相关port变更。agent调用get_device_details()处理通知,获取新的包含新qos_policy_id的port dict。每个设备的详细dict被传递到L2 agent扩展管理器,其传递到每个使能的扩展,包括QoS。QoS扩展看到port的一个新未知QoS策略,它使用ResourcesPullRpcApi从服务器获取策略的当前状态(及所有包含的规则)。之后,QoS扩展调用对应于agent的QoS驱动,以应用策略。
对于浮动IP,实现了L3 agent扩展fip_qos。此扩展接收并处理router更新。对于每个更新,遍历关联与router的每个浮动IP,如果浮动IP具有关联的QoS策略,扩展使用ResourcesPullRpcApi从Neutron服务器获取策略详细信息。如果策略包含“bandwidth_limit”规则,扩展通过直接调用l3_tc_lib应用这些规则到合适的router设备。
对于现存QoS策略的更新(包括任意策略或其规则变化),服务器通过ResourcesPushRpcApi接口推送新策略对象状态。此接口扇出串行化(dehydrated)对象到每个监听QoS策略更新的agent。如果agent之前见到过此策略(关联到维护的port或浮动IP之一),应用更新到port/浮动IP。否则,agent悄悄的忽略更新。
实现了QoS功能的参考agent,可参见OpenStack官方网站的: l2_agent_extensions.html.
neutron.agent.l2.extensions.qos
定义QoS L2 agent扩展。它接收handle_port 和 delete_port实现,传递到QoS agnet后端驱动(参见以下介绍)。此文件也定义了QosAgentDriver接口。注意:每个后端实现其自身的驱动。驱动处理与底层网络技术的低级别交互,QoS扩展处理对所有agents通用的操作。
对于 L3 agent:
neutron.agent.l3.extensions.fip_qos
定义QoS L3 agent扩展。它实现L3 agent一侧的浮动IP限速。对于所有的routers,如果浮动IP具有QoS“bandwidth_limit”规则,相应的TC过滤器将添加到对于的router设备,此依赖于router的类型。
当前,Open vSwitch,SR-IOV和Linux网桥 ML2驱动支持QoS。
每个agent后端定义一个QoS驱动,其实现QosAgentDriver接口:
Neutron后端,支持规则,流量方向(VM视角)列表:
+----------------------+----------------+----------------+----------------+
| Rule \ Backend | Open vSwitch | SR-IOV | Linux Bridge |
+----------------------+----------------+----------------+----------------+
| Bandwidth Limit | Egress/Ingress | Egress (1) | Egress/Ingress |
+----------------------+----------------+----------------+----------------+
| Minimum Bandwidth | - | Egress | - |
+----------------------+----------------+----------------+----------------+
| DSCP Marking | Egress | - | Egress |
+----------------------+----------------+----------------+----------------+
(1) 由于ip工具不支持最大burst参数,将其跳过.
Open vSwitch实现依赖于新的ovs_lib OVSBridge函数::
通过设置port接口的ingress_policing_rate 和 ingress_policing_burst参数可有效的配置端口的egress带宽限制.
此方式不如linux-htb, Queues 和 OvS QoS profiles灵活,将在以后介绍,但要与openflow联合使用。
通过为port设置Queue和OVS QoS profile,linux-htb类型可有效的配置端口的ingress带宽限制。
Open vSwitch DSCP标记实现依赖于最近添加的ovs_agent_extension_api OVSAgentExtensionAPI去请求访问integration网桥功能:
DSCP标记实际上由openflow规则配置到port上。
SR-IOV带宽限制和最小带宽实现依赖于新的pci_lib函数:
正如函数名称所示,此限制应用与Virtual Function(VF)。此函数由一个参数"rate_type",其值可设置为"rate" 或 “min_tx_rate”,分别用于带宽限制和最小带宽控制。
ip link接口对于带宽限制有以下的局限:它使用Mbps作为带宽测量,而不是kbps,不支持浮点数。所以如果要设置限制到小于1000kbps时,它只能设置为1Mbps。如果设置值不能被均分为1000kbps,最终的限制值射入到最近的整数Mbps。
Linux网桥实现依赖于新的tc_lib函数.
对于egress带宽限制规则:
通过在tc的ingress queueing discipline(qdisc)设置流量策略,可在tap端口配置egress带宽限制。关于ingress qdisc的详细信息请参考lartc how-to. 使用ingress qdisc配置egress带宽的原因是,tc工作于由网桥内部视角的流量。所以,通过tap接口到达网桥的流量,实际上就是从Nneutron端口发出的流量。
此实现与Open vSwitch通过ingress_policing_rate 和 ingress_policing_burst配置端口一致。
对于ingress带宽限制规则:
ingress带宽限制通过设置简单的tc-tbf queueing discipline(qdisc)配置到tap端口上。它需要宿主机内核配置的HZ参数。此值是计算设置到tc的最小burst值所需要的。关于如何计算可参见:http://unix.stackexchange.com/a/100797. 此解决方案类似于 Open vSwitch 的实现.
Linux bridge DSCP标记实现依赖于linuxbridge_extension_api去请求访问IptablesManager类,管理iptables中的“mangle”表。
QoS框架非常灵活以支持任何的第三方厂商。要集成一个第三方的驱动(仅需要实现QoS create/update/delete API调用),需要实现“neutron.services.qos.drivers.base”类,并在核心插件或mechanism驱动加载时注册此驱动,参见以下示例的注册方法:
neutron.services.qos.drivers.openvswitch.driver
注:
厂商必须实现所有的功能,Neutron QoS框架仅作为一个接口传递接收到的QoS API请求,及在数据库中保存API操作。L3 agent “fip_qos” 扩展没有驱动实现,它直接为所有的router类型使用“l3_tc_lib”。
要使能服务,遵循以下的步骤:
服务器侧:
agent侧 (OVS):
L3 agent侧:
所有添加或扩展的代码都应经过合理的测试。
验证Neutron对象的基础测试类,当引入新对象类型时,以一种允许代码重用的方式实现。
由两个测试类用于此目的:
每个在以上类基础上实现的新对象,被期望继承现有测试用例,或者进行重新实现,前提是这些对象的实现是合理的。特殊的测试类可以很好的按照需要扩展测试用例集(例如,如果你在所有Neutron对象的基础通用语法之上,为你的对象实现添加额外的方法,你需要为这些方法定义新的测试用例)。
对ovs_lib设置端口带宽限制新增了以下测试内容:
为使用tc_lib进行端口带宽限制新增了以下功能测试:
test_l3_tc_lib的新功能测试,在router浮动IP地址相关设备设置TC过滤器的内容在以下类中:
L3 agent 浮动IP限速的新功能测试如下:
ports, networks, policies, 和 rules的基础CRUD操作的API测试添加在以下类: