使用 libvirt 存储池¶
https://blueprints.launchpad.net/nova/+spec/use-libvirt-storage-pools
目前,libvirt 驱动程序没有利用 libvirt 的存储池和卷。使用 libvirt 存储池将简化对新的镜像后端支持的添加,并促进冷迁移(参见后续蓝图)。
问题描述¶
目前,Nova 的 libvirt 驱动程序不使用 libvirt 卷和存储池。
这意味着,对于镜像后端,我们有很多代码直接处理各种镜像后端格式,并且我们必须通过各种命令行工具和库手动处理各种不同的情况。
然而,这些功能中的很多已经存在于 libvirt 中,以 libvirt 存储池的形式存在,因此 libvirt 驱动程序重复了 libvirt 本身已经存在的功能。
提议的变更¶
从 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 中的目标镜像。
如果我们使用 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”等,具体取决于传递给镜像创建方法的名称)。 这样,仍然可以轻松找到与特定实例关联的磁盘镜像。
使用此新后端将成为新安装的默认设置。 但是,旧后端将保留在原位以维护实时升级功能(例如,Icehouse->Juno)。 请参阅下面的 其他部署者影响 部分,了解更多信息。
对于在实例创建时提供给 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 Icehouse 迁移/升级到 OpenStack Juno,旧的镜像后端(以及 Nova 镜像缓存中对它们的的支持)将在下一个版本(Juno)中保留,但将被标记为已弃用。 在 K 版本中,旧后端将被删除(以及对镜像缓存管理器中对它们的的支持)。
为了允许现有的安装轻松过渡到新的后端,现有的实例将保留在旧后端上,而所有新的实例都将创建为使用新的后端。 可以通过检查实例目录中是否存在镜像来确定实例是否正在使用旧后端(如果存在,则实例正在使用旧后端,如果不存在,则实例正在使用新的后端)。
在允许更改 libvirt XML 的操作期间,例如冷迁移、调整大小、重新启动和实时迁移,实例将自动过渡到使用新的系统 [5]。 这将允许部署者根据自己的意愿迁移到新系统,因为他们可以选择批量重新启动 VM,或者简单地要求 VM 所有者在方便时执行此操作。 对于仍然使用旧系统的实例,将在计算节点启动时发出警告。
这将涉及告诉 libvirt 使用卷作为磁盘源。 在使用共享存储的实时迁移、相同主机的调整大小和重新启动的情况下,将采取一些额外的步骤,用于使用基于本地文件的旧后端。 对于重新启动和调整大小,我们只需在 VM 关闭时将磁盘镜像文件移动到目录池位置。 在支持硬链接的共享存储的情况下,将指向磁盘镜像文件的硬链接放置在存储池目录中。 一旦实时迁移完成,原始位置将被删除,只留下新的硬链接作为对磁盘镜像文件的唯一剩余引用。 对于不支持硬链接的文件系统,需要进行块实时迁移才能将 VM 迁移到新的镜像后端。
开发人员影响¶
目前,特定实例的基于文件的镜像存储在实例目录中 (/var/lib/nova/instances/{instance-id})。 为了在每个计算节点上有一个存储池,libvirt 的基于目录的存储池需要将所有磁盘镜像存储在一个目录中,因此镜像本身将不再位于 /var/lib/nova/instances/{instance-id} 中,而是位于类似 /var/lib/nova/instance/disks 的位置中。
如果希望将不同的磁盘类型(例如,主磁盘与交换磁盘)存储在不同的位置 [6],我们可以简单地为每种类型创建一个池,并将镜像放置到基于其名称的适当池中。 使用池的优势在于 Nova 实际上不需要了解池的基础细节,而只需要它的名称。 因此,如果部署者想要将特定的池移动到不同的位置、设备等,则无需更改 XML,只要保留相同的池名称即可。
如 此蓝图 建议,例如
实现¶
负责人¶
- 主要负责人
sross-7
- 其他贡献者
无
工作项¶
修改从 Glance 下载镜像到缓存的代码,以在缓存目录中创建一个存储池,并在下载新镜像时刷新缓存。
实现新的镜像后端(并在 RBD 本机不支持时对其进行子类化,如 [1] 所述),以及 XML 配置生成器中的部分,以接受磁盘元素的
volume类型。实现支持过渡安装所需的功能(检测旧后端使用情况,在迁移和重新启动中添加代码以过渡到新的后端使用情况)。
在镜像缓存管理器中实现功能,以利用 libvirt 卷信息 XML 中存储的新 backing 文件数据(除非在 Juno 中将
images_type设置为“libvirt-storage”,这意味着部署者不希望使用上述过渡功能),这将禁用此功能。
依赖项¶
此更改不需要新的库。 但是,上述 XML 更改需要 libvirt 版本 > 1.0.5(实际的存储池不需要,但是)。 虽然这并非严格必需的(因为我们可以简单地使用现有代码来确定给定镜像的正确 XML),但它简化了负责 XML 生成的代码部分。 但是,由于我们很可能将在 Juno 中增加最低 libvirt 版本,因此这不应该成为问题。
测试¶
我们将要复制现有后端各种镜像的现有测试,以确保新的后端涵盖所有现有功能。 此外,应引入新的测试,用于
XML 更改
存储池管理
将现有实例迁移到新的后端以及支持的过渡功能
文档影响¶
我们应该警告旧镜像后端已弃用,并注意新后端。 还应注意的是,迁移和冷调整大小是首选的将现有实例迁移到新后端的方法。