允许在排队状态下中止实时迁移¶
https://blueprints.launchpad.net/nova/+spec/abort-live-migration-in-queued-status
此蓝图增加了支持,允许在 queued(排队)状态下中止实时迁移。
问题描述¶
中止实时迁移的功能是在 microversion 2.24 中添加的 [1],目前仅允许中止处于 running(运行中)状态的迁移。
有一个配置选项 max_concurrent_live_migrations,可用于控制并发实时迁移的最大数量,默认值为 1。当实时迁移请求的数量可能大于最大并发实时迁移配置时,将会有迁移在队列中等待。这些迁移可能会根据队列长度和处理速度,在 queued(排队)状态下停留很长时间。
管理员可能希望由于时间消耗等原因而中止队列中的迁移。在状态变为 running(运行中)之前让管理员等待是不合理的。
用例¶
由于迁移队列长度和处理速度,迁移可能会在 queued(排队)状态下长时间停滞。管理员可能希望由于时间消耗等原因而中止队列中的迁移。
提议的变更¶
整个更改将分为两个步骤
步骤 1 - 修复缺少队列的问题¶
在当前实现中,在计算节点上序列化实时迁移的代码使用 Python semaphore(信号量),信号量的值设置为 CONF.max_concurrent_live_migrations,每个传入的迁移将尝试获取此信号量,如果获取成功,信号量的值将减少 1,迁移的状态将变为 queued(排队)以外的状态。当值减少到 0 时,新的传入迁移将被阻止(迁移状态将为 queued(排队)),直到一些先前的迁移完成(成功、失败或中止)并释放信号量。
根据上述实现,由于实际上没有队列,因此无法中止处于 queued(排队)状态的迁移,因此我们无法控制被信号量阻止的迁移。
此规范将提出一个可以实现上述目标的设计
使用来自
concurrent.futureslib 的ThreadPoolExecutor(线程池执行器)代替当前eventlet.spawn_n()+ PythonSemaphore(信号量)实现。线程池的大小将限制为CONF.max_concurrent_live_migrations。当实时迁移请求进来时,我们将_do_live_migration调用提交到池中,它将返回一个Future对象,稍后我们将使用它。如果池已满,新的请求将被阻塞并保持在queued(排队)状态。将一个新的
_waiting_live_migration变量添加到计算节点的ComputeManager类中,这将是一个字典,并初始化为空字典。我们将记录
migration_uuid和上一步创建线程时Future对象之间的连接,我们将使用migration_uuid作为键,Future对象作为我们的字典中的值。如果线程成功获取执行器并进入
_do_live_migration()[2],则首先删除相应的键/值。 这样,我们将拥有类似队列的东西来存储 Futures,并使其能够通过migration_uuid获取它们。
步骤 2 - 允许在排队状态下中止实时迁移¶
在步骤 1 中提出的修改之后,我们将能够获取被 migration_uuid 阻塞的线程,然后我们可以中止它们
首先检查提供的
migration_uuid是否在_waiting_live_migration字典中,如果不在,则它将处于queued(排队)以外的状态,我们可以切换到今天的流程。如果提供的
migration_uuid在_waiting_live_migration字典中,则获取相应的Future对象并调用ThreadPoolExecutor的cancel()方法。如果取消调用成功,我们将对处于
queued(排队)状态的迁移执行回滚和清理。如果提供的Future对象当前正在执行,则取消调用将返回False,这意味着提供的线程不再被阻塞,因此我们可以切换到中止处于running(运行中)状态的迁移的流程,就像今天一样。向
DELETE /servers/{id}/migrations/{migration_id}API 添加一个 API microversion(微版本),以允许在queued(排队)状态下中止实时迁移。如果请求的 microversion 等于或高于新添加的 microversion,API 将在发出 RPC 调用之前检查instance.host'snova-compute 服务版本,并确保它足够新以支持新的支持,否则,API 仍将返回 400,就像今天一样。rpcapi 接口将被修改为接受迁移对象作为参数,以便我们可以根据目标计算版本和迁移状态来决定是否可以发送 rpc 调用,我们仍然会在 rpc 调用中发送 migration.id。
我们还将在计算管理器关闭时向池中添加清理。这部分将在实现过程中进行试验和错误,因为仍有一些细节需要弄清楚。这里的原则是,我们不希望阻塞服务的关闭,因此我们希望将这些迁移设置为
cancelled(已取消)状态,取消队列 Future,以便池关闭不会阻塞它。cleanup_host 期间的步骤是关闭池,这样我们就不会收到新的请求
对于任何排队的迁移,将迁移状态设置为
cancelled(已取消)使用 Future.cancel() 取消 future
步骤 2 和 3 可能是可以互换的,我们将在实现中找到最佳顺序。
备选方案¶
无
数据模型影响¶
无
REST API 影响¶
该提案将向 DELETE /servers/{id}/migrations/{migration_id} API 添加 API microversion(微版本),以允许在 queued(排队)状态下中止实时迁移。当使用大于新添加的 microversion 的 API microversion 的请求时,如果请求的实时迁移状态为 queued(排队)状态,响应将从 HTTP 400 BadRequest 更改为 HTTP 202 Accepted。
安全影响¶
无
通知影响¶
无
其他最终用户影响¶
Python-novaclient 将被修改以处理新的 microversion(微版本),以允许在 queued(排队)状态下中止实时迁移。
性能影响¶
无
其他部署者影响¶
无
开发人员影响¶
无
升级影响¶
如果运行实例的计算服务太旧,计算 API 仍然会返回 400,以尝试中止排队状态下的迁移。
实现¶
负责人¶
- 主要负责人
郑振宇
工作项¶
将计算管理器转换为使用线程/futures 排队迁移
创建一个新的 API microversion(微版本),以允许在
queued(排队)状态下中止实时迁移。修改 rpcapi 接口以接受迁移对象作为参数,以便我们可以根据目标计算版本和迁移状态来决定是否可以发送 rpc 调用。
修改 python-novaclient 以处理新的 microversion(微版本)。
依赖项¶
无
测试¶
需要新的 in-tree 功能和单元测试。
文档影响¶
需要有关新的 API microversion(微版本)和使用方法的文档。
参考资料¶
历史¶
发布名称 |
描述 |
|---|---|
Rocky |
提议 |