Neutron Quota管理与执行

云计算 专栏收录该内容
40 篇文章 0 订阅

Neutron API开放的大部分资源都受到配额限制。Neutron API开放了管理此类配额的扩展。配额限制在API层执行,在请求分派到插件之前。

配额限制的默认值定义在文件neutron.conf。管理员可以project为单位改写这些默认值。限制值保存在Neutron数据库中;如果没有找到给定资源与project的限制值,使用此资源的默认值。基于设置的配额管理,即每个project在配置文件中得到相同的配额限制值,已经在Liberty发布版中废弃。

请注意,Neutron不支持基于用户的配额限制和层次化多租户配额管理(事实上Neutron根本不支持层次化多租户)。并且,当前的配额限制不在监听与AMQP总线的RPC接口上执行。

Plugin 和 ML2驱动不支持对其管理的资源执行配额。尽管如此,subnet_allocation扩展是个例外,将在以下讨论。

这里讨论的配额管理和执行机制应用于每个注册于配额引擎的资源,不管此资源时属于核心Neutron API或者是其扩展。

概述

Neutron配额系统包含以下两个主要组件:

  • The Quota API extensions.
  • The Quota Engine.

两个组件依赖于一个配额驱动。Neutron代码当前定义了两个配额驱动:

  • neutron.db.quota.driver.DbQuotaDriver
  • neutron.quota.ConfDriver

尽管后者已被废弃.

配额API扩展处理配额管理,额配额引擎组件处理配额执行。API扩展像其他扩展一样加载。据此原因,插件必须通过在supported_extension_aliases属性中包含"quotas"来显示的支持它。

在配额API中,使用简单的CRUD操作管理project配额。请注意当前删除project配额的操作是重置project的配额限制到默认配置。API扩展不通过标识服务验证project标识符。

另外,Quota Detail API扩展通过允许用户(典型的为admins)获取每个project的quotas的详细信息补充了Quota API扩展。Quota详情包括project资源(networks, ports, 等)的used/limit/reserved的计数。

Quota引擎负责执行quota限制。在向插件发送请求之前,RESTful API控制器尝试从quota引擎获得客户端所请求资源的预定。如果预定成功,它继续分配操作到插件上。

为了预定能够成功,请求资源的总量,加上预留资源的总量,加上已经保存在数据库中的资源总量,不应超过project的quota限制值。

最终,quota管理和执行依赖于"quota driver",其任务基本上是执行数据库操作。

Quota 管理

quota管理组件相当简单。

尽管如此,不像大多数的Neutron扩展,其使用自身的控制器类。此类不执行POST操作。List, get, update, 和 delete操作通过常用的index, show, update 和 delete方法实现。这些方法简单的调用quota驱动实现获取project的quotas或更新它们的操作。

控制器生命周期内仅会调用一次_update_attributes方法。此方法动态更新Neutron资源属性映射,所以属性添加到quota引擎管理的每个资源。请求认证在控制器内执行,仅“admin”用户可修改project的quota。由于Neutron的策略引擎没有使用,不能使用policy.json配置哪些用户可管理quota。

处理quota管理的驱动操作有:

  • delete_tenant_quota, 为指定的project标识删除所有的“quotas”表项;
  • update_quota_limit, 为指定的project标识和资源名称增加或更新“quotas”表项;
  • _get_quotas, 获取指定的project标识的资源集的限值
  • _get_all_quotas, 类似于以上的_get_quotas, 但是针对所有的projects.

资源使用信息

Neutron有两种方式追踪资源使用信息:

  • CountableResource, 每次执行quotas限值时计算一下资源的使用情况,方法是计算资源表中行的个数以及为此资源做的预留.
  • TrackedResource, 不依赖于特定表跟踪使用数据,仅当表中数据与实际使用和预留资源不同步时,进行显式的计算.

CountableResource 与 TrackedResource 的另一个区别是前者触发插件方法来计算资源。所以CountableResource应用于不能使用Neutron数据库的插件。Neutron的quota引擎实际使用的类取决于quota配置部分的track_quota_usage变量。如果其为真,创建TrackedResource实例,否则quota引擎使用CountableResource实例。

资源的创建由neutron.quota.resource模块的create_resource_instance工厂方法实现。

