允许 Manila 共享直接附加到使用 libvirt 的实例

https://blueprints.launchpad.net/nova/+spec/libvirt-virtiofs-attach-manila-shares

Manila 是 OpenStack 共享文件系统服务。此规范将概述 Nova 中所需的 API、数据库、计算和 libvirt 驱动程序更改,以允许 Manila 提供的共享与实例关联并附加到实例。

问题描述

目前,用户必须手动连接到并挂载实例中由 Manila 提供的共享。因此,操作员需要确保 Manila 后端存储可以从客户机子网路由访问。

用例

  • 作为操作员,我希望 Manila 数据路径与任何租户可访问的网络分离。

  • 作为用户,我希望将 Manila 共享直接附加到我的实例,并拥有一个简单的界面来在实例中挂载它们。

  • 作为用户,我希望从我的实例分离直接附加的 Manila 共享。

  • 作为用户,我希望跟踪附加到我的实例的 Manila 共享。

提议的变更

此初始实现仅提供对附加共享到现有 SHUTOFF 实例的支持,以及稍后分离共享的支持。在实例的初始创建过程中表达附件的能力不在本规范的涵盖范围内。

一旦共享附加,对移动操作的支持也不在本规范的涵盖范围内,任何请求 shelve、evacuate、resize、cold migrate 或 live migrate 具有附加共享的实例都将被拒绝,并暂时返回 HTTP409 响应。

将在新的微版本下引入一个新的服务器 shares API。这将列出当前共享,显示其详细信息,并允许附加或分离共享。

将引入一个新的 share_mapping 数据库表和相关的 ShareMapping 版本化对象,以捕获共享附件的详细信息。将提供一个基础 ShareMapping 版本化对象,可以从中派生 virt 驱动程序和后端共享特定的对象,从而提供特定的共享附加和分离实现。

注意

需要注意的是,Nova 内部不会存储任何 Manila 状态,除了用于初始附加共享的导出详细信息。稍后在分离共享时将使用这些详细信息。如果共享随后重新附加,Nova 将从 Manila 请求新的导出详细信息,并在 Nova 中新的共享附件中存储这些信息。

libvirt 驱动程序将被扩展以支持上述内容,并初步支持冷附加和分离。未来的工作将旨在添加实时附加和分离,一旦 libvirt 本身支持

此初始 libvirt 支持将针对 Manila 中的基本 NFS 和更复杂的 CephFS 后端。共享将通过 virtio-fs 映射到基础 libvirt 域。这需要计算主机上的 QEMU >=5.0 和 libvirt >= 6.2,以及实例客户机操作系统内的 >= 5.4 的内核版本。

