随笔-168  评论-683  文章-48 

[译] libvirt 虚机的生命周期 (Libvirt Virtual Machine Lifecycle)

翻译自:http://wiki.libvirt.org/page/VM_lifecycle
 
这篇文章描述虚机生命周期的基本概念。其目的在于在一篇文章中提供完整的关于虚机创建、运行、停止、迁移和删除的基础知识。

1. 概念

先补充一下 Domain(域)、Virutal Machine(虚机)和 Guest OS (客户机操作系统)三个术语的区别。这三个概念经常被相互使用,其实它们之间还是有些区别。

Oracel 的解释 (资料来源):

  • Domain:资源的一个可配置集合,包括内存,虚拟CPU,网络设备和磁盘设备。在 Domain 中运行(多个)虚拟机。一个 Domain 被分配虚拟资源,可以独立地被启动、停止和重启。
  • Guest OS:运行在 domain 中的虚拟操作系统。一个 Guest OS 可以是部分虚拟化或者硬件虚拟化的。一个 Hypervisor上可以运行多个 Guest OS。
  • VM:Guest OS + 它相关的应用软件。

libvirt 的解释 (资料来源):

一个 libvirt Domain 是一个运行在虚拟机器上的操作系统的实例,它可以指一个运行着的虚拟机,或者用于启动虚拟机的配置。

Xen 的解释(资料来源):

对 Xen 来说,一个 domain 就是指一个虚拟机,其 domain 概念如下:

好吧,这些说法还是有细微差别,下文中的 Domain 就当是虚拟机吧。其它术语:

术语
解释
Domain 域
一个运行在被虚拟化的机器上的,由 hypervisor 提供的操作系统实例
Hypervisor 虚机管理程序
一个虚拟化一个物理服务器为多个虚拟机的软件层。
Node 节点
一个物理服务器。它可能有多种类型,比如存储节点,集群节点和数据库节点等。
Storage Pool 存储池
一个存储介质的集合,比如物理硬盘驱动器的集合。一个存储池被细分为卷,卷会被分配给一个或者多个域。
Volume 卷
一个从存储池中分配出来的存储空间。一个卷可能会分配给一个或者多个域使用,并且往往被用作域内的虚拟硬盘驱动器。

1.1 XML 描述

Guest domain 是用 XML 配置来描述的。libvirt 使用 XML 文件格式来保存它的所有对象的配置,包括 domain,网络、存储和其它元素。这样,用户就可以使用任何他们喜欢使用的编辑器来编辑这些XML配置了。

比如,domain 中的设备使用 XML 元素 来表示其被分配的属性和子元素的一个示例如下:

<domain type='qemu'>
   <name>demo</name>
   ...
   <devices>
      ...
      <disk type='file' device='disk'> ... </disk>
      <disk type='file' device='cdrom'> ... </disk>
      <input type='mouse' bus='ps2'/>
      ...
   </devices>
</domain>
libvirt 使用 XPath 技术来从XML 文档中选择node。 

1.2. 过渡性 Guest Domain VS 持久性 Guest Domain

Libivrt 区分两种不同类型的 domain:短暂性的(transient )和持久性的(persistent)。

  • 短暂性 domain 只在 domain 被关机( shutdown) 或者所在的主机(host)被重启(restart)之前存在。
  • 持久性 domain 会一直存在,直到被删除。
 
无论它是什么类型,当一个 domain 被创建后,它的状态可以被保存进一个文件。之后,只要该文件存在,这个 domain 的状态就可以从无限次从该文件中被恢复( restored)。因此,即使是一个短暂性的domain,它也可以被反复地恢复。
 
创建短暂性的 domain 与创建持久性 domain 有一点不同。对持久性domain来说,它必须在其启动前定义(define)好。而短暂性虚机可以被一次性被创建和启动。操作两种类型的domain的命令也有些区别。当性domain被创建和关闭时,其需要的所有部件(比如存储、网络、设备等)都必须提前被准备好。

