02月21, 2017

nova rescue、evacuate、 shelve 功能分析

nova的rescue、evacuate、 shelve 功能是为了应对虚拟机的异常情况和提高资源利用率而生的,今天我们来分下一下它们各自的功能。

nova resuce

官方文档: https://wiki.openstack.org/wiki/RescueMode

功能介绍: 在 OpenStack 环境下的 KVM 虚拟机文件系统损坏或密码忘记后,可以使用rescue功能修复文件系统并找回数据。

就像我们笔记本/物理机文件系统损坏或者密码忘记后,可以使用 ilo/idrac 挂载 iso 镜像进入 linux rescue mode 对文件系统进行修复原理一样。openstack 虚拟机也可以使用rescue功能修复。

适用的几种场景:

  • Damage to the boot loader or partition table on a computer's hard drive that prevents it from booting properly.
  • Loss of critical system files that results in a system that won't boot properly.
  • Corruption to the (physical) file system that requires manual intervention to repair.
  • Loss of the administrator credentials; e.g. the root password or SSH private keys.
  • Suspicion that booting up the system normally may damage things; e.g. destroy files to remove evidence.

resuce工作流程:

  1. 保存目前domain 的 xml 配置为 unrescue.xml 文件。

  2. 根据 image 重新生成启动盘 disk.swap (大小不受 falvor.root_disk_size 控制,尽可能小的一个文件)

  3. 构造一个新的 domain 的 xml 配置,使用 disk.rescue 做启动盘,将原来的 disk 挂载到该 domain,只挂系统盘,其他的盘和volume不会被挂载

    <disk type="file" device="disk">
    <driver name="qemu" type="qcow2" cache="none"/>
    <source file="/var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd/disk.rescue"/> #新构造的启动盘
    <target bus="virtio" dev="vda"/>
    </disk>
    <disk type="file" device="disk">
    <driver name="qemu" type="qcow2" cache="none"/>
    <source file="/var/lib/nova/instances/8352e969-0a25-4abf-978f-d9d0ec4de0cd/disk"/> #原来的启动盘
    <target bus="virtio" dev="vdb"/>
    </disk>
    
  4. 将原来的 domain destroy 掉 (virt_dom.destroy)

  5. 定义新的 domain (conn.defineXML(xml))

  6. 启动新的 domain (domain.createWithFlags)

至此,nova rescue 的过程完成。用户可以 ssh 到新的虚机,修改 “Vdb“分区中的受损害的文件。然后执行 ”nova unrescue“命令。其主要过程是:

  1. 读取之前保存的 unrescue.xml 文件
  2. 将 rescued domain destroy 掉
  3. 定义和启动新的domain(同上面5和6)
  4. 删除 unrescue.xml 文件

注意,这时候文件夹中的 libvirt.xml 文件和新运行的 domain 的 xml 不一致,因为代码中没有将新的 domain 的xml 写到该文件。

rescue 是一种修复虚拟机无法启动或者密码丢失后重置密码的方法,它将旧虚拟机的系统盘挂载到新启动的虚拟机上作为数据盘进行处理。同我们直接将虚拟机的磁盘挂载到某个目录是一样的。

nova evacuate

官方地址:https://wiki.openstack.org/wiki/Evacuate 功能介绍:当一个计算节点 down 掉后,在新的 计算节点 上根据其 DB 中保存的信息重新创建虚机。这个往往在虚机 HA 方案中用到。它尽可能地将原来的虚机在新的主机上恢复:

  • 虚机的配置:从 DB 中获取,包括 image,block,network 等
  • 虚机的数据:如果使用共享存储,则使用共享存储上的虚机数据;如果不使用共享存储,则无法恢复数据
  • 内存状态:无法恢复

因此,HA 方案中,应该尽可能地将虚机的数据文件放在共享存储上,否则,恢复出来的虚机的价值非常有限。

Nova CLI:usage: nova evacuate [--password <password>] [--on-shared-storage] <server> [<host>]

要求:

  1. 必须指定和虚机的 host 不同的 host,否则将报错“The target host can't be the same one”。
  2. 虚机的host 必须处于不可用状态,否则将报错 “Compute service of compute2 is still in use.”
  3. 可以指定新的 admin password,不指定的话,nova 将生成一个随机密码
  4. 参数 on-shared-storage 表示虚机的 instance folder 是不是在共享存储上。

主要流程: (1) 在做完以上各种参数检查后,调用 Conductor 的 方法:

return self.compute_task_api.rebuild_instance(context, instance=instance, new_pass=admin_password,
                                                                           injected_files=None, image_ref=None,
                                                                           orig_image_ref=None, orig_sys_metadata=None,
                                                                           bdms=None, recreate=True, on_shared_storage=on_shared_storage, host=host)

如果 host 为none 的话,conductor 将调用 scheduler 的方法选择一个 host。

(2) 接着调用 nova compute 的 rebuild_instance 方法。该方法从系统(DB)中获取已有的数据,然后根据这些已有的 metadata 重新构造domain。

“A 'rebuild' effectively purges all existing data from the system and remakes the VM with given 'metadata' and 'personalities'.”

  • 获取 image_ref,再获取 image meta
  • 获取 network_info 并在新的 host 上构造网络
  • 获取 BlockDeviceMappingList
  • 获取 block_device_info