此外,此初始实现需要关联的实例使用 文件支持的内存大页。这是 virtio-fs 的要求,因为 virtiofsd 服务使用 vhost-user 协议直接与基础客户机通信。(参考:vhost-user 文档

将引入两个新的计算能力特征和过滤器,以模拟计算对 virtio-fs 和文件支持内存的支持。在将共享关联到实例时,将检查运行该实例的主机是否支持

  • COMPUTE_STORAGE_VIRTIO_FS 特征

  • COMPUTE_MEM_BACKING_FILE 特征

或者

实例配置了 hw:mem_page_size 附加规格。

从操作员的角度来看,这意味着 COMPUTE_STORAGE_VIRTIO_FS 支持要求操作员必须将所有计算节点升级到支持使用 virtiofs 的版本的版本。

COMPUTE_MEM_BACKING_FILE 支持要求操作员配置一个或多个具有文件支持内存的主机。可以通过创建包含这些主机的 AZ 来确保实例将降落在其中一个主机上。然后指示用户将他们的实例部署到此 AZ。或者,操作员可以通过将 trait:COMPUTE_MEM_BACKING_FILE=required 作为附加规格或镜像属性添加到调度器来引导调度器选择合适的宿主机。

用户将使用挂载标签挂载附加的共享,这要么是 Manila 中的共享 UUID,要么是用户在其附加共享请求中提供的字符串。

user@instance $ mount -t virtiofs $tag /mnt/mount/path

最初的实现不会创建先前讨论的 os-share 库,但如果底层主机上挂载和跟踪共享所需的逻辑也由其他项目需要,则将来可以创建它。目前,libvirt 驱动程序中现有的代码 用于跟踪基于 remoteFS 的存储(例如 NFS、SMB 等)托管的卷使用的文件系统主机挂载,将尽可能地重用。

共享映射状态

                     +----------------------------------------------------+   Reboot VM
    Start VM         |                                                    | --------------+
    Share mounted    |                       active                       |               |
+------------------> |                                                    | <-------------+
|                    +----------------------------------------------------+
|                      |                   |             |
|                      | Stop VM           |             |
|                      | Fail to umount    |             |
|                      v                   |             |
|                    +------------------+  |             |
|                    |      error       | <+-------------+-------------------+
|                    +------------------+  |             |                   |
|                      |                   |             |                   |
|                      | Detach share or   |             |                   |
|                      | delete VM         | Delete VM   |                   |
|                      v                   |             |                   |
|                    +------------------+  |             |                   |
|    +-------------> |        φ         | <+             |                   | Start VM
|    |               +------------------+                |                   | Fail to mount
|    |                 |                                 |                   |
|    | Detach share    |                                 | Stop VM           |
|    | or delete VM    | Attach share                    | Share unmounted   |
|    |                 v                                 v                   |
|    |               +----------------------------------------------------+  |
|    +-------------- |                      inactive                      | -+
|                    +----------------------------------------------------+
|                      |
+----------------------+
φ

表示数据库中没有条目。共享和服务器之间没有关联。

附加共享

表示 POST /servers/{server_id}/shares

分离共享

表示 DELETE /servers/{server_id}/shares

此图描述了共享映射状态(nova),这与 Manila 共享的状态无关。

只有在 VM 状态为 STOPPEDERROR 时,才能附加/分离共享。这些只是数据库上的操作,不需要对计算 API 进行 RPC 调用。这是此规范的有意设计。因此,这可能导致 VM 启动操作失败,因为底层共享附加失败。

如果共享未挂载到计算主机上,则将执行挂载操作。如果以前的共享已挂载到计算主机上用于另一个服务器,则将尝试挂载它,并记录警告,说明该共享已挂载。

卸载操作只有在共享已挂载且不再被另一个服务器使用时才会真正完成。

使用上述挂载和卸载操作,状态存储在内存中,不需要在数据库中查找。

共享将以读/写模式挂载到计算主机上。不支持只读,因为无法同时以只读和读/写模式挂载共享。如果用户想以只读模式挂载共享,则必须在 VM fstab 中执行此操作。

Manila 共享删除问题

尽管实例正在使用共享,但用户仍可以删除它。因此,实例将失去对数据的访问权限,并且可能导致删除丢失的共享和修复实例的困难。这是一个已识别的问题,需要 Manila 修改。与 Manila 团队确定了一种解决方案,即附加到共享访问允许策略的元数据,该元数据将锁定共享并防止其删除,直到删除锁定。如果上述 Manila 更改可以在 Zed 周期中落地,那么这里的建议是在 Nova 中使用锁定机制。否则,明确记录已知问题为不受支持,并警告用户要小心并避免此陷阱。

实例元数据

将实例共享添加到实例元数据。使用 ShareMetadata 对象扩展 DeviceMetadata,其中包含用于在实例上挂载 virtiofs 的 shareIdtag。请参阅 其他最终用户影响

备选方案

唯一的替代方案是继续当前的情况,即用户必须手动在他们的实例中挂载共享。缺点是这些实例必须能够访问 Manila 后端使用的存储网络。

REST API 影响

将在新的微版本下引入一个新的服务器级别 shares API,其中包含以下方法

  • GET /servers/{server_id}/shares

列出附加到实例的所有共享。

返回代码:200、400、401、403、404

{
    "shares": [
        {
            "shareId": "48c16a1a-183f-4052-9dac-0e4fc1e498ad",
            "status": "active",
            "tag": "foo"
        },
        {
            "shareId": "e8debdc0-447a-4376-a10a-4cd9122d7986",
            "status": "active",
            "tag": "bar"
        }
    ]
}
  • GET /servers/{server_id}/shares/{shareId}

显示附加到实例的特定共享的详细信息。

返回代码:200、400、401、403、404

{
    "share": {
        "shareId": "e8debdc0-447a-4376-a10a-4cd9122d7986",
        "status": "active",
        "tag": "bar"
    }
}

PROJECT_ADMIN 能够查看存储在 Nova 中的附件 ID 和导出位置的详细信息

{
    "share": {
        "attachmentId": "715335c1-7a00-4dfe-82df-9dc2a67bd8bf",
        "shareId": "e8debdc0-447a-4376-a10a-4cd9122d7986",
        "status": "active",
        "tag": "bar",
        "export_location": "server.com/nfs_mount,foo=bar"
    }
}
  • POST /servers/{server_id}/shares

将共享附加到实例。

先决条件:

  • 实例必须处于 SHUTOFF 状态。

  • 实例应具有启用 virtiofs 所需的功能(见上文)。

这是一个同步 API。因此,VM 共享附件状态定义在数据库中并设置为非活动状态。然后,打开 VM 将执行所需的操作以附加共享并在没有错误的情况下将其设置为活动状态。

返回代码:202、400、401、403、404、409

请求主体

注意

tag 将是请求体中的可选请求参数,如果未提供,则始终如请求中提供的 shareId(UUID)。

tag 如果由用户提供,必须是最大长度为 64 字节的 ASCII 字符串。

{
    "share": {
        "shareId": "e8debdc0-447a-4376-a10a-4cd9122d7986"
    }
}

响应体

{
    "share": {
        "shareId": "e8debdc0-447a-4376-a10a-4cd9122d7986",
        "status": "active",
        "tag": "e8debdc0-447a-4376-a10a-4cd9122d7986"
    }
}
  • DELETE /servers/{server_id}/shares/{shareId}

将共享从实例分离。

先决条件:实例必须处于 SHUTOFFERROR 状态。

返回代码:202、400、401、403、404、409

数据模型影响

将引入一个新的 share_mapping 数据库表。

  • id - 主键自动递增

  • uuid - 用于标识特定共享附件的唯一 UUID

  • instance_uuid - 共享将附加到的实例的 UUID

  • share_id - Manila 中的共享的 UUID

  • status - Nova 中共享附件的状态(activeinactiveerror

  • tag - 用户用于在实例中挂载共享的设备标签。

  • export_location - 用于将共享附加到基础主机的导出位置

  • share_proto - 共享文件系统协议(NFSCEPHFS

将引入一个新的基础 ShareMapping 版本化对象,以封装上述数据库条目,并用作特定 virt 驱动程序实现的父类。

数据库字段 statusshare_proto 的值将不会使用枚举强制执行,从而允许未来的更改并避免数据库迁移。但是,为了使代码更健壮,将在对象字段上定义枚举。

包含文本的字段将在数据库模式中使用 String 而不是 Text 类型,以限制列宽并将其内联存储在数据库中。

此基础 ShareMapping 对象将提供存根 attachdetach 方法,任何子对象都需要实现这些方法。

将引入新的 ShareMappingLibvirtShareMappingLibvirtNFSShareMappingLibvirtCephFS 对象作为 libvirt 实现的一部分。

安全影响

Manila 返回的用于将共享挂载到主机以及主机文件系统位置的 export_location JSON blob 不应被 Nova 记录,并且默认情况下只能通过 API 由管理员访问。

通知影响

将添加新的通知

  • 一个用于添加共享附加和共享分离的新通知。

  • 一个用于使用共享映射信息扩展实例更新通知。

实例有效负载中的共享映射将是可选的,并通过通知配置参数 include_share_mapping 进行控制。默认情况下将禁用它。

附加和分离通知的建议有效负载与具有管理员权限的 show 命令返回的有效负载相同。

{
    "share": {
        "instance_uuid": "7754440a-1cb7-4d5b-b357-9b37151a4f2d",
        "attachmentId": "715335c1-7a00-4dfe-82df-9dc2a67bd8bf",
        "shareId": "e8debdc0-447a-4376-a10a-4cd9122d7986",
        "status": "active",
        "tag": "bar",
        "export_location": "server.com/nfs_mount,foo=bar"
    }
}

实例更新的建议有效负载将是附加到该实例的共享列表。

{
    "shares":
    [
        {
            "instance_uuid": "7754440a-1cb7-4d5b-b357-9b37151a4f2d",
            "attachmentId": "715335c1-7a00-4dfe-82df-9dc2a67bd8bf",
            "shareId": "e8debdc0-447a-4376-a10a-4cd9122d7986",
            "status": "active",
            "tag": "bar",
            "export_location": "server.com/nfs_mount,foo=bar"
        },
        {
            "instance_uuid": "7754440a-1cb7-4d5b-b357-9b37151a4f2d",
            "attachmentId": "715335c1-7a00-4dfe-82df-ffffffffffff",
            "shareId": "e8debdc0-447a-4376-a10a-4cd9122d7987",
            "status": "active",
            "tag": "baz",
            "export_location": "server2.com/nfs_mount,foo=bar"
        }
    ]
}

其他最终用户影响

用户需要使用返回的 tag 在他们的 guestOS 中挂载共享。

用户可以使用实例元数据来发现和自动挂载共享。

性能影响

通过使用 vhost-user virtio-fs 应该在 guestOS 中具有接近本地(已挂载)文件系统性能。虽然 VM 和主机之间将具有接近本地的性能,但实际性能将受到网络文件共享协议和硬件的网络性能的限制。

其他部署者影响

开发人员影响

升级影响

将引入一个新的计算服务版本和能力特征,以确保计算服务和基础 virt 堆栈足够新,才能在接受请求之前通过 virtio-fs 附加共享。

实现

负责人

主要负责人

uggla (rene.ribaud)

其他贡献者

lyarwood(初始贡献者)

功能联络人

功能联络人

uggla

工作项

  • 在 os-traits 中添加新的能力特征

  • 添加 libvirt 驱动程序对冷附加和分离的支持

  • 添加新的共享 API 和微版本

依赖项

测试

  • 功能 libvirt 驱动程序和 API 测试

  • 集成 Tempest 测试

文档影响

将提供详细的管理员和用户文档。

参考资料

历史

修订

发布名称

描述

瑜伽

引入

Zed

重新提出

Antelope

重新提出

Bobcat

重新提出