Detach and attach boot volumes

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

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

问题描述

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

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

存在一些用例要求在实例未运行时分离启动卷,因此我们建议放宽固有的假设,认为当实例被搁置时可以更改启动卷的附加关系。为了确保安全,我们可以防止在没有启动卷的情况下取消搁置实例。

用例

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

用例如下

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

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

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

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

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

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

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

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

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

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

提议的变更

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

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

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

当启动卷被分离时,其块设备映射将被替换为指示没有卷的块设备映射。将为此目的添加一个新的布尔字段,称为 device_present;device_present = False 表示设备缺失且无法使用。

将使用通常的附加卷 API 调用来附加启动卷。卷附加操作允许用户指定设备名称。实例的启动设备名称是已知的,因此用于确定用户是否尝试将卷作为根设备附加。只有当实例处于 shelved_offloaded 状态并且根设备具有“无卷”块设备映射时,才允许附加。

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

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

备选方案

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

我们还可以进一步推广,允许在实例关机时分离和附加启动卷。这将涉及影响计算节点上与 hypervisor 的连接。现有卷设备代码固有地支持对启动卷执行此操作,因此似乎没有必要禁用它。但是,这会打开代码中更多的边界情况,并且对于上述用例来说不是必需的。

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

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

数据模型影响

将向 BlockDeviceMapping 对象和 block_device_mapping 数据库表添加一个名为 device_present 的布尔字段。该字段的默认值为 True。

将 device_present 字段设置为 False 将指示块设备映射是缺失设备的占位符,并且无法使用。

REST API 影响

REST API 的操作或参数不会发生变化。

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

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

当实例处于 shelved_offloaded 状态时,这将允许分离。

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

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

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

安全影响

无。

通知影响

无。

其他最终用户影响

无。

性能影响

无。

其他部署者影响

无。

开发人员影响

无。

实现

负责人

主要负责人

pmurray@hp.com

其他贡献者

andrea.rosa@hp.com

工作项

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

  • 向 BlockDeviceMapping 对象和 block_device_mapping 数据库表添加 device_present 字段。

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

  • 扩展用于处理搁置实例的附加/分离卷的方法,以处理启动卷和“无卷”块设备映射。

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

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

依赖项

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

存在一个并行(但不依赖)的规范 [3],该规范解决了 bug [2]。本规范不需要该规范,但值得注意的是,此功能将受益于该规范中处理的通用 bug 修复。

测试

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

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

文档影响

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

尝试启动没有根设备的实例时返回错误。

参考资料

[1] 添加在实例处于

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

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

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

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

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

历史

修订版

发布名称

描述

Mitaka

引入