Volume multiattach 增强

https://blueprints.launchpad.net/nova/+spec/volume-multiattach-enhancements

本规范建议添加一个计算 API 微版本,以便在同一请求中创建多个服务器,使用相同的 multiattach 卷,并允许用户在将卷附加到服务器时指定附加模式。

问题描述

此更改将解决两个问题。

  1. 添加从 multiattach 兼容卷启动多个服务器的功能,在一个请求中完成。

    相关 bug: https://bugs.launchpad.net/nova/+bug/1747985

    目前,用户无法使用 multiattach 卷在一个请求中创建多个服务器,因为计算 API 特别阻止超过一个服务器尝试附加到同一个卷(在这方面它不了解 multiattach)。

  2. 添加在附加卷时传递 attach_mode 的能力。

    相关 bug: https://bugs.launchpad.net/cinder/+bug/1741476

    目前,所有对 multiattach 卷的辅助附加都以读/写模式进行。用户希望能够指定对 multiattach 卷的附加是只读的。Nova 将简单地将此传递给 Cinder 在创建(或更新)附加时(attach 模式在 host connector 参数中指定给 POST /attachmentsPUT /attachments/{id})。

    虽然指定只读附加模式主要只有在使用 multiattach 卷时才有意义,但计算 API 不会区分 multiattach 兼容卷和非 multiattach 兼容卷在传递 attach 模式时。默认情况下,attach 模式将与 Cinder 中的默认模式匹配,即读/写

    https://github.com/openstack/cinder/blob/12.0.0/cinder/volume/manager.py#L4391

用例

作为计算 API 的最终用户,我希望能够在单个请求中创建一组服务器,所有服务器都附加到同一个 multiattach 卷。

作为计算 API 的最终用户,我希望能够将同一个卷附加到多个服务器,但只有一台服务器能够写入该卷。

作为 Scientific SIG 用户 [1],我希望为我的裸机实例创建多个服务器,这些服务器共享同一个只读 multiattach 根卷。

提议的变更

将在新的微版本中对计算 API 进行以下更改。

  • 更改计算 API _check_and_transform_bdm 逻辑 [2],以便如果请求了新的微版本并且正在使用 multiattach 卷,则可以在单个请求中创建多个服务器时重用该 multiattach 卷。

  • 更改 block_device_mapping_v2 请求体参数模式,以允许传递 attach_mode 字段。如果未指定,卷 BDM 将默认设置为“rw”表示读/写。另一个可能的值将是“ro”表示只读。这将允许从卷启动的场景,其中该卷应以只读模式附加。

    注意

    attach_mode 字段仅适用于 destination_type=volume 的块设备映射。如果 destination_type=local 并且指定了 attach_mode,则将导致向用户返回 400 HTTPBadRequest 错误响应。这是因为本地块设备用于交换或临时磁盘,并且在块存储服务中没有被建模为卷,而 attach_mode 字段将在那里使用。与其忽略这种情况下的 attach_mode 请求,我们将明确失败,因为它不受支持。

  • 将一个 attach_mode 参数添加到 POST /servers/{server_id}/os-volume_attachments 卷附加 API 的请求体中。与 block_device_mapping_v2 模式类似:默认值为“rw”,唯一的其他有效选项是“ro”。

在使用 host connector 字典创建或更新卷附加时,将 mode 键添加到 connector 字典中,这是将此信息传递给 Cinder 的当前方式,因为它不是这些 API 上的顶级参数。

计算 RPC API 版本将增加,以指示哪些计算服务支持用户定义的附加模式。这将允许我们检查(并失败)来自 API 的情况,如果用户尝试将卷以只读模式附加到运行在尚未支持该功能的旧计算实例上。这将导致向用户返回 409 错误响应。

交换卷

PUT /servers/{server_id}/os-volume_attachments/{attachment_id} 交换卷 API 请求不会更改。正在交换的卷的块设备映射将与正在交换的卷的 attach_mode 相同。例如,如果卷 A 以只读模式附加到服务器 X,并且用户将该卷重新类型化为 B,那么卷 B 也将以只读模式附加到服务器 X。

备选方案

多重创建

诚然,能够在单个请求中创建多个服务器,所有服务器都附加到同一个 multiattach 卷,并非至关重要,因为用户可以针对同一个 multiattach 卷连续创建服务器。但是,如果仅在某些参数用于创建服务器时才支持某些功能(在本例中为服务器多重创建、从卷启动和 multiattach 卷),则会导致 API 用户体验不佳。

附加模式

与其让用户指定哪些附加应该是读/写,哪些应该是只读,不如让 nova(或 cinder)计算 multiattach 卷上的附加,并使所有辅助附加都为只读。但这会引入一些问题

  • 在计算连接时可能会出现竞争条件。

  • 辅助附加的默认附加模式应该是多少?使该默认值可配置将意味着添加由配置驱动的 API 行为,这在 OpenStack 云之间不可互操作。

  • 如果第一个也是唯一的读/写附加被删除,并且还有其他只读附加到该卷,我们应该怎么办?我们是否应该自动将其中一个更改为读/写,以便至少一台服务器可以写入该卷?

