亲和性和反亲和性调度器过滤器

https://blueprints.launchpad.net/manila/+spec/affinity-antiaffinity-filter

Cinder 功能的副本 https://blueprints.launchpad.net/cinder/+spec/affinity-antiaffinity-filter

为 Manila 添加调度器过滤器,允许调度器根据现有共享和新共享(正在调度的共享)之间的亲和关系做出放置决策。这里的亲和关系是指共享的位置(共享的“宿主”)。

问题描述

Manila 通过使用共享类型,很好地隐藏了存储后端细节,但有些情况下,构建在共享之上的应用程序的用户希望能够“选择”共享创建的位置。Manila 如何在不损害我们一直保持的简洁性的前提下提供这种能力?亲和/反亲和性是我们可以在不暴露后端细节的情况下提供的灵活性之一。

这里的亲和/反亲和性是指在位置方面两组共享之间的关系。为了限制范围,我们描述一个共享只有在它们位于相同的共享后端时才与另一个共享具有亲和性;相反,两组共享之间的“反亲和性”关系仅仅意味着它们位于不同的 Manila 后端(宿主)上。

此亲和/反亲和性过滤器根据最终用户指定的提示过滤 Manila 后端。该提示表达了新共享与现有共享之间的亲和或反亲和关系。这允许最终用户提供诸如“请将此共享放置在与 share-XYZ 位于不同位置的地方”之类的提示。

用例

DB 团队在单个共享上构建 MySQL 主服务器,他们更希望将用于从 DB 的新共享放置在与主 DB 所在的不同的后端,以提高可用性。

提议的变更

为 Manila 添加两个新的过滤器 - AffinityFilter 和 AntiAffinityFilter。这两个过滤器将查看最终用户提供的调度器提示,并通过检查旧共享和新共享的“宿主”来过滤后端,以查看后端是否满足要求(位于与现有共享相同的后端,或不位于与现有共享相同的后端)。位于相同宿主上的不同池中的共享仍然被视为基于相同的宿主。

调度器提示 (same_host, different_host) 必须在数据库中创建新的共享记录后立即保存为共享元数据。那些提示中引用的共享也将收到元数据更新,例如

  1. 存在三个共享,其 UUID 为:UUID1、UUID2、UUID3。

  2. 用户使用 UUID4 预置一个新共享,并请求它与 UUID1、UUID2 和 UUID3 共享具有不同的宿主。

  3. 共享 UUID4 将此提示与所有其他三个共享 UUID 一起存储。

  4. 每个三个共享的元数据也会更新,以反映它们与具有 UUID4 的新共享具有反亲和性。

相应的共享元数据也会在共享删除时以类似的方式自动更新。

此额外元数据应标记为仅“admin_modifiable”,以防止非管理员用户意外删除或修改这些值。

需要提示信息以允许用户了解共享是如何调度的,并且能够在共享在其生命周期内迁移时尊重这些提示。

备选方案

曾有一种提议允许管理员用户直接指定新共享的后端。它并没有真正提供与亲和性过滤器类似的功能,因为它仅限于管理员,并且本身也存在一些缺点(例如安全问题)。

亲和性也可以与共享组一起使用。但是,对于所提出的用例,共享组存在一些限制

1) 亲和/反亲和性仅需要在资源预置时需要,而不是在其生命周期的任何其他时间点。今天在共享组中创建的共享在其整个生命周期内都与共享组绑定在一起。 2) 共享组当前的功能限制包括无法在共享组内迁移或复制共享。 3) 虽然可以使用共享组实现亲和性,但无法实现反亲和性。

对于这两个过滤器,可以采用软 OR 语义而不是硬 AND。这意味着,如果至少满足一个条件,共享创建应该成功。缺点是由于共享创建是异步的,因此无法清楚地向用户呈现此信息。(当用户“发射并忘记”一个带有提示的创建请求时,其中并非所有条件都满足)。

将 scheduler_hints 存储在共享元数据中的替代方法是对 Share DB 模型进行扩展,以在那里保存提示。这种方法会导致更多的修改。

数据模型影响

无。提示将作为额外的共享元数据保存。

REST API 影响

将“scheduler_hints”参数添加到共享创建中,例如

`{
    "share": {
        "scheduler_hints": {
            "different_host": [
                "share_uuid_1",
                "share_uuid_2"
            ],
            "same_host": ["share_uuid_3"]
        }
    }
}`

在此示例中,共享应被调度到与“share_uuid_3”位于相同宿主的位置,但前提是“share_uuid_1”和“share_uuid_2”都不位于该宿主上。

将验证给定的所有 uuid 是否存在,如果至少一个共享不存在或 uuid 格式错误,则共享创建将失败。

这两个过滤器的语义都是硬 AND,这意味着除非满足所有放置条件,否则共享将无法创建。

如果所需的调度组合不可行(例如,与位于两个不同宿主上的两个共享具有亲和性),则共享创建应失败。反亲和性过滤器也适用 - 如果只有两个宿主,并且每个宿主都有一个带有在“different_host”提示中给定的 uuid 的共享,则创建将失败。

如果共享在宿主之间迁移,也应尊重调度器提示,但是应该有一种手动覆盖提示并强制迁移的选项,即使在迁移后亲和/反亲和性条件不满足(例如,添加“force: true”选项)。

API 的微版本递增。

安全影响

虽然此更改涉及使用或解析用户提供的 - 调度器提示。这并没有使 Manila 比现在更危险。

通知影响

其他最终用户影响

性能影响

新过滤器将为每个请求查询 DB 一次,它只会为系统增加略微的延迟,并且延迟与系统的大小无关。

共享元数据更新可能需要更多时间,尤其是在提示中指定了许多共享时。但是,共享创建或删除是一个异步过程,因此最终用户不应注意到此影响。

其他部署者影响

开发人员影响

实现

负责人

主要负责人

Dmitry Galkin (galkindmitrii in Gerrit) Kiran Pawar (kpdev in Gerrit)

工作项

  1. 过滤器实现

  2. 添加调度器提示参数

  3. 为 python-manilaclient 添加提示参数

  4. 在 manila-ui 中添加提示支持

依赖项

测试

针对 AffinityFilter(相同宿主)进行测试
  • 创建共享 A;

  • 创建另一个共享 B,其 uuid 为 A,提示为“same_host”;

  • 检查 B 是否创建在与 A 相同的后端;

针对 AntiAffinityFilter(不同宿主)进行测试
  • 创建共享 A;

  • 创建另一个共享 C,其 uuid 为 A,提示为“different_host”;

  • 检查 C 是否创建在与 A 不同的后端;

文档影响

需要记录新过滤器的用法。

参考资料

Nova 自 Diablo 起一直提供名为 SameHostFilter 和 DifferentHostFilter 的类似功能。

https://github.com/openstack/nova/blob/master/nova/scheduler/filters/affinity_filter.py

Cinder 自 Juno 起一直提供名为 AffinityFilter 和 AntiAffinityFilter 的类似功能。

https://specs.openstack.org/openstack/cinder-specs/specs/juno/affinity-antiaffinity-filter.html