使用 libvirt 存储池

https://blueprints.launchpad.net/nova/+spec/use-libvirt-storage-pools

目前,libvirt 驱动程序没有利用 libvirt 的存储池和卷。使用 libvirt 存储池将简化对新的镜像后端支持的添加,并促进冷迁移(参见后续蓝图)。

问题描述

目前,Nova 的 libvirt 驱动程序不使用 libvirt 卷和存储池。

这意味着,对于镜像后端,我们有很多代码直接处理各种镜像后端格式,并且我们必须通过各种命令行工具和库手动处理各种不同的情况。

然而,这些功能中的很多已经存在于 libvirt 中,以 libvirt 存储池的形式存在,因此 libvirt 驱动程序重复了 libvirt 本身已经存在的功能。

用例

开发者:这将有助于从resize/migrate中移除SSH,因为它将允许我们使用virStorageVolUpload和virStorageVolDownload来迁移存储。

开发者:其次,这将简化对libvirt支持但Nova不支持的池类型(例如Sheepdog)的支持。

开发者:从长远来看,这将简化imagebackend代码,使其更易于维护。

项目优先级

提议的变更

从Glance下载的镜像缓存将被放置到卷池中(nova-base-images-pool)。这只需指示libvirt Nova的镜像缓存目录(例如/var/lib/nova/_base)是一个目录存储池,因此不会影响目录布局(因此与旧版镜像后端和下面提出的新镜像后端兼容)。

将引入一个新的镜像后端,LibvirtStorage。 这将支持代替所有当前类型(RBD 支持除外,目前需要一个子类 [1])。

如果我们不使用COW,可以使用libvirt的pool.createXMLFrom方法,将模板镜像从源池nova-base-images-pool正确复制到目标池nova-disks-pool中的目标镜像。无论源和目标格式如何,这都有效(例如,用于从raw复制到LVM或从qcow2复制到raw的函数调用相同)。

如果我们使用 COW,可以使用带有 backingStore 元素的 libvirt pool.createXML 方法,这将适当地创建新的 QCOW2 文件,并将 backing 文件作为镜像缓存中的文件。

这还有额外的优势,为简化镜像缓存管理器铺平了道路——不必运行外部可执行文件来检查镜像是否处于 qcow2 格式并具有 backing store,我们可以简单地检查每个 libvirt 卷的 backingStore 元素的 path 子元素(这也使代码更具弹性,如果我们决定支持具有 backing store 的其他格式)[2]

可以使用类似的方法与extract_snapshot一起使用——使用createXMLFrom将libvirt卷(我们传入的新XML可以处理压缩等)复制到临时目录池。

为了将镜像与实例关联,nova-disks-pool中的卷将具有{instance-uuid}_{name}形式的名称(其中name为“disk”、“kernel”等,具体取决于传递给镜像创建方法的名称)。这样,仍然可以轻松找到与特定实例关联的磁盘镜像。这是旧版LVM和RBD后端使用的相同名称格式。

一个名为[libvirt]use_storage_pools的配置变量将启用或禁用存储池功能,并且默认设置为true。但是,旧版后端将保留在原位以维护实时升级功能(例如Juno->Kilo)。有关更多信息,请参阅下面的其他部署器影响部分。

对于在实例创建时提供给 libvirt 的 domain 元素中的 disk XML 元素,可以提供类型为 volume 的元素,并且 <source> 元素指定池名称和卷名称 [3]

备选方案

本文档中描述的设置要求在系统上的所有 VM 使用单个存储池。

在使用基于文件的后端时,这将需要在单个目录中存储磁盘镜像(例如 /var/lib/nova/instance/disks),而不是当前设置,其中磁盘镜像存储在实例目录中 (/var/lib/nova/instances/{instance-id})。 这是由于 libvirt dir 存储池的工作方式所致。

虽然可以为每个实例创建一个新的存储池,但这仅适用于基于文件的后端。 在基于文件和其它后端之间存在不同的功能将使代码复杂化并降低此蓝图引入的抽象性。

数据模型影响

无。

REST API 影响

无。

安全影响

无。

通知影响

无。

其他最终用户影响

无。

性能影响

由于 createXMLFrom 实际上可以智能地创建和复制镜像文件(例如,在适当的时候在后台调用 qemu-img),因此不应有性能影响。 如 Proposed change 部分所述,我们将维护当前的镜像缓存功能,包括对 COW(通过 QCOW2)的支持,同时为 libvirt 支持的其他文件格式铺平道路。