1.3 Domain 状态

 一个 Guest domain 可能处于的状态:
  • Undified (未定义的):这是起始状态。这时 libvirt 不会知道 domain 的任何信息,因为这时候 domain尚未被定义或者创建。
  • Defined (定义了的)/ Stopped (停止的):domain 已经被定义,但是不在运行(running)。只有持久性 domains 才能处于该状态。当一个短暂性 domain 被停止或者关机时,它就不存在了。
  • Running (运行中的):domain 被创建而且启动了,无论是短暂性domain还是持久性domain。任何处于该状态的 domain 都已经在主机的 hypervisor 中被执行了。
  • Paused (中止了的):Hypervisor 上对该 domain 的运行被挂起(suspended)了。它的状态被临时保存(比如到内存中),直到它被继续(resumed)。domain 本身不知道它处于是否被中止状态。
  • Saved (保存了的):类似中止(Paused) 状态,除了domain 的状态被保存在持久性存储比如硬盘上。处于该状态上的 domain 可以被恢复 (restored)。
 
下图描述了 domain 的状态机。方框表示状态,箭头表示使得状态变更的命令。
 
Image:Vm lifecycle graph.png
 从改图中可以看出,对持久性 domain,shtudown 命令可以将其从运行(running) 状态变为定义(defined)状态;对短暂性 domain 而言,它会从运行(running) 状态变为变为未定义(undefined) 状态。 

1.4 快照

一个快照是虚机的操作系统和它的所有应用(applications )在某个时刻的视图。在虚拟化领域,提供可以被恢复的虚机快照是个非常基本的功能。快照允许用户保存虚机在某个时刻的状态,然后在将来某个时候回滚到该状态。基本的用例包括,创建快照、安装新的应用、更新或者升级,然后回滚到之前的某个时间点。显然,在快照生成之后发生的任何操作都不会包含在快照中。一个快照不会持续更新。它只表示虚机的某个时间上的状态。 

1.5 迁移 

一个运行中的 domain 或者虚机可以被迁移到另一个主机上,只要虚机的存储是在主机之间共享的,并且目标主机的CPU能够支持虚机的CPU模式。根据类型和应用,虚机迁移可以不导致虚机上运行的服务的中断。 

Libvirt 支持多种不同的迁移模式:
  • Standard (标准模式):该模式下,一个 domain 的资源在从源主机迁移到目标主机时,它会处于被挂起(suspended)状态。迁移结束后,虚机在新的主机上继续运行。迁移所花的时间和 domain 的内存大小直接相关。
  • Live vs non-live(实时 VS 非实时模式):当使用实时迁移模式时,domain 不会被中止,它的所有服务都继续运行。一开始,目的主机上的 domain 或者虚机会处于停止状态,而且在domain的状态在网络传输的过程中,domain 在目的主机上实际上是不可见的。实时迁移和它上面所运行的应用的类型有直接关系的。当实时迁移一个 domain 时,它已经被分配的内存会被发送到目的主机,与此同时,其内存的任何改变都会被监视(watched)然后也会被发到目的主机。原主机上的 domain 会一直保持它的状态,直到两个节点上的 domain 的内存达到完全达到一致了。这时,目的主机上的 domain 变为 active 状态,原主机上的 domain 变为 passive 或者不可见状态。
  • Peer-to-peer (对等模式):该模式下,当原主机和目的主机能够直接通信。
  • Tunnelled (隧道模式) :该模式下,在原主机和目的主机之间会建立一个隧道 (tunnel),比如 SSH 隧道。两个主机之间的所有通信都会经过该隧道。
  • Direct (直接模式):该模式下,libivrt 使用 hypervisor 来发起迁移,迁移过程完全被 hypervisor 控制。这种模式下,源主机和目的主机的 hypervisor 往往是可以直接交互的(比如,原主机和目的主机上的 Xen 能够直接交互,而不需要libvirt 的干预)

迁移要求:

  • 使用路径和位置相同的共享存储
  • 两个物理主机上的 hypervisor 的版本完全相同
  • 相同的网络配置
  • 目的主机上有相同的或者更好的CPU。CPU必须来自同一生产厂家,目的主机上的 CPU flags 必须是原主机上的CPU flags 的超集。
这里有个成功迁移所需要的 checklist: here