从性能的角度考虑,使用表跟踪资源使用情况有一定的优势,虽然不是特别显著。事实上,为显式计算对象而执行查询所需的时间随着表中记录的增加而增加。另一方面,使用TrackedResource值仅需获取单个记录,缺点是必须在操作完成之后,执行一个UPDATE语句。

尽管如此,CountableResource实例并不是简单的对资源相关的表执行SELECT查询,而是触发一个插件方法,其可能执行多个语句,在某些情况下甚至要在返回之前要与后端交互。

资源使用跟踪,对于和资源预留相结合时的操作正确变得非常重要,以下将详细讨论。

跟踪quota使用情况不是简单的在每次资源创建和删除时更新计数器。实际上Neutron中的quota-limited资源可以多种方式创建。RESTful API请求时创建资源的最常用方式,资源可由AMQP总线上的RPC处理函数创建,类似于创建DHCP ports的函数,或者由插件操作,类似于创建router ports的方法。

为此目的,TrackedResource实例初始化时带有其跟踪的资源的model类的引用。对象初始化过程中,为此类安装SqlAlchemy事件处理函数。在记录插入或删除时,执行此事件处理函数。当此操作结束之后,此资源的计数将被标记为“dirty”,所以下次请求资源计数时,将从数据库同步资源使用计数。尽管此方案有缺陷(列在,'exceptions and caveats’一节),仍比以下的方案更可靠:

  • 在每次操作完成后,使用“正确”的数值更新使用计数器.
  • 使用定期任务同步quota使用数据与Neutron DB中的实际数据.

最后,不管是使用 CountableResource 或者 TrackedResource,quota引擎总是调用其count()方法获取资源使用情况。所以,从Quota引擎的角度看,CountableResource 和 TrackedResource没有任何差别。

Quota 执行

在向插件分配请求之前,Neutron ‘base’ 控制器尝试为请求的资源做预留。通过调用neutron.quota.QuotaEngine中的make_reservation方法实现。

预留流程十分简单:

  • 获取资源当前使用情况。这可通过针对每个请求的资源调用count方法,之后再获取预留资源量实现。
  • 通过调用_get_tenant_quotas方法,获取请求资源的当前quota限值。
  • 获取所选资源的到期预留。将从资源使用量中减去此值,与将请求的非到期和预留资源相加比较,这样做可请求较少的DB操作。
  • 对每一种资源计算其头部空间,验证请求的资源量小于头部空间(headroom).
  • 如果对于所有资源以上条件都成立,预留保存到DB中,否则,触发OverQuotaLimit异常。

quota引擎可为多个资源做预留。尽管如此,值得注意的是,由于当前的Neutron API层的结构,还没有任何实际的用例执行多个资源的预留。由于此原因,避免重复请求每个资源的性能优化不属于当前的实现。

为了保证正确的操作,创建预留的事务中需要获得一个row-level的锁。当读取使用数据时获取此锁。在write-set鉴定失败的情况下(可发送在诸如MySQL galera类的active/active集群场景中),如果触发了DBDeadLock异常,neutron.db.api.retry_db_errors修饰符将重试此事务。

当非锁定方式可行时,结果是,由于非锁定算法增加了冲突的几率,处理DBDeadLock异常的成本仍然低于检查冲突时的重试操作的成本。此方向的研究是针对IP分配操作进行的,但同样的原则也适用于这里。然而,对于将来的quota执行来说,移除DB-level锁是必须的事情。

提交和取消预留量与删除其本身一样简单。提交预留量后,已提交的资源现在存储在数据库中,因此预留量本身应删除。Neutron quota引擎在取消预留量时简单地删除数据库记录(即未能完成的请求),并且在提交预留时将quota使用信息标记为过期(即请求正确完成)。通过分别调用neutron.quota.QuotaEngine中的commit_reservation和cancel_reservation方法来提交或取消资源预留。

预留不是永久性的。永久预留最终会耗尽project的quotas,因为当API客户端在操作过程中崩溃时,它们将永远不会被删除。预留过期时间当前设置为120秒,并且不可配置,至少目前还不可配置。计算资源使用率时不计算过期的预留。创建预留时,如果发现任何过期的预留,则将从数据库中删除该project和资源的所有过期预留,从而避免累积过期的预留。

为插件设置资源跟踪

默认情况下,插件不使用资源跟踪。让插件显式地声明应该跟踪哪些资源是一个精确的设计选择,目的是尽可能地限制在现有插件中引入错误的可能性。

因此,插件必须声明它要跟踪的资源。这可以通过使用neutron.quota.resource_registry模块中的tracked_resources修饰符来实现。修饰符最好应用在插件的__init__方法。

修饰符接受关键字参数列表输入。参数的名称必须是资源名称,参数的值必须是一个DB model类。例如:

@resource_registry.tracked_resources(network=models_v2.Network,
port=models_v2.Port,
subnet=models_v2.Subnet,
subnetpool=models_v2.SubnetPool)

将确保跟踪network, port, subnet和subnetpool资源。从理论上讲,可以多次使用这个修饰符,而不是仅用于__init__方法。但是,这最终会导致代码的可读性和可维护性问题,因此开发人员强烈建议将此修饰符专门应用于插件的__init__方法(或插件在初始化期间仅调用一次的任何其他方法)。

RPC接口和RESTful控制器的实现的注意事项

不幸的是,Neutron没有一个由插件调度操作之前调用的层,这个插件可以由RESTful和基于AMQP API的RPC中使用。特别是,RPC处理程序直接调用插件,而不执行任何请求授权或quota强制。

因此,RPC处理程序必须显式地指明他们是否要调用插件来创建或删除任何类型的资源。这是通过一种简单的方法实现的,方法是确保在RPC处理程序执行终止后,修改后的资源被标记为过期(dirty)。为此,开发人员可以使用neutron.quota.resource_registry模块中可用的mark_resources_dirty修饰符。

此修饰符将扫描已注册资源的整个列表,并保存插件操作期间资源项被创建或销毁的资源的使用情况跟踪器的(dirty)状态到数据库中。

异常和警告

请注意quota执行引擎的以下限制:

  • Subnet Pools(尤其是shared pools)中的Subnet分配也需要进行quota限制检查。但是,这种检查不是由quota引擎执行的,而是通过neutron.ipam.subnetalloc模块中实现的机制执行的。这是因为Quota引擎无法满足Subnet分配quota的要求。

  • Quota引擎还提供了一个limit_check例程,该例程强制配额检查而不创建预留。这种执行quota的方式非常不可靠,被预留机制所取代。它还没有被删除,以确保代码树外插件和扩展对其的使用不被破坏。

  • SqlAlchemy事件可能不是检测资源使用变化的最可靠方法。由于事件机制监视数据模型类,因此正确地执行quota至关重要,即始终使用对象关系映射创建和删除资源。例如,使用query.delete调用删除资源不会触发事件。由于Neutron缺乏持久的API对象,因此应将SQLAlchemy事件视为一种临时措施。

  • 由于CountableResource实例不跟踪使用数据,因此在进行预留时,不会获取write-intent锁。因此,CountableResource类型的quota引擎不是并发安全的。

  • 用于指定哪些资源启用使用率跟踪的机制依赖于这样一个事实:在quota-limited资源注册之前加载插件。因此,在启用资源跟踪时,无法验证资源是否实际存在。开发人员应特别注意确保指定正确的资源名称。

  • 代码假定使用情况跟踪程序是可信的事实来源:如果它们报告使用计数器,并且未设置dirty位,则该计数器是正确的。如果它是dirty的,那么计数器肯定是不同步的。这并不是非常可靠,因为在切换use_tracked_resources配置变量时,重新启动可能会出现问题,因为陈旧的计数器可能会被信任以进行预留。此外,如果服务器在API操作完成后,但在提交预留之前崩溃,则可能会发生相同的情况,因为实际资源使用情况已更改,但相应的使用率跟踪程序未标记为dirty。

参考

[#] Subnet allocation extension: http://git.openstack.org/cgit/openstack/neutron/tree/neutron/extensions/subnetallocation.py
[#] DB Quota driver class: http://git.openstack.org/cgit/openstack/neutron/tree/neutron/db/quota_db.py#n33
[#] Quota API extension controller: http://git.openstack.org/cgit/openstack/neutron/tree/neutron/extensions/quotasv2.py#n40
[#] Neutron resource attribute map: http://git.openstack.org/cgit/openstack/neutron/tree/neutron/api/v2/attributes.py#n639
[#] Base controller class: http://git.openstack.org/cgit/openstack/neutron/tree/neutron/api/v2/base.py#n50
[#] http://lists.openstack.org/pipermail/openstack-dev/2015-February/057534.html

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值