其他部署者影响

对于从OpenStack Juno到OpenStack Kilo的实时迁移/升级,旧版镜像后端(以及Nova的镜像缓存中对它们的支持)将在下一个版本(Kilo)中保留,但将被标记为已弃用。在L版本中,旧版后端将被删除(以及对镜像缓存管理器中对它们的支持)。

当部署器启用[libvirt]use_storage_pools配置选项时,将产生几种影响

首先,Nova将检查nova-image-cache-poolnova-disks-pool是否已经存在。如果不存在,则将nova-image-cache-pool存储池作为当前镜像缓存目录中的目录池创建。然后,Nova将检查当前镜像类型并尝试使用现有信息来创建nova-disks-pool存储池。自动创建主存储池是一种临时措施,用于协助过渡过程;最终(在L之后),这将删除,因为旧版后端配置选项也将删除。这减轻了Nova与各种存储后端交互的负担——Nova不再需要为它支持的每个存储后端都拥有大量的配置选项。

其次,所有新实例都将使用存储池镜像后端创建。任何当前正在运行的实例将继续使用旧版镜像后端。

在允许更改libvirt XML的操作期间,例如冷迁移、调整大小、重新启动和实时迁移[4],实例将自动过渡到使用新系统。这将允许部署者和用户根据自己的意愿迁移到新系统,因为他们可以选择批量重新启动虚拟机,或者简单地要求用户在方便时执行此操作。对于仍然使用旧系统的实例,将在计算节点启动时发出警告。

对于“冷”操作(调整大小、重新启动和冷迁移),磁盘镜像将在虚拟机(重新)启动之前移动到存储池中。对于非目录型后端(LVM和RBD),无需移动,因为名称格式相同,并且它们本质上已经使用集中位置。

然后,当Nova生成新的XML来启动VM时,XML将指向libvirt存储卷(在软重新启动的情况下,我们将简单地更新现有的XML)。

对于实时块迁移,我们只需在存储池中创建一个新的空镜像,并让libvirt在块迁移期间填充它。对于共享存储实时迁移,我们只能在镜像后端是Ceph时进行过渡,因为在VM仍在运行时将磁盘文件移动到存储池中而不会丢失数据,没有可靠的方法。

开发人员影响

目前,特定实例的基于文件的镜像存储在实例目录中 (/var/lib/nova/instances/{instance-id})。 为了在每个计算节点上有一个存储池,libvirt 的基于目录的存储池需要将所有磁盘镜像存储在一个目录中,因此镜像本身将不再位于 /var/lib/nova/instances/{instance-id} 中,而是位于类似 /var/lib/nova/instance/disks 的位置中。

如果希望以不同的方式存储不同的磁盘类型(例如,主磁盘与交换磁盘),我们可以简单地为每种类型创建一个池,并将镜像放置到基于其名称的适当池中。使用池的一个优点是Nova实际上不需要知道池的基础细节,只需要它的名称。因此,如果部署者想要将特定池移动到不同的位置、设备等,则无需更改XML,只要保持相同的池名称即可。

针对特定后端类型(例如LVM加密)的代码仍然是可能的,因为我们可以询问libvirt存储池类型。

实现

负责人

主要负责人

sross-7

其他贡献者

工作项

  1. 修改从 Glance 下载镜像到缓存的代码,以在缓存目录中创建一个存储池,并在下载新镜像时刷新缓存。

  2. 实现新的镜像后端和XML配置生成器中的部分,以接受磁盘元素的volume类型,并使镜像缓存管理器了解如何检查libvirt存储卷以获取backing stores。

  3. 实现支持过渡安装所需的功能(检测旧后端使用情况,在迁移和重新启动中添加代码以过渡到新的后端使用情况)。

  4. 为RBD支持创建新的镜像后端子类,以便它可以与新的镜像后端一起使用。

依赖项

测试

我们将要复制现有后端各种镜像的现有测试,以确保新的后端涵盖所有现有功能。 此外,应引入新的测试,用于

  • XML 更改

  • 存储池管理

  • 将现有实例迁移到新的后端以及支持的过渡功能

文档影响

我们应该警告旧镜像后端已弃用,并注意新后端。 还应注意的是,迁移和冷调整大小是首选的将现有实例迁移到新后端的方法。

参考资料