迁移或撤离时检查目标主机¶
https://blueprints.launchpad.net/nova/+spec/check-destination-on-migrations
提供一种方法,以确保所有操作的一致性资源分配,即使提供了目标主机。
问题描述¶
实时迁移和撤离允许指定目标主机或不指定。 后一种选项完全绕过调度器,直接调用目标 Compute RPC API。
不幸的是,在迁移虚拟机时,有时会破坏调度器规则,从而可能破坏未来的启动请求,因为在迁移/撤离时未强制执行某些约束(例如分配比例)。
我们应该修改该逻辑,以便在请求移动(即,实时迁移或撤离)时显式调用调度器(无论是否提供目标主机),以便调度器通过所有启用的过滤器验证目标主机,如果成功,则从其内部 HostState 消耗实例使用量。
也就是说,我们也理解,在某些情况下,操作员希望手动移动实例,而不是调用调度器,即使操作员知道他明确破坏了调度器规则(例如,过滤器未通过、违反了亲和性策略,或者实例使用了已分配的 pCPU,在 CPU 引脚的上下文中)。
用例¶
一些正常的用例(验证目标主机)可能是
作为操作员,我想确保在实时迁移特定实例时提供的目标主机是正确的,并且不会因为我对目标主机容量的计算方式与调度器考虑内存分配比例的方式之间的差异而破坏我的内部云(请参阅下面的“参考”部分)。
作为操作员,我想确保将实例实时迁移到特定目标不会因为我遗漏的某些亲和性而影响在该目标主机上运行的现有实例。
项目优先级¶
‘scheduler’优先级的一部分,已被Liberty接受。
提议的变更¶
此规范超越了 persist-request-spec 蓝图 [1],通过确保在每次调用 select_destinations() 之前,从当前要调度的实例读取 RequestSpec 对象,并确保在 select_destinations() 的结果之后,RequestSpec 对象将被持久化。
这样,我们将能够从创建 VM 的用户那里获取与相应实例相关的原始 RequestSpec,包括调度器提示。 鉴于此,我们建议修改 RequestSpec 对象以包含一个名为 requested_destination 的新字段,该字段将是一个 ComputeNode 对象(至少包含 host 和 hypervisor_hostname 字段),并将在 conductor 中为接受可选目标主机的每种方法(此处为 live-migrate 和 rebuild_instance)设置。
请注意,此新字段与迁移对象或 Instance.host 字段无关,因为它只是对等效调度器提示的引用,说明“我想去那里”(而不是作为可用区黑客传递的难看的 force_hosts 信息……)。
将由 conductor(在 live_migrate 和 evacuate 方法中)获取与实例相关的 RequestSpec,添加 requested_destination 字段,将相关的 Migration 对象设置为 scheduled,并调用调度器的 select_destinations 方法。 最后一步当然是存储更新后的 RequestSpec 对象。 如果调度器认为请求的目标不可接受,则 conductor 将 Migration 状态更改为 conflict。
其背后的想法是,调度器将在 FilterScheduler 的 _schedule() 方法中检查该字段,然后仅对该目标调用过滤器。
由于 RequestSpec 对象蓝图通过提供旧的 request_spec 和 filter_properties 到旧的 select_destinations API 方法来关注向后兼容性,因此我们将不会将新的 requested_destination 字段作为 request_spec 的键传递。
由于此 BP 还提供了一种让操作员绕过调度器的方法,我们将通过添加一个名为 force(接受 True 或 False,默认值为 False)的额外请求体参数来修改所有包含目标主机的迁移的 API,并且相应的 CLI 方法将公开该 force 选项。 如果客户端请求的微版本早于提供该字段的版本,则不会将其传递(既不为 True 也不为 False,而是该键不存在)给 conductor,因此 conductor 不会调用调度器 - 以保持现有行为(有关更多详细信息,请参阅下面的 REST API 部分)。
为了跟踪这些强制调用,我们建议将迁移已被强制执行这一事实记录为实例操作,以便操作员稍后如果需要可以重新安排实例。 为此,我们建议添加两个新的可能操作,称为 FORCED_MIGRATE(在实时迁移时)和 FORCED_REBUILD(在撤离时)。 这样,操作员可以通过调用每个实例的 /os-instance-actions API 资源来获取具有 FORCED_MIGRATE 或 FORCED_REBUILD 的所有实例,并且我们还可以稍后添加一个新的蓝图(超出此规范范围)来获取具有特定操作设置为某个内容的实例列表(此处为 FORCED_something)。
备选方案¶
我们可以只提供一种调用调度器以获取答案,以确定目标主机是否有效,但这不会消耗实例使用量,这从我们的角度来看是现有设计的关键问题。
数据模型影响¶
无。
REST API 影响¶
拟议的更改只是更新了 os-migrateLive 和 evacuate 操作的 POST 请求体,以包含可选的 force 布尔字段,如果请求具有最低版本,则默认为 False。
根据 host 和 force 字段是否设置或为空,操作和返回代码为
如果在请求体中提供了 host 参数,则现在将要求调度器验证请求的目标计算节点是否实际上能够容纳该请求,包括遵守所有先前使用的调度器提示。 如果调度器确定请求无法由请求的目标主机节点容纳,则相关的 Migration 对象会将
status字段更改为conflict。如果请求体中提供了主机参数,则请求体中还可以提供一个新的 –force 参数。如果存在,调度器将不被咨询以确定目标计算节点是否可以容纳,并且不会向用户返回 409 Conflict 错误。
如果请求体中提供了 –force 参数,但 host 参数为空(对于 live-migrate)或未提供(对于 evacuate),则将向用户提供 HTTP 400 Bad Request。
当然,由于这是一个新的请求体属性,它将获得一个新的 API 微版本,这意味着如果未提供该属性,则 conductor 不会调用调度器(以保持现有行为,即设置主机绕过调度器)。
os-migrateLive的 body 数据 JSON schema 定义
migrate_live = {
'type': 'object',
'properties': {
'os-migrateLive': {
'type': 'object',
'properties': {
'block_migration': parameter_types.boolean,
'disk_over_commit': parameter_types.boolean,
'host': host,
'force': parameter_types.boolean
},
'required': ['block_migration', 'disk_over_commit', 'host'],
'additionalProperties': False,
},
},
'required': ['os-migrateLive'],
'additionalProperties': False,
}
evacuate的 body 数据 JSON schema 定义
evacuate = {
'type': 'object',
'properties': {
'evacuate': {
'type': 'object',
'properties': {
'host': parameter_types.hostname,
'force': parameter_types.boolean,
'onSharedStorage': parameter_types.boolean,
'adminPass': parameter_types.admin_password,
},
'required': ['onSharedStorage'],
'additionalProperties': False,
},
},
'required': ['evacuate'],
'additionalProperties': False,
}
我们不应该进行任何策略更改,因为我们没有更改操作本身,而只是提供了一个新选项。
安全影响¶
无。
通知影响¶
无。
其他最终用户影响¶
Python-novaclient 将为以下方法接受一个 force 选项
撤离
实时迁移
性能影响¶
默认情况下,将进行一个新的 RPC 调用,在迁移或撤离时,但它实际上不应该影响性能,因为它对于一般的迁移来说是正常的行为。 为了使该 RPC 与 API 查询异步,我们不会在原始请求中提供检查结果,而是修改 Migration 对象状态(请参阅上面的 REST API 影响部分)。
其他部署者影响¶
无。
开发人员影响¶
无。
实现¶
负责人¶
- 主要负责人
sylvain-bauza
工作项¶
在调用
select_destinations()的所有 conductor 方法之前,读取任何现有的 RequestSpec使用
requested_destination字段修改 RequestSpec 对象修改 conductor 方法,用于撤离和 live_migrate,以填充
requested_destination,调用scheduler_client.select_destinations(),并在调用之后持久化修改后的 RequestSpec 对象。修改 FilterScheduler._schedule() 以检查
requested_destination,如果存在,则仅对该主机调用过滤器。扩展 API(并增加新版本)以在上述两个 API 资源中添加
force属性,并具有适当的行为。如果设置了该标志,则绕过调度器并记录
FORCED_REBUILD或FORCED_MIGRATE操作。将一个新的
force选项添加到 python-novaclient 并将其暴露在 CLI 中,用于evacuate和live-migrate命令。
依赖项¶
如提案中上述所述,由于调度器提示是请求的一部分,尚未持久化,因此我们需要依赖于在调用 select_destinations() 之前持久化 RequestSpec 对象 [1],以便将来的迁移可以读取该 RequestSpec 并再次提供它。
测试¶
需要更新 API 示例,并使用单元测试来涵盖该行为。 树内功能测试将被修改以涵盖该选项。
文档影响¶
如上所述,API 示例将被修改以包含新的属性。
参考资料¶
[1] https://specs.openstack.org/openstack/nova-specs/specs/liberty/approved/persist-request-spec.html
很多 bug 都提到了我们上面描述的注意事项。以下是我识别出的,并在 spec 实现落地后将会关闭的 bug:
https://bugs.launchpad.net/nova/+bug/1451831 指定目标节点与 nova live_migration 不会考虑 overcommit 设置 (ram_allocation_ratio)
https://bugs.launchpad.net/nova/+bug/1214943 实时迁移应使用与实例启动相同的内存超额订阅逻辑
https://bugs.launchpad.net/nova/+bug/1452568 nova 允许从一个可用区实时迁移实例到另一个可用区