Fuel/外部快照
目录
外部快照
我们根据 libvirt 文档,将外部快照视为外部形式的“系统检查点”类型快照 https://libvirt.org/formatsnapshot.html#SnapshotAttributes。
什么是外部快照?
外部快照是外部形式的两种类型快照的组合
- 磁盘快照 - 包含磁盘内容
- 内存(或虚拟机)状态 - 仅跟踪 RAM 和虚拟机使用的所有其他资源的状态
外部形式意味着快照不是创建在一个文件中,而是创建在不同的文件中,与内部形式不同。
磁盘快照是一对文件:至少一个用于快照本身,另一个用于在创建快照后写入更改(快照文件 - 是此文件的备份存储)。
在外部形式下,内存状态也是一个单独的文件。
外部快照中的卷链
在使用外部快照时,必须考虑一个特性:磁盘的多个连续外部快照会创建一个卷链。每个后续快照都是与前一个快照以及前一个快照相关的所有卷的“增量”。依此类推,直到基本卷。这是由于磁盘外部快照的设计所致。
Fuel 系统测试环境中的外部快照
外部快照支持已添加到 fuel-devops 应用程序。
要在 fuel-devops 中开始使用外部快照,只需定义 SNAPSHOTS_EXTERNAL 环境变量并将其值设置为“true”。
export SNAPSHOTS_EXTERNAL=true
它是如何工作的?
Fuel-devops 对环境中的每个节点执行以下步骤:
创建快照
- 创建一个卷,并将当前设置的磁盘作为备份存储以保存快照后的更改(为连接到虚拟机的每个磁盘创建)。
这样做是为了在 fuel-devops 数据库中拥有新的卷,以便将来能够控制该卷。 - 定义内存状态文件的路径
- 使用 snapshot libvirt 功能从生成的 XML 定义创建快照
- 将快照重新定义为当前快照
将虚拟机恢复到快照状态
- 销毁节点
- 选择在虚拟机恢复后使用的卷
- 如果它是链中的最新快照,将使用相同的卷(重新创建卷)。
- 否则将创建新卷
- 使用 restore libvirt 功能启动虚拟机
已知问题
事实证明,在使用 host-passthrough cpu 模式时无法创建外部快照。原因如下:
- virDomainSnapshotGetXMLDesc 函数不会在快照 XML 定义中返回 cpu 模型
- libvirt 禁止在修改快照定义期间更改 cpu 模型
需要完整的快照 XML 定义才能将快照重新定义为当前快照。为了避免此问题,已实现从域定义获取 cpu 模型并将其注入快照定义的功能。 另外,作为一种解决方法,可以在创建环境之前通过将 DRIVER_USE_HOST_CPU 变量设置为 false 来禁用 host-passthrough 模式。
export DRIVER_USE_HOST_CPU=false
未来外部快照的使用计划
导出和导入环境
假设我们有有限数量的节点(例如 Jenkins 从节点),可以在这些节点上执行部署测试。如果测试失败,则需要禁用发生故障的节点,以便能够执行根本原因分析。这会导致资源稀缺并降低 CI 环境的整体性能。在这种情况下,最好能够将环境从一个节点(我们称之为 源节点,例如 Jenkins 从节点)导出到另一个节点(目标节点,例如用于故障排除和分析的备份节点)。这样可以使节点从失败的环境中释放出来,并将其返回到 CI 环境。
由于此任务不简单,首先考虑目标节点用于导入环境是空的,即 libvirt 环境中不包含任何节点、项目等。
系统测试环境由以下部分组成:
- fuel-devops DB 中的记录(以便能够使用 libvirt 对象)
- Libvirt 环境(域、网络、卷、快照等)
目前,导出和导入 systest 环境的步骤已实现为 shell 脚本。
导出环境
NOTE: Steps 7 - 9 are implemented in a separate script as it needs root privileges to run.
这里有一系列导出环境的步骤(使用 libvirt virsh 和 psql)::
- 从 fuel-devops DB 导出记录(psql -c '\copy ...')
- 转储存储池定义(pool-dumpxml)
- 转储网络定义(net-dumpxml)
- 转储卷定义(vol-dumpxml)
- 转储域定义(dumpxml)
- 下载卷(vol-download)。它在当前使用的 libvirt 1.2.12 中表现出较差的性能。相关错误:(https://bugzilla.redhat.com/show_bug.cgi?id=1026136 https://bugzilla.redhat.com/show_bug.cgi?id=1026137)。因此,我们需要升级 libvirt 或实现直接复制卷(移动到单独的脚本,如 7-9 步中所做)。
- 转储快照定义。目前使用直接复制,因为实现起来更容易,因为snapshot-dumpxml 返回的 XML 文件在 cpu 模式为“host-passthrough”时(默认设置)没有 cpu 模型,也没有 libvirt 需要的 <active/> 标签。
- 将
<active>1</active>设置为将设置为当前快照的 XML 定义(要导出的快照列表中的第一个),并将<active>0</active>设置为所有其他快照定义 - 复制内存状态文件(用于快照)
导入环境
NOTE:There're 2 ways to import snapshots: 1. Replay snapshots, i.e. create snapshots in the same order as it was done on the source node
and then redefine ones using exported definitions 2. Add snapshots definitions to /var/lib/libvirt/qemu/snapshot/<domain> directory
第一种方法比较复杂,因为在许多快照和复杂的快照创建方案的情况下,有很多步骤需要执行。此外,还需要考虑到所有“重放”的快照必须与源快照的状态相同。
第二种方法要容易得多,因为它只需要将快照定义放入 libvirt 快照目录并将内存状态文件复制到与源节点上相同目录即可。为此,我们需要 root 权限。
目前已实现第二种方法。
这里有一系列导入环境的步骤(使用 libvirt virsh)::
- 将记录导入到 fuel-devops DB(psql -c '\copy ...')
- 从定义创建存储池并自动启动它(pool-define、pool-start、pool-autostart)
- 从定义创建网络并自动启动网络(net-define、net-start、net-autostart)
- 从定义创建卷(vol-create)
- 将内容从导出的文件上传到卷(vol-upload)
- 从定义创建域(define)
- 将内存状态文件放置到与源节点上相同路径
- 将快照 XML 定义复制到 /var/lib/libvirt/qemu/snapshot/<domain> 目录
- 重新启动 libvirt 守护程序