1.6 删除 domain 时的数据安全性

 一些应用可能会存储敏感数据,这些数据必须被安全地处理。在任何文件系统中都一样,当一个虚机从一个系统中被删除的时候,只是文件系统的指针被删除。存储介质上的数据块任然存在,只是它们在文件系统中被标识为空。当然,这取决于你的文件系统。我们希望,当一个应用处理这种敏感数据的时候,这些机器必须物理上被安全保护,而且网络防护也必须是被防护的。安全在任何时候都很重要。
 

2. 任务 (Tasks)

2.1 创建一个 domain  

为了运行一个 domain,首先必须创建一个 domain。有很多方式可以创建一个 domain。
(1)这篇文章描述了使用 Virtual Machine Manager GUI 来创建一个domain。
(2)下面的代码使用 virt-install 命令来创建一个 domain:
# virt-install \
             --connect qemu:///system \
             --virt-type kvm \
             --name MyNewVM \
             --ram 512 \
             --disk path=/var/lib/libvirt/images/MyNewVM.img,size=8 \
             --vnc \
             --cdrom /var/lib/libvirt/images/Fedora-14-x86_64-Live-KDE.iso \
             --network network=default,mac=52:54:00:9c:94:3b \
             --os-variant fedora14

该命令创建一个名为 'MyNewVM' 的 domain,它有 512M 内存和8G磁盘空间,使用KVM。你可以阅读该命令的手册。 

(3)最后一种方式是创建 domain 和 卷 (volume)的 XML 定义,然后使用 virsh 的 vol-create 和 define 命令。

卷 (volume)会被加入一个池(pool)中。默认的话,一个名为  "default" 的池会存在。这是一个目录类型的池,它的意思是所有的卷都以文件形式存在于一个目录中。详细信息,你可以读  this page 。

一个卷的 XML定义例子(new_volume.xml):
<volume>
 <name>sparse.img</name>
 <capacity unit="G">10</capacity>
</volume>
它定义了一个容量为 10G 的卷。使用如下命令来在 'default' 池中创建该卷:
# virsh vol-create default new_volume.xml
Domain 的 XML 定义的例子 (MyNewVM.xml) 如下:
<domain type='kvm'>
  <name>MyNewVM</name>
  <currentMemory>524288</currentMemory>
  <memory>524288</memory>
  <uuid>30d18a08-d6d8-d5d4-f675-8c42c11d6c62</uuid>
  <os>
    <type arch='x86_64'>hvm</type>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/><apic/><pae/>
  </features>
  <clock offset="utc"/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <vcpu>1</vcpu>
  <devices>
    <emulator>/usr/bin/qemu-kvm</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/var/lib/libvirt/images/MyNewVM.img'/>
      <target dev='vda' bus='virtio'/>
    </disk>
    <disk type='block' device='cdrom'>
      <target dev='hdc' bus='ide'/>
      <readonly/>
    </disk>
    <interface type='network'>
      <source network='default'/>
      <mac address='52:54:00:9c:94:3b'/>
      <model type='virtio'/>
    </interface>
    <input type='tablet' bus='usb'/>
    <graphics type='vnc' port='-1'/>
    <console type='pty'/>
    <sound model='ac97'/>
    <video>
      <model type='cirrus'/>
    </video>
  </devices>
</domain>

定义一个持久性的domain:

# virsh define MyNewVM.xml

Domain 的 XML 格式有很多的可选元素你可能觉得有用。因此,可以阅读 this page ,它包含完整的参考。 

2.2 编辑一个 domain

 可以使用任何编辑器来编辑一个 domain。你需要设置 $VISUAL or $EDITOR 环境变量来指定编辑器,然后运行:
# virsh edit <domain>

如果这些变量都不存在,默认会使用 vi。当编辑器关闭的时候,libvirt 会自动检查其变化并应用这些改变。你也可以在 Virtual Machine Manager 编辑 domain。

2.3 启动一个domain

 当一个 domain 被创建后,你可以启动它。你可以使用Virtual Machine Manager,或者运行 virsh start <domain> 命令,比如:
# virsh start MyNewVM
该命令可能从零启动(boot up)一个 domain 或者从之前保存的一个状态上恢复 domain。请阅读 virsh 的 managedsave 命令 。重要的是,如果它的任何部件比如 network 还没有起来的话,一个 domain 不会被启动起来。
 
就像之前提到的那样,一个 transient domain 可以不需要提前定义(define)而直接被启动:
# virsh create /path/to/MyNewVM.xml