由于这些复杂性,nova 和 cinder 团队在 Rocky 项目团队会议上达成一致 [3],我们将把附加模式的决定权交给用户。

数据模型影响

将在 block_device_mappings 表中添加一个 attach_mode 列。现在,这只需要一个可为空的 2 个字符的字段。

将对 nova.objects.BlockDeviceMapping 对象进行相应的更改。

我们不会在数据模型中设置“rw”的默认值,因为“local”BDM 不使用 attach_mode。相反,BlockDeviceMapping 版本对象将确保为卷 BDM 使用“rw”的默认值。

REST API 影响

以下 API 将在响应体中返回 attach_mode

  • GET /servers/{server_id}/os-volume_attachments:

    {
        "volumeAttachments": [
            {
                "device": "/dev/sdd",
                "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803",
                "serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
                "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803",
                "attach_mode": "rw"
            },
            {
                "device": "/dev/sdc",
                "id": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
                "serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
                "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804",
                "attach_mode": "ro"
            }
        ]
    }
    
  • GET /servers/{server_id}/os-volume_attachments/{volume_id}:

    {
        "volumeAttachment": {
            "device": "/dev/sdd",
            "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803",
            "serverId": "2390fb4d-1693-45d7-b309-e29c4af16538",
            "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803",
            "attach_mode": "rw"
        }
    }
    

在一个新的微版本中,有两个 API 模式更改。

服务器创建

POST /servers

block_device_mapping_v2 请求体参数中添加一个 可选 attach_mode 字段,例如:

"block_device_mapping_v2": [{
    "boot_index": "1",
    "uuid": "ac408821-c95a-448f-9292-73986c790911",
    "source_type": "volume",
    "destination_type": "volume",
    "attach_mode": "ro"}]

新字段的模式将是

'attach_mode': {
    'type': 'string',
    'enum': ['ro', 'rw'],
}

附加卷

POST /servers/{server_id}/os-volume_attachments

volumeAttachment 请求体参数中添加一个 可选 attach_mode 字段,例如:

{
    "volumeAttachment": {
        "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803",
        "attach_mode": "ro"
    }
}

新字段的模式将是

'attach_mode': {
    'type': 'string',
    'enum': ['ro', 'rw'],
}

安全影响

通知影响

nova.notifications.objects.instance.BlockDevicePayload 对象将镜像 nova.objects.BlockDeviceMapping 对象中的 attach_mode 字段。将使用一个新的枚举来对版本对象中的 attach_mode 字段进行建模。

其他最终用户影响

将对 python-novaclient 和 python-openstackclient 进行更改,以获得新的微版本。

同样,可以向 Horizon“附加卷”表单添加一个新字段,但这超出了此更改的范围。

需要/想要更改给定卷和服务器的附加模式的用户需要分离该卷,然后以所需的模式重新附加它。PUT /servers/{server_id}/os-volume_attachments/{attachment_id} API 不会更改以增加 attach_mode 参数。

性能影响

其他部署者影响

无。API 将检查是否可以根据计算 RPC API 版本将只读附加到实例,从而支持 nova-compute 服务的滚动升级。

开发人员影响

无。此更改与超visor 无关。

升级影响

无。

实现

负责人

主要负责人

Matt Riedemann <mriedem.os@gmail.com> (mriedem)

其他贡献者

工作项

  • 添加新的 attach_mode 字段的数据模型和版本对象更改。

  • 在计算服务中,在附加卷到实例时使用 BlockDeviceMapping.attach_mode 字段。这将是在任何创建或更新附加(包括正常卷附加以及实例移动操作,如调整大小)时,只要指定了 host connector 就会发生的情况。

  • 增加计算 RPC API 版本。

  • 使用新的微版本添加对 REST API 的更改以启用该功能。

依赖项

Bug 1747985 需要在 Cinder 中修复,以便在所有附加都“完成”之前,可以在 multiattach 卷上存在多个附加,这可能意味着将“reserved”添加到此代码中 multiattach 卷的允许状态列表中。[4]

测试

  • 针对负面场景的单元测试,例如:

    • 使用错误的微版本指定 attach_mode

    • 指定格式错误的 attach_mode 值/格式

    • 指定 attach_mode,而实例正在运行在较旧的计算服务上

    • 使用 destination_type=local BDM 指定 attach_mode

    • 尝试使用非 multiattach 卷在一个请求中创建多个服务器

  • 针对使用新微版本的常规 API 示例测试的功能测试。

  • 鉴于“多重创建到相同的 multiattach 卷”场景涉及的相对复杂性,应为此情况添加一个 Tempest 测试。

文档影响

  • 将更新计算 API 参考,以获取新的微版本。

  • 将更新计算管理指南的 已知问题 部分。

参考资料

历史

修订

发布名称

描述

Rocky

引入