通用镜像缓存功能¶
https://blueprints.launchpad.net/cinder/+spec/image-volume-cache
目前,一些卷驱动程序实现了 clone_image 方法,并使用后端内部缓存来存储最近使用的镜像卷。对于可以执行非常高效的卷克隆的存储后端,这比为每个卷附加和复制镜像内容可以带来显著的性能提升。为了使其他卷驱动程序更容易地使用此功能,并防止代码库中的任何重复,我们应该实现一种更统一的方法来执行此缓存。
问题描述¶
如果我们不创建一种统一的镜像缓存方法,最终将会有多个供应商在卷驱动程序中实现它。这意味着重复的代码、冗余的供应商前缀配置选项,以及管理员设置和配置镜像缓存的非统一方式。
用例¶
此功能的主要(我认为唯一)用例是在从镜像创建卷多次时。作为最终用户,我可能会看到(可能)更快的卷创建速度,第一次之后从镜像创建卷的速度会更快,并且作为管理员,一旦在后端配置中设置好,就不再需要进行任何交互。
提议的变更¶
在使用缓存从镜像创建卷时,需要执行几个高级步骤
检查镜像是否在缓存中存在相应的条目。
如果它在缓存中但已被更新,则删除它。
- 如果它不在缓存中(或者不再存在)
如果需要空间,则驱逐旧的镜像条目。
从镜像创建卷(“正常”方式复制数据),此卷将被称为“镜像卷”。该卷将由 Cinder 控制的特殊租户拥有。
更新缓存以了解这个新的镜像卷及其镜像内容。
克隆镜像卷。
这个新行为将通过一个新的卷驱动程序配置选项 ‘image_volume_cache_enabled’ 来启用。然后,此缓存的大小将由几个新的配置选项定义
image_volume_cache_max_size_gb
image_volume_cache_max_size_percent
image_volume_cache_max_count
这些选项作用于每个后端。
在 CreateVolumeFromSpecTask 的 _create_from_image 中,我们可以添加逻辑来首先检查镜像缓存是否为目标后端启用。如果是,则可以使用缓存,否则仅使用慢速路径。这将是在调用 driver.clone_image 之后完成的,以便为后端提供机会,如果可能的话,执行更优化的克隆。
对于实际的镜像卷,我认为最好能够重用正常的 Cinder 卷模型和数据库表。理想情况下,我们可以利用 cinder-internal 租户功能,以便特殊租户拥有这些缓存的镜像。
然后,我们需要一个新的表来跟踪我们的镜像缓存。该表将包含卷、镜像和主机 ID,以及镜像元数据,以便做出它是否仍然“有效”的决定。更多细节请参见数据模型影响部分。
这些信息足以让我们查找镜像是否在目标后端的缓存中,并决定是创建一个新的镜像还是使用 _create_from_source_volume 和镜像卷。
对于卷驱动程序而言,它将创建从镜像创建的卷和克隆卷,它不需要了解缓存,对于创建方法而言。
对于需要使用快照的任何后端,它们将不得不从镜像卷 -> 快照 -> 卷 转换。将来,此镜像缓存表始终可以扩展为除了卷 ID 之外,还包含 snapshot_id,但对于第一次迭代,它将仅处理作为缓存后端的卷。
缓存中可能存在竞争条件,即镜像卷正在被驱逐,并且被选中用于克隆操作。如果发生这种情况,我们应该捕获错误并尝试通过下载镜像来创建卷。同时,也可能缓存了多个相同的镜像,这被认为是“可以接受的”,如果需要空间,额外的镜像最终将被驱逐。
在未来的迭代中,我们可以将缓存中的对象作为公共快照公开,并以与缓存对象相同的方式存储其他公共快照的后端卷。这应该允许代码中大量重用,并为用户提供另一种快速复制卷的方式,用于具有优化的快照 -> 卷和卷 -> 卷操作的后端。在第一次迭代中,此功能将不会提供。值得注意的是,我们可以确保实现具有可扩展性,以便将来允许它。
备选方案¶
一个非常简单的替代方案是简单地将所有这些逻辑和行为推送到每个卷驱动程序中,并忍受重复的代码和配置选项。但是,这会禁止后端无法在其卷的任何地方存储元数据。
另一种替代方案是不使用实际的卷对象,而是扩展镜像缓存表以包含后端创建卷和克隆所需的信息(也许是元数据类型值?)。然后,我们可以向卷驱动程序添加新的 API,例如 ‘create_cached_image_volume’、‘delete_cached_image_volume’、‘create_volume_from_cached_image’ 等。这将把更多的逻辑放入卷驱动程序中,但需要它们实现这些新方法。这里的优点是,我们不会开始拥有特殊的“内部”卷。缺点是每个驱动程序都需要实现所有这些方法,这些方法将执行与 create_volume、delete_volume 等几乎相同的事情,但参数不同。
数据模型影响¶
用于镜像缓存的新数据库表。
+------------+-----------+--------------------------------+
| NAME | TYPE | DESCRIPTION |
+------------+-----------+--------------------------------+
| | | |
| id | String | Auto generated UUID |
| | | |
| updated_at | DateTime | The updated_at time from the |
| | | image metadata |
| | | |
| host_id | String | ForeignKey for Host.id that |
| | | has the backing volume |
| | | |
| volume_id | String | ForeignKey for Volume.id of |
| | | the backing volume |
| | | |
| image_id | String | The image id from the image |
| | | metadata |
+------------+-----------+--------------------------------+
REST API 影响¶
无
安全影响¶
特殊的 Cinder 拥有的租户可能存在风险,如果有人能够获取其凭据或访问镜像卷。最坏的情况是,如果他们有权附加和直接写入镜像卷,他们可能会更改缓存的镜像卷。
必须小心确保它不能被普通用户访问。
通知影响¶
新的信息日志消息和事件通知,用于指示缓存命中或未命中。这样才能获得足够的信息来确定其有效性以及是否需要调整设置。
其他最终用户影响¶
无
性能影响¶
对于可以执行高效卷克隆的系统,在从镜像创建卷时,平均而言应该可以提高性能。具体改进程度取决于许多因素,但不太可能变慢。
这可能会在偶尔的请求中增加一些延迟,这些请求会遇到“最坏情况”场景,即必须执行数据库查找、尝试从缓存的镜像创建、由于被驱逐而失败,然后下载镜像。在这些情况频繁发生时,可以修改缓存大小或禁用该功能。
其他部署者影响¶
Cinder 后端的新配置选项,可能需要设置
image_volume_cache_enabled (布尔值)
image_volume_cache_max_size_gb (整数)
image_volume_cache_max_size_percent (整数)
image_volume_cache_max_count (整数)
开发人员影响¶
只需要了解新的 DB API 和表。
实现¶
负责人¶
- 主要负责人
patrick-east
- 其他贡献者
无
工作项¶
DB 变更
create_volume 流变更
依赖项¶
无
测试¶
DB 迁移测试
DB API 的单元测试
流程变更的单元测试
文档影响¶
新的配置选项。