2.4 停止或者重启(reboot)domain

停止一个运行中的 domain:

# virsh shutdown <domain>

重启一个持久性的 domain:

# virsh reboot <domain>
注意:重启一个暂时性的 domain 是不可能的,因为当它被关闭 (shutdown)后它就变成了 undefined 状态。

粗野的关机(inelegant shutdown),等同于直接拔电源:

# virsh destroy <domain>
 
Stopping 是指中止一个运行着的domain 的过程。包括两个方法: shutdown 和 destroy。
  • shutdown 是个优雅(graceful)的停止过程,它会发一个信号给 domain 的操作系统,通知它立刻关机。domain 只有在 OS 成功关闭后才停止。该过程类似于在物理机器上运行 shutdown 命令。
  • destroy 是立刻中止 domain。该过程类似于拔掉物理机器的电源。 

2.5 中止(Pause)domain

使用 suspend 命令来中止一个domain:

# virsh suspend <domain>

当一个虚机处于挂起( suspended) 状态时,它会继续占用系统内存,但不会占用处理器资源。这时候也不会有磁盘和网络IO操作。 

2.6 继续(unpause/resume)domain

使用 resume 命令来继续一个domain:

# virsh resume <domain> 
  • Suspend and resume 是指将一个domain 临时性的保存到内存中的过程。一段时间后,可以继续该 domain 到其原始的运行状态。Suspend 不保存 domain 的内存到持久性文件。 
  • Save 和 restore 是指将一个运行着的 domain 的状态保存到文件,以及从文件中恢复的过程。
需要指出的是,save/restore 只会保存内存状态,不会保存存储状态。因此,当一个虚机被恢复时,其所使用的存储必须和虚机被保存时的存储状态一致。对基础性使用来说,这意味着虚机只能从被保存的文件中恢复一次。要运行多次恢复,应用需要在虚机被保存时生成一个快照,然后在恢复虚机时恢复快照。libvirt 将来的一个改进会在保存内存状态的同时进行自动化的快照。 

2.7 对domain做快照

使用 snapshot-create 命令来对 domain 做快照:

# virsh snapshot-create <domain>

2.8 列表domain 所有的快照

使用 snapshot-list 命令来获取 domain 的所有快照列表:

# virsh snapshot-list <domain>

结果比如:

 Name                 Creation Time             State
---------------------------------------------------
 1295973577           2011-01-25 17:39:37 +0100 running
 1295978837           2011-01-25 19:07:17 +0100 running

2.9 从快照恢复一个domain

使用 snapshot-restore 命令来从一个快照恢复一个domain:

# virsh snapshot-restore <domain> <snapshotname>

2.10 删除domain 的一个快照

使用 snapshot-delete 命令来删除一个快照:

# virsh snapshot-delete <domain> <snapshotname>

2.11 迁移 (Migration )

 Libvirt 支持 domain 的迁移。这意味着你可以把 domain 经过网络从一个主机迁移到另一个主机。迁移的两种主要模式:
  • 普通迁移(Plain migration):原主机开通一个与目的主机的 TCP 连接来发送迁移的数据。如果TCP 端口没有被指定,那么 libvirt 会自己在 49152-49215 区间内选择一个端口。因此你需要在目的主机的防火墙上开启该端口。
  • 隧道迁移(Tunneled migration):原主机创建一个与目的主机之间的连接隧道。它允许加密数据流。它不需要额外的防火墙操作,但是只在 qemu 0.12+ 和 libvirt 0.7.2 以后才支持。
要进行成功的迁移,很多事情要做。比如,存储设置。被迁移的 domain 的所有卷都必须保存在同样的路径上。读  this page 来获取完整的check list。我们建议你使用 secure migration。当迁移前的检查都完成后,可以使用migrate 命令来进行迁移:
# virsh migrate <domain> <remote host URI> --migrateuri tcp://<remote host>:<port>

2.12 删除一个domain

使用virsh 的 undefine 命令来删除一个 domain:

# virsh undefine <domain>

同样地,你也可以在 Virtual Machine Manager 中删除一个 domain。可以阅读这篇文章.

posted on 2015-05-08 08:55 SammyLiu 阅读(...) 评论(...) 编辑 收藏