(3) 然后调用 virt driver 的 rebuild 方法,但是 libvirt 没有实现该方法,转而调用 _rebuild_default_impl 方法。该方法:

从 volume 端断开其与原来 host 的连接 调用 driver.spawn 方法构造新的 domain,依次创建 image(如果 on_shared_storage = false 的话,则重新下载 image, 构造 instance folder。)

如果 on_shared_storage = true 的话,则直接使用共享存储上的 instance folder。这也可见使用共享存储的优势),network 和 domain,并设置 domain 的状态和之前一致。

(4) 在坏了的 host 被重启后,nova-compute 服务调用 _destroy_evacuated_instances 方法来找到 evacuated instances 并将它们删除:

调用 libvirt 找到该 host 上所有 domains,然后在 nova db 中一一查找其状态,过滤出 “deleted” 为 false 的 domains。

如果instance.host 不是本机,而且 instance.task_state 不是 { MIGRATING,RESIZE_MIGRATING,RESIZE_MIGRATED,RESIZE_FINISH} 之一,则删除该 domain,以及 network,block device 以及 instance folder。

总之,在使用共享存储的情况下,evacuate 出来的新的 domain 除了临时盘上的数据外,它和之前的 domain 的数据是一样的了,但是内存状态除外。

但evacuate也有一些不足,比如同rebuild一样,目前evacuate仅支持active和stopped状态的虚拟机,其他状态(paused,suspended等)的虚拟机是不支持的,这也就意味着其他状态的虚拟机遇到host故障的时候是无法恢复的。

顺带说一句,目前只有libvirt driver支持rebuild和evacuate。

nova shelve

功能介绍:将长时间不使用的VM从底层释放,从而节约服务器资源。用户要使用时可再次恢复。

现状

  • 用户对暂时不使用的VM进行停止操作,以节省费用。
  • 对于长时间未使用的VM,管理员想要从hypervisor层面上清除它们从而节省主机资源。
  • 但之前的停止VM,VM仍旧会占用hypervisor上的资源,并且还需要在主机上占用CPU/内存配额来保证重启动的成功。
  • 以上问题当然也可以通过先做一个快照镜像并且重创VM来解决,但是它会重新分配一个IP,并且之前的VM仍旧存在,而快照、IP资源也同样会计费。

使用场景: 周末关机、用户休假、长时间不使用VM等。

当一个虚机不需要使用的时候,可以将其 shelve 起来。该操作会创建该虚机的一个快照并传到 Glance 中,然后在 Hypervisor 上将该虚机删除,从而释放其资源。

其主要过程为:

  1. destroy 虚机 (virt_dom.destroy())
  2. snapshot 该 domain
  3. 如果 CONF.shelved_offload_time == 0 的话,将domain 的各种资源(interface,volume,实例文件等),然后将其undefine (virt_dom.undefine())

其只存在于数据库和 Glance 中。运行 nova list 能看到一条记录:

| 8352e969-0a25-4abf-978f-d9d0ec4de0cd | vm11               | SHELVED_OFFLOADED | -          | Shutdown    | demo-net2=10.0.10.14; demo-net=10.0.0.41 |

运行 glance image-list 能看到其image:

| 6ed6eb92-ce42-46d1-ab46-259e3e235304 | vm11-shelved   | qcow2       | bare             | 19988480 | active |

能看到该 image 的 instance 相关的属性:

s1@controller:~$ glance image-show 6ed6eb92-ce42-46d1-ab46-259e3e235304
+---------------------------------------+--------------------------------------+
| Property                              | Value                                |
+---------------------------------------+--------------------------------------+
| Property 'base_image_ref'             | bb9318db-5554-4857-a309-268c6653b9ff |
| Property 'image_location'             | snapshot                             |
| Property 'image_state'                | available                            |
| Property 'image_type'                 | snapshot                             |
| Property 'instance_type_ephemeral_gb' | 1                                    |
| Property 'instance_type_flavorid'     | 129f237e-8825-49fa-b489-0e41fb06b70e |
| Property 'instance_type_id'           | 8                                    |
| Property 'instance_type_memory_mb'    | 50                                   |
| Property 'instance_type_name'         | tiny2                                |
| Property 'instance_type_root_gb'      | 1                                    |
| Property 'instance_type_rxtx_factor'  | 1.0                                  |
| Property 'instance_type_swap'         | 30                                   |
| Property 'instance_type_vcpus'        | 1                                    |
| Property 'instance_uuid'              | 8352e969-0a25-4abf-978f-d9d0ec4de0cd |
| Property 'network_allocated'          | True                                 |
| Property 'owner_id'                   | 74c8ada23a3449f888d9e19b76d13aab     |
| Property 'user_id'                    | bcd37e6272184f34993b4d7686ca4479     |

Unshelve 是 shelve 的反操作。它的主要过程是:

  1. 从 DB 中获取 network_info 和 block_device_info
  2. 从 Glance 中获取 image
  3. 像新建一个虚拟那样 spawn 新的虚机
  4. 调用 image API 将 image 删除

本文链接:https://www.opsdev.cn/post/nova-rescue-exacuate-shelve.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。