Detach and attach boot volumes

https://blueprints.launchpad.net/nova/+spec/detach-boot-volume

对于云用户来说,在实例未运行时能够分离和附加启动卷有时会很有用。目前 nova 根本不允许这样做,并且某些操作假定它不会发生。本规范建议允许在实例关机或置于搁置状态时分离和附加启动卷,并添加保障措施以确保其安全性。

问题描述

nova 代码中存在一个隐式假设,即实例始终附加一个 cinder 启动卷或一个临时启动磁盘。Nova 允许随时分离和附加 cinder 卷,但分离操作受到限制,以排除启动卷,从而保留上述假设[1]。

这种限制意味着除了删除实例并创建一个新实例之外,无法更改附加到实例的启动卷。但是,在实例未运行时更改启动卷附件是安全的,因此完全阻止这样做是不必要地限制。

存在需要实例未运行时分离启动卷的使用场景,因此我们建议放宽固有的假设,认为启动卷的附加可以在实例关机或置于搁置状态时更改。为了确保安全,我们可以防止在没有启动卷的情况下启动或取消搁置实例。

用例

第一个用例基于灾难恢复场景。在此场景中,连接到网络并使用位于站点 A 的持久卷的虚拟机系统正在执行在线应用程序。为了提供远程故障恢复能力,持久卷上的数据正在复制到远程站点 B 的卷。持久卷包括启动卷。

用例如下

作为云用户,我希望能够以最少的停机时间和确保远程站点能够接管的保证,将我的应用程序故障转移到远程站点。

此用例需要能够分离和附加启动卷,如以下从站点 A 故障转移到站点 B 中实现:

  1. 提前在站点 B 上构建虚拟基础设施,并检查新的基础设施是否完整、配置正确且可运行。然后搁置实例并分离磁盘。现在,当提供副本磁盘时,此基础设施已准备好接管。

  2. 设置从站点 A 到站点 B 的磁盘持续复制

  3. 故障转移过程:停止复制到站点 B;将副本磁盘附加到搁置的实例;取消搁置实例。

上述概述表明,站点 B 上的虚拟基础设施是提前构建的,并保持休眠状态。这些卷被分离并保持为站点 A 卷的副本,以便稍后交换回来。这满足了用例的要求

首先,基础设施的构建,包括将接收副本卷的实例,可以在执行故障转移之前完成并检查是否正确。这提供了更高程度的保证,即切换将成功。

其次,通过将虚拟基础设施构建从故障转移的关键路径中移除,故障转移导致的中断时间被最小化。

针对 nova 注册的一个 bug 描述了进一步的使用场景(参见 [2])。例如:

作为用户,我希望运行一个带有 windows 实例的 VM。我将不时地拍摄启动卷的快照。我可能想要还原到快照。如果我删除我的实例并从快照重新创建它,我将产生额外的许可费用,并且可能使我的许可失效。

提议的变更

此更改假定只有 cinder 卷才能以这种方式动态更改。我们不会支持分离临时磁盘。

基于卷的实例在置于搁置状态一段时间后[3]总是会被卸载,因此实例将不会位于主机上。因此,实现方式将是更改记录的块设备映射并使用 cinder 注册附加/分离操作。

将使用常规的分离卷 API 调用来分离启动卷。此调用的保护机制将被更改,以允许在实例关机或 shelved_offloaded 状态下分离。

当启动卷被分离时,我们将设置根块设备映射(boot_index=0)为 volume_id=None,这意味着它未附加到任何卷。

将为显示卷附件 API 添加一个新的微版本。我们将暴露 BDM boot_index 字段,用于使用新微版本或更高版本的 GET 请求,以便用户可以在分离卷时使用此信息。这个新的微版本也会影响卷附加 API。一个新的 is_root 参数将允许用于使用新微版本或更高版本的请求,指示用户正在尝试附加一个根卷。使用此参数的附件只有在实例关机或 shelved_offloaded 状态下才会被允许。

目前 Nova 也允许用户将卷附加/分离到 PAUSEDRESIZEDSOFT_DELETED 状态的服务器。正如邮件列表 [4] 中讨论的那样,允许在这些状态下附加/分离根卷的使用场景尚不清楚,并且可能会导致处理它们的复杂性,因此本规范将不支持在这些状态下附加/分离根卷。

对于分离/附加根卷实例,这里有一些具体的考虑事项:

  • 分离

    删除通过 BDM.attachment_id 字段引用的卷附件,并将 BDM.attachment_id 和 BDM.volume_id 字段置空(将这些更改保存到数据库)。此时,旧的根卷再次变为“可用”。对于搁置实例,这将由 API 服务处理。对于已停止的实例,这将由 nova-compute 服务处理,因此计算服务版本将被提升,以表示支持删除实例的根卷分离。

  • 附加

    通过 BlockDeviceMappingList.root_bdm() 找到根 BDM;此时,根 BDM 具有空 attachment_id 和 volume_id。

    为新的根卷创建卷附件记录 [5],然后更新 BDM 的 attachment_id 和 volume_id 字段,并将这些更改保存到数据库。

    正常的卷附加错误条件将生效,例如,除非它是多附加卷,否则无法附加已正在使用的卷。

启动和取消搁置操作将受到“无卷”块设备映射检查的保护。除非已附加另一个卷,否则在启动卷被分离后,实例将不允许启动或取消搁置。

对于关机实例的分离/附加卷,这将涉及影响计算节点上超visor的连接,因此将取决于计算驱动程序的能力。我们现在知道 libvirtvmawarexen 驱动程序将能够做到这一点。将适当地更新此功能的特性支持矩阵。

在此 bug [6] 中识别出卷操作和实例状态更改之间存在竞争条件。启动卷分离和取消搁置操作之间将存在相同的竞争条件,直到该 bug 被修复。该 bug 将由规范 [7] 解决。

备选方案

一种替代方案是根本不允许分离启动卷。这意味着根设备只能通过删除和重新创建实例来更改。目前,实例上的许多设备都可以动态添加和删除。

另一种替代方案是更通用,允许删除任何类型的启动设备并添加任何类型的启动设备。这将包括临时磁盘上的镜像、快照和卷。由于这超出了现有的卷 API,这种泛化建议需要一个新的 API。这对于满足提供的用例是不必要的,因此我们建议将此行为限制在现有的 API 中。

另一种替代方案是仅允许在单个操作中交换启动卷。这保留了实例始终具有卷的假设(在操作期间除外),但会降低一些灵活性。在灾难恢复用例中,可以搁置实例并分离其启动卷。如果实例始终必须具有卷,这将需要为每个未使用的实例使用第二个卷(除了副本)。这会浪费资源。

数据模型影响

REST API 影响

为显示卷附件 REST API 添加一个新的微版本,以允许暴露 boot_index 字段。

在同一个微版本中,我们将更改附加卷 REST API 以允许将 is_root 作为参数传递。

尝试分离启动卷当前始终返回错误

“Can’t detach root device volume (HTTP: 403)”

这将改变实例处于停止或 shelved_offloaded 状态的情况,以允许分离。

尝试启动或取消搁置一个由于已被分离而缺少启动卷的实例将返回一个错误

“Can’t unshelve instance without a root device volume (HTTP: 403)”

这些错误更改也需要 API 微版本递增。

安全影响

无。

通知影响

无。

其他最终用户影响

python-novaclient 和 python-openstackclient 将更新以支持新的功能。

性能影响

无。

其他部署者影响

无。

开发人员影响

无。

升级影响

计算服务版本将被提升,以表示支持删除实例的 detach_volume 流。

实现

负责人

主要负责人

Kevin Zheng

工作项

本规范将建立在 [7] 的基础之上。以下更改是本规范的一部分。

  • 添加“无卷”块设备映射实用程序方法,以指示已删除启动设备。这些方法将创建“无卷”块设备映射,将 volume_id 字段设置为 None,并检查映射中是否存在未存在的卷。

  • 扩展用于分离已停止和 shelved_offloaded 实例的卷的方法,以处理启动卷和“无卷”块设备映射。为卷附加 API 添加一个新的微版本,以指示指定的卷是根卷。

  • 在 API 中添加保护机制,以在启动和取消搁置实例之前检查“无卷”映射。

  • 更改计算 API 上的条件保护机制,以允许在实例停止或 shelved_offloaded 状态下分离启动设备。

依赖项

本规范扩展了 [8] 启用的卷操作。

有一个并行(但不依赖)的规范 [7],它解决了 bug [6]。该规范不是本规范所必需的,但值得注意的是,此功能将受益于该规范中处理的通用 bug 修复。

测试

所有现有的卷操作都具有单元测试和系统测试。此处描述的更改可以通过 nova 中的单元测试覆盖。

我们还将在对分离和附加操作的新用例进行覆盖后,在 tempest 中添加系统测试。

文档影响

记录何时可以分离和附加根设备卷。

特性支持矩阵将更新关于此功能的信息。

参考资料

[1] 检查分离时是否为根卷

https://github.com/openstack/nova/blob/aa9f9448c9cf77bb1e55aa0cde5e7f9c4e0157c4/nova/api/openstack/compute/volumes.py#L434

[2] 添加在以下情况下分离实例的根设备卷的功能

关机状态时分离根设备卷的功能。 https://bugs.launchpad.net/nova/+bug/1396965

[3] shelved_offload_time 配置选项

https://docs.openstack.org/nova/latest/configuration/config.html#DEFAULT.shelved_poll_interval

[4] 关于实例 vm_state 的邮件列表讨论,以允许分离/附加根卷

volume. http://lists.openstack.org/pipermail/openstack-discuss/2019-January/001344.html

[5] Cinder 附件创建

https://github.com/openstack/nova/blob/85b36cd2f82ccd740057c1bee08fc722209604ab/nova/volume/cinder.py#L710

[6] 卷操作应设置任务状态。

https://bugs.launchpad.net/nova/+bug/1275144

[7] https://blueprints.launchpad.net/nova/+spec/avoid-parallel-conflicting-api-operations

[8] Shelved 卷操作规范(已在 Mitaka 中完成)

https://blueprints.launchpad.net/nova/+spec/volume-ops-when-shelved

历史

修订版

发布名称

描述

Mitaka

引入

Newton

重新提出。

Ocata

重新提出。

Stein

重新提出。

Train

重新提出。