支持 Cinder 卷多重挂载

https://blueprints.launchpad.net/nova/+spec/multi-attach-volume

目前,Nova 仅允许一个卷附加到一个宿主机或实例。有时,用户可能希望能够将同一个卷附加到多个实例。

问题描述

目前,Nova 仅允许一个卷一次附加到一个实例或宿主机。Nova 在多个地方做出了假设,假设单个卷只能附加到一个实例,尽管 Cinder 现在支持将卷附加和分离到/从多个实例。Nova 假设如果一个卷已附加,则不能再次附加,详情请参见 nova/volume/cinder.py: check_attach()。

用例

允许用户使用读写或只读附件在多个客户机之间共享卷。具有两个节点的集群应用程序,其中一个处于活动状态,一个处于被动状态。两者都需要访问相同的卷,尽管只有其中一个处于活动访问状态。当活动节点发生故障时,被动节点可以快速接管并访问数据。

提议的变更

Nova 中需要的更改与附加和分离时间相关。

在附加时,Nova 必须移除只能在卷“未被使用”时才能附加它的假设。Cinder 卷现在可以在“可用”和/或“正在使用”时附加。Cinder 仅允许在卷创建时设置了“multiattach”标志的情况下,将卷附加多次。

在分离时,Nova 需要将 attachment_id 传递给 cinderclient,以告诉 cinder 要分离哪个特定的附件。由于一个卷可以附加到实例和/或宿主机,因此不能跳过在分离时传递 attachment_uuid。仅传递实例 uuid 是不够的,因为 cinder 提供了将卷附加到宿主机的可能性。如果未传递,并且存在多个附件,那么 cinder 将会失败,因为它不知道要分离哪个附件。在 Nova 侧,可以通过从 volume_api 获取卷附件,并使用 instance_uuid 搜索附件来识别 attachment_id,无需将其存储在 Nova 中。

默认情况下,libvirt 假设所有磁盘仅供单个客户机独占使用。如果您想在实例之间共享磁盘,则需要在配置磁盘的客户机 XML 时,通过设置磁盘的 sharable 标志来告知 libvirt。这意味着超visor 将不会尝试获取磁盘的独占锁,所有 I/O 缓存都将被禁用,并且任何 SELinux 标记都允许所有域使用。

Nova 需要为实例的多附加磁盘设置此 sharable 标志。只有 libvirt 驱动程序被修改以支持多附加,对于所有其他 virt 驱动程序,此功能被禁用,信息存储在基础 ComputeDriver 的 virt 驱动程序 capabilities 字典中。

备选方案

对于上述用例,故障转移场景可以通过将卷挂载到被动/待机实例来处理。这意味着待机实例不再是热备用,因为卷挂载需要时间,这意味着在重新挂载期间,新的主实例将没有卷,这在标记主实例故障后释放卷的意义上会有所不同。

另一种选择是克隆卷并将其克隆挂载到第二个实例。缺点是原始卷的任何更改不会显示在挂载的克隆中,因此只有在卷是只读的情况下,这才是可行的选择。

数据模型影响

REST API 影响

Nova API 的某些功能需要谨慎处理或暂时禁用,以支持多附加卷。在这种情况下,‘create_volume_snapshot’ 被禁用,因为我们无法在没有 instance_uuid 的情况下识别 BDM。此请求的 API 格式未更改,仅作为一种保护措施,直到所需的 API 更改支持使用多附加的此请求为止。

另一个需要限制的功能是“从卷启动”(BFV)。在这种情况下,需要进一步调查两个方面。第一是 ‘delete_on_termination’ 标志,如果设置为 True,则旨在在删除实例时删除附加的卷。此选项不会造成问题,因为 Cinder 会负责在仍然存在活动附件的情况下不删除卷。Nova 将从 Cinder 收到卷删除失败的错误,然后将其记录 [1],但不会影响实例终止过程。根据这一点,此标志可以与多附加一起使用,当提供的卷具有 multiattach=True 并且传递了 delete_on_termination=True 标志用于 BFV 时,无需进行更改。

BFV 的第二个方面是启动过程。在这种情况下,唯一的问题来自启动卷,这些卷在启动请求中指定为启动设备。为此,必须检查 ‘block_device_mapping’ 列表,以过滤掉将多附加卷指定为启动设备的情况。可以通过检查 BDM 的 ‘source_type’ 和 ‘destination_type’,以及在 BDM 字典中搜索 ‘boot_index’: 0 项来完成。基于 BDM 信息中存储的 volume_id,可以从 Cinder 检索卷,以检查 ‘multiattach’ 标志是否设置为 True,在这种情况下,请求将返回错误,表明此操作不支持多附加卷。

对于 Nova 自身创建卷的情况,即 source_type 为 blank/image/snapshot,目前不应为卷启用多附加。

更多期望的 REST API 更改列在后续规范中。

安全影响

在 libvirt 驱动程序中,磁盘被赋予共享的 SELinux 标签,因此该磁盘不再具有强大的 sVirt SELinux 隔离。

OpenStack 卷加密功能应该也适用于此用例,不应破坏加密器在集群文件系统下方的运作方式,通过为所有连接使用相同的密钥。在多个实例上附加加密卷应该在 Tempest 中进行测试,以查看是否存在任何意外问题。

通知影响

其他最终用户影响

命令行现在允许您调用 Nova volume-attach 将一个卷附加到多个实例。

性能影响

其他部署者影响

开发人员影响

任何时候向 Nova 添加需要调用分离卷的新代码时,开发人员必须获取实例的卷附件 UUID。此信息嵌入在 cinder 卷的 volume_attachments 列表中。

实现

基于 Walter Boring 和 Charlie Zhou 的工作。同意 Walter 重新开始工作。

负责人

主要负责人

ildiko-vancsa

工作项

  1. 更新 cinderclient 的使用方式,以提取 Nova 获取卷时的新卷附件列表。

  2. 更新所有对 cinderclient.detach() 的调用,以包含 attachment uuid。

  3. 更新 libvirt 驱动程序以生成具有多重挂载卷的实例的正确域 XML

依赖项

测试

我们将需要添加新的 Tempest 测试来支持新的 Cinder 卷 multiattach 标志。新的 cinder multiattach 标志允许将卷挂载多次。例如,需要测试以下场景

  • 将同一个卷挂载到两个实例。

  • 从具有 multiattach 的卷启动

  • 具有 multiattach 的加密卷

  • 负面测试

  • 从具有 boot_index=0 的可多重挂载卷启动

  • 尝试将非 multiattach 卷挂载到多个实例

文档影响

我们将需要更新文档以讨论将卷挂载到多个实例的新能力,如果 cinder multiattach 标志设置在卷上。还需要添加到文档中,由于 Nova 卷创建 API 的弃用,通过 API 不支持创建这些类型的卷。如果需要允许多个卷挂载,则必须在 Cinder 侧使用指定的必要属性创建卷。

还需要在文档中概述,以读写模式多次挂载卷可能会导致数据损坏,如果未正确处理。用户有责任添加某种类型的排除(在文件系统或网络文件系统层)以防止多个写入器损坏数据。如果可用,应提供示例来指导用户如何操作。

参考资料

历史

修订

发布名称

描述

Kilo

引入

Liberty

重新批准

Mitaka-1

重新批准

Mitaka-2

已更新 API 限制和测试场景