使用扩展卷完成操作

https://blueprints.launchpad.net/nova/+spec/assisted-volume-extend

该蓝图建议使用 Cinder 中提出的 os-extend_volume_completion 卷操作 [3],以便在处理 volume-extended 外部服务器事件时提供成功或失败的反馈。

问题描述

Cinder 中的许多基于 remotefs 的卷驱动程序使用 qemu-img resize 命令来扩展卷文件。但是,当卷附加到客户机时,QEMU 将锁定该文件,并且 qemu-img 将无法调整其大小。

在这种情况下,只有持有锁定的 QEMU 进程才能调整卷的大小,这可以通过 QEMU 监视器命令 block-resize 触发。

目前,Cinder 没有足够的方法来使用此功能,因此 NFS、NetApp NFS、Powerstore NFS 和 Quobyte 卷驱动程序都禁用了扩展已挂载卷的功能。

用例

作为用户,我希望在卷附加到实例时扩展 NFS/NetApp NFS/Powerstore NFS/Quobyte 卷,并且希望卷的大小和状态反映操作的成功或失败。

提议的变更

Nova 的 libvirt 驱动程序在处理 volume-extended 外部服务器事件时使用 block-resize 命令,以告知 QEMU 附加卷的大小已更改。原则上,它也可以扩展卷文件,但目前无法向 Cinder 提供操作成功的反馈。

目前,Cinder 仅在完成扩展操作并重置卷状态从 extending 回到 in-use 后,才会向 Nova 发送 volume-extended 外部服务器事件。

借助 [3],Cinder 将允许卷驱动程序延迟完成扩展操作,并将卷状态保留为 extending,直到它发送了 volume-extended 事件并从 Nova 接收到反馈,即 os-extend_volume_completion 卷操作,其中包含一个 error 参数,指示是完成还是回滚操作。

目前,这只会影响上述提及的卷驱动程序,所有这些驱动程序之前都不支持在线扩展。所有其他驱动程序将继续在完成操作并重置为 in-use 状态后发送 volume-extended 事件,并且不会期望 os-extend_volume_completion 卷操作。

计算代理

Nova 的计算代理将在处理 volume-extended 事件时,使用卷状态来区分这两种行为

  • 如果卷状态为 extending,则它将尝试从卷的元数据中读取 extend_new_size,并使用此值作为卷的新大小,而不是卷大小字段。

    在成功扩展卷后,它将使用 "error": false 调用卷的扩展卷完成操作。

    如果出现任何问题,包括 extend_new_size 缺失于元数据中,或者小于卷的当前大小,它将记录错误并调用 os-extend_volume_completion 操作,其中 "error": true,以便 Cinder 可以回滚操作。

  • 对于任何其他卷状态,包括 in-use,事件的处理方式将与之前相同。

API

Nova 的 API 将引入一个新的微版本,以便 Cinder 可以在未完成扩展操作之前,确保新的行为可用。

为了在滚动升级期间处理旧的计算代理,API 还会检查接收到具有新微版本的 volume-extended 事件的目标代理的计算服务版本。如果目标计算代理太旧而无法支持该功能,API 将丢弃该事件并调用 os-extend_volume_completion 操作,其中 "error": true

备选方案

  • 之前的更改尝试使用 volume-extended 外部服务器事件来支持 NFS 驱动程序的在线扩展 [1],但完全没有依赖 Nova 到 Cinder 的反馈。相反,它只会设置卷的新大小,将状态改回 in-use,通知 Nova,并寄希望于一切顺利。

    如果 Nova 侧出现任何问题,这仍然会导致卷状态指示操作已成功,这是不可接受的。

  • 此规范的早期版本提出在 Nova 中一个新的同步 API [2],它将直接调用管理附加了卷的客户机的 nova-compute 实例的 CompVirtAPI.extend_image,以触发调整大小操作,将新大小传递给 virt 驱动程序的 extend_volume 方法,并获得操作成功与否的反馈。

    同步 API 的问题是,RPC 和 API 超时限制了扩展操作可以花费的最大时间。对于 QEMU,这似乎是可以接受的,因为为 block-resize 命令禁用存储预分配,并且因为所有合理的的文件系统都支持稀疏文件操作。

    但是,这可能不适用于将来可能需要此 API 的其他卷或 virt 驱动程序。它也会打破 Nova 和 Cinder 之间已建立的异步协调模式,其中包括辅助快照和卷迁移功能。

  • 遵循此模式,我们可以使提出的 API 异步,并使用类似于 Nova 的 os-assisted-volume-snapshots API 的新回调,该 API 使用 os-update_snapshot_status 快照操作向 Cinder 提供反馈。

    新的 Nova API 的功能将只是触发操作并通信新的大小。问题在于,是否值得为 Nova 添加一个新的 API,因为已经存在可以用于这两者的机制。

  • 在 Nova 中触发扩展操作的现有机制当然是 volume-extended 外部服务器事件。正如本规范建议的那样,将其用于此目的,需要单独传输目标大小,因为外部服务器事件只有一个可自由使用的文本字段,对于 volume-extended 已经用于卷 ID。

    除了像 [3] 和本规范建议的那样将其存储在管理元数据中之外,还有更新卷大小字段的选项,就像 [1] 本质上所做的那样。

    如果 Nova 的错误响应丢失,卷将继续保持新的大小。我们需要扩展 os-reset_status 以允许大小重置,或者类似的东西来清理像这样的卷。这是可行的,但仅在卷成功扩展后才更新大小字段似乎是一个更干净的解决方案。

  • 我们还可以扩展外部服务器事件 API 以接受事件的附加数据,并使用它将新的大小通信给 Nova。

    此选项受到此规范早期版本审查人员的青睐 [2],但它将是对 Nova API 的更复杂更改。

    但是,如果外部服务器事件 API 的未来版本中可用额外的字段,那么使用它而不是卷元数据将是一个相对较小的更改。

数据模型影响

REST API 影响

外部服务器事件 API 的行为将发生变化。

  • 如果 Nova 收到 volume-extended 事件,并且引用的卷状态为 extending,Nova 将查找卷元数据中的 extend_new_size 键,并将其用作目标大小来更新块设备映射并传递给 virt 驱动程序的 extend_volume 方法,而不是使用卷大小字段。

    Nova 还会尝试调用 Cinder 的新 os-extend_volume_completion 卷操作,该操作在 [3] 中提出,以让 Cinder 知道操作是否成功。

  • 否则,API 的行为将与之前相同。

安全影响

通知影响

其他最终用户影响

性能影响

其他部署者影响

开发人员影响

升级影响

检查目标计算服务版本允许 API 优雅地处理滚动升级。

实现

负责人

主要负责人

kgube

其他贡献者

功能联络人

功能联络人

目前还没有

工作项

  • 更新外部服务器事件 API,以检查 volume-extended 事件的目标计算服务版本。

  • 更新 ComputeVirtAPI.extend_volume 方法,以遵循 计算代理 中概述的行为。

  • 添加单元测试。

  • 调整 Nova gate 中的 NFS 作业以验证在线扩展。

依赖项

  • 扩展卷完成操作 [3]

测试

我们应该测试在所有可能的错误或成功条件下,如果卷状态为 extending,是否正确调用了 os-extend_volume_completion

我们应该测试调用 os-extend_volume_completion 失败的情况。

我们还需要测试 volume-extended 是否继续正确处理非 extending 状态的卷。

文档影响

外部服务器事件 API 的新行为应添加到文档中。

参考资料

历史

修订版

发布名称

描述

2023.1 Antelope

引入