1.1 libvirt

1.1.1 libvirt简介

提到KVM的管理工具,首先不得不介绍的就是大名鼎鼎的libvirt,因为libvirt是目前使用最为广泛的对KVM虚拟机进行管理的工具和应用程序接口(API),而且一些常用的虚拟机管理工具(如virsh、virt-install、virt-manager等)和云计算框架平台(如OpenStack、OpenNebula、Eucalyptus等)都在底层使用libvirt的应用程序接口。

libvirt是为了更方便地管理平台虚拟化技术而设计的开放源代码的应用程序接口、守护进程和管理工具,它不仅提供了对虚拟化客户机的管理,也提供了对虚拟化网络和存储的管理。尽管libvirt项目最初是为Xen设计的一套API,但是目前对KVM等其他Hypervisor的支持也非常的好。libvirt支持多种虚拟化方案,既支持包括KVM、QEMU、Xen、VMware、VirtualBox等在内的平台虚拟化方案,又支持OpenVZ、LXC等Linux容器虚拟化系统,还支持用户态Linux(UML)的虚拟化。libvirt是一个免费的开源的软件,使用的许可证是LGPL[1](GNU宽松的通用公共许可证),使用libvirt库进行链接的软件程序不需要一定选择开源和遵守GPL许可证。和KVM、Xen等开源项目类似,libvirt也有自己的开发者社区,而且随着虚拟化、云计算等成为近年来的技术热点,libvirt项目的社区也比较活跃。目前,libvirt的开发主要由Redhat公司作为强大的支持,由于Redhat公司在虚拟化方面逐渐偏向于支持KVM(而不是Xen),故libvirt对QEMU/KVM的支持是非常成熟和稳定的。当然,IBM、Novell等公司以及众多的个人开发者,对libvirt项目的代码贡献量也是非大的。

libvirt本身提供了一套较为稳定的C语言应用程序接口,目前,在其他一些流行的编程语言中也提供了对libvirt的绑定,在Python、Perl、Java、Ruby、PHP、OCaml等高级编程语言中已经有libvirt的程序库可以直接使用。libvirt还提供了为基于AMQP(高级消息队列协议)的消息系统(如Apache Qpid)提供QMF代理,这可以让云计算管理系统中宿主机与客户机、客户机与客户机之间的消息通信变得更易于实现。libvirt还为安全的远程管理虚拟客户机提供了加密和认证等安全措施。正是由于libvirt拥有这些强大的功能和较为稳定的应用程序接口,而且它的许可证(license)也比较宽松,libvirt的应用程序接口已被广泛地用在基于虚拟化和云计算的解决方案中,主要作为连接底层Hypervisor和上层应用程序的一个中间适配层。

libvirt对多种不同的Hypervisor的支持是通过一种基于驱动程序的架构来实现的。libvirt对不同的Hypervisor提供了不同的驱动:对Xen有Xen的驱动,对QEMU/KVM有QEMU驱动,对VMware有VMware驱动。在libvirt源代码中,可以很容易找到qemu_driver.c、xen_driver.c、xenapi_driver.c、vmware_driver.c、vbox_driver.c这样的驱动程序源代码文件。

libvirt作为中间适配层,让底层Hypervisor对上层用户空间的管理工具是可以做到完全透明的,因为libvirt屏蔽了底层各种Hypervisor的细节,为上层管理工具提供了一个统一的、较稳定的接口(API)。通过libvirt,一些用户空间管理工具可以管理各种不同的Hypervisor和上面运行的客户机,它们之间基本的交互框架如图1-1所示。

libvirt 支持各种CPU架构 libvirt详解_linux

图1-1 虚拟机管理工具通过libvirt管理各种类型的虚拟机

在libvirt中涉及到几个重要的概念,解释如下:

1. 节点(Node):一个物理机器,上面可能运行着多个虚拟客户机。Hypervisor和Domain都运行在Node之上。

2. Hypervisor:也称虚拟机监控器(VMM),如KVM、Xen、VMware、Hyper-V等,是虚拟化中的一个底层软件层,它可以虚拟化一个节点让其运行多个虚拟客户机(不同客户机可能有不同的配置和操作系统)。

3. 域(Domain):是在Hypervisor上运行的一个客户机操作系统实例。域也被称为实例(instance,如亚马逊的AWS云计算服务中客户机就被称为实例)、客户机操作系统(guest OS)、虚拟机(virtual machine),它们都是指同一个概念。

关于节点、Hypervisor和域的关系,可以简单地用图1-2来表示。

libvirt 支持各种CPU架构 libvirt详解_虚拟化_02

图1-2 节点、Hypervisor和域 三者之间的关系

在了解了节点、Hypervisor和域的概念之后,用一句话概括libvirt的目标,就是:为了安全高效的管理节点上的各个域,而提供一个公共的稳定的软件层。当然,这里的管理,既包括本地的管理,也包含远程的管理。具体地讲,libvirt的管理功能主要包含如下五个部分:

(1)域的管理:包括对节点上的域的各个生命周期的管理,如:启动、停止、暂停、保存、恢复和动态迁移。也包括对多种设备类型的热插拔操作,包括:磁盘、网卡、内存和CPU,当然不同的Hypervisor上对这些热插拔的支持程度有所不同。

(2)远程节点的管理:只要物理节点上运行了libvirtd这个守护进程,远程的管理程序就可以连接到该节点进程管理操作,经过认证和授权之后,所有的libvirt功能都可以被访问和使用。libvirt支持多种网络远程传输类型,如SSH、TCP套接字、Unix domain socket、支持TLS的加密传输等。假设使用最简单的SSH,则不需要额外配置工作,比如:example.com节点上运行了libvirtd,而且允许SSH访问,在远程的某台管理机器上就可以用如下的命令行来连接到example.com上,从而管理其上的域。


virsh -c qemu+ssh://root@example.com/system


(3)存储的管理:任何运行了libvirtd守护进程的主机,都可以通过libvirt来管理不同类型的存储,如:创建不同格式的客户机镜像(qcow2、raw、qde、vmdk等)、挂载NFS共享存储系统、查看现有的LVM卷组、创建新的LVM卷组和逻辑卷、对磁盘设备分区、挂载iSCSI共享存储,等等。当然libvirt中,对存储的管理也是支持远程管理的。

(4)网络的管理:任何运行了libvirtd守护进程的主机,都可以通过libvirt来管理物理的和逻辑的网络接口。包括:列出现有的网络接口卡,配置网络接口,创建虚拟网络接口,网络接口的桥接,VLAN管理,NAT网络设置,为客户机分配虚拟网络接口,等等。

(5)提供一个稳定、可靠、高效的应用程序接口(API)以便可以完成前面的4个管理功能。

libvirt主要由三个部分组成,它们分别是:应用程序编程接口(API)库、一个守护进程(libvirtd)和一个默认命令行管理工具(virsh)。应用程序接口(API)是为了其他虚拟机管理工具(如virsh、virt-manager等)提供虚拟机管理的程序库支持。libvirtd守护进程负责执行对节点上的域的管理工作,在用各种工具对虚拟机进行管理之时,这个守护进程一定要处于运行状态中,而且这个守护进程可以分为两种:一种是root权限的libvirtd,其权限较大,可以做所有支持的管理工作;一种是普通用户权限的libvirtd,只能做比较受限的管理工作。virsh是libvirt项目中默认的对虚拟机管理的一个命令行工具,将在2.2节中详细介绍该工具。

2.1.2 libvirt的编译、安装和配置

1. 从源代码编译和安装libvirt

如果只是普通用户使用libvirt,一般不需要从源码编译libvirt,只需要安装对应的Linux系统上libvirt软件包即可。一些高级用户或者开发者,可能希望对libvirt进行更多的了解,甚至修改libvirt的源代码来实现自己的功能,那么还是需要了解从源代码编译和安装libvirt的过程。

下面以在一个RHEL 6.3系统上编译libvirt 1.0.0 版本为例,介绍一下libvirt的编译和安装过程。

(1)真正开始编译之前,需要检查和清理系统上已经安装的libvirt(如果曾经安装过),命令行操作如下:


 [root@jay-linux kvm_demo]# which libvirtd

/usr/sbin/libvirtd

[root@jay-linux kvm_demo]# rpm -q libvirt

libvirt-0.9.10-21.el6.x86_64

[root@jay-linux kvm_demo]# rpm -e libvirt

[root@jay-linux kvm_demo]# libvirtd –version

-bash: /usr/sbin/libvirtd: No such file or directory


(2)下载libvirt的源代码

你可以选择从正在Linux系统发行版的源代码ISO中获取其libvirt的源代码安装包,也可以选择到libvirt官方网站下载libvirt源代码的tar.gz压缩包,还是可以通过git工具将开发中的libvirt源码仓库克隆到本地。

libvirt官方发布的源代码存放的网页是:http://libvirt.org/sources/ 。该网页上提供了最原生的libvirt各个版本的源代码tar.gz压缩包,以及已经编译好的libvirt-devel 、libvirt-python、libvirt-java、libvirt-php等RPM包下载。libvirt官方还提供了FTP下载源代码的站点:ftp://libvirt.org/libvirt/。下载libvirt-1.0.0.tar.gz 源码包并将其解压缩的命令行如下:


[root@jay-linux kvm_demo]# wget \ http://libvirt.org/sources/libvirt-1.0.0.tar.gz

 

–2012-11-25 22:58:24–  http://libvirt.org/sources/libvirt-1.0.0.tar.gz

HTTP request sent, awaiting response… 200 OK

Length: 21868950 (21M) [application/x-gzip]

Saving to: “libvirt-1.0.0.tar.gz”

 

100%[=======================>] 21,868,950  67.6K/s   in 2m 29s

 

2012-11-25 23:00:54 (143 KB/s) – “libvirt-1.0.0.tar.gz” saved [21868950/21868950]

[root@jay-linux kvm_demo]# tar -zxf libvirt-1.0.0.tar.gz


libvirt处于开发中的最新的git代码仓库的地址为:git://libvirt.org/libvirt.git 。还可以通过网页http://libvirt.org/git/ 以在线网页的方式浏览libvirt.git和libvirt-java.git、libvirt-php.git等开发中的代码仓库。另外,libvirt的python绑定的代码就存放在libvirt的源码仓库(libvirt.git)中,没有单独的libvirt-python代码仓库。下载libvirt开发代码仓库的命令行如下:


[root@jay-linux kvm_demo]# git clone git://libvirt.org/libvirt.git

Initialized empty Git repository in /root/kvm_demo/libvirt/.git/

remote: Counting objects: 96578, done.

remote: Compressing objects: 100% (15214/15214), done.

Receiving objects:  52% (50926/96578), 51.28 MiB | 26 KiB/s

Receiving objects:  52% (50927/96578), 51.31 MiB | 24 KiB/s

remote: Total 96578 (delta 80940), reused 96578 (delta 80940)

Receiving objects: 100% (96578/96578), 91.22 MiB | 63 KiB/s, done.

Resolving deltas: 100% (80940/80940), done.


(3)配置和编译libvirt

配置和编译libvirt的方法与Linux上多数的开源项目的方法类似,都是先运行 configure 脚本进行编译环境配置,然后用 make 命令进行编译,用 make install 命令进行安装。

查看有哪些配置选项可用的命令为“./configure –help”,命令行操作如下:


[root@jay-linux kvm_demo]# cd libvirt-1.0.0

[root@jay-linux libvirt-1.0.0]# ./configure –help

`configure’ configures libvirt 1.0.0 to adapt to many kinds of systems.

 

Usage: ./configure [OPTION]… [VAR=VALUE]…

 

To assign environment variables (e.g., CC, CFLAGS…), specify them as

VAR=VALUE.  See below for descriptions of some of the useful variables.

 

Defaults for the options are specified in brackets.

 

Configuration:

-h, –help              display this help and exit

–help=short        display options specific to this package

–help=recursive    display the short help of all the included packages

-V, –version           display version information and exit

-q, –quiet, –silent   do not print `checking …’ messages

–cache-file=FILE   cache test results in FILE [disabled]

-C, –config-cache      alias for `–cache-file=config.cache’

-n, –no-create         do not create output files

–srcdir=DIR        find the sources in DIR [configure dir or `..']

 

Installation directories:

–prefix=PREFIX         install architecture-independent files in PREFIX

[/usr/local]

–exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX

[PREFIX]

 

By default, `make install’ will install all the files in

`/usr/local/bin’, `/usr/local/lib’ etc.  You can specify

an installation prefix other than `/usr/local’ using `–prefix’,

for instance `–prefix=$HOME’.

<!– 此处省略配置libvirt的数百行帮助选项信息 –>


根据上面的配置帮助信息可知,如果不用“–prefix=PREFIX”参数指定自定义的安装路径,那么libvirt相关的文件默认都会被安装到 /usr/local/bin 和 /usr/local/lib 等目录中。

配置libvirt编译环境的命令为“./configure”,命令行操作如下:


[root@jay-linux libvirt-1.0.0]# ./configure

checking for a BSD-compatible install… /usr/bin/install -c

checking whether build environment is sane… yes

checking for a thread-safe mkdir -p… /bin/mkdir -p

checking for gawk… gawk

checking whether make sets $(MAKE)… yes

checking how to create a ustar tar archive… gnutar

<!– 此处省略配置过程中的数百行输出信息 –>

configure:      Readline: yes

configure:        Python: yes

configure:        DTrace: no

configure:         numad: no

configure:   XML Catalog: /etc/xml/catalog

configure:   Init script: redhat

configure: Console locks: /var/lock

configure:

configure: Privileges

configure:

configure:       QEMU: root:root

configure:


在配置过程中,可能会由于缺少编译时需要依赖的软件包而配置失败,只需要按照提示安装对应的软件包,然后重新运行“./configure”命令配置即可。默认情况下,libvirt会配置QEMU/KVM、vmware的驱动支持(如果能找到相关依赖库程序),也会配置libvirtd和virsh等,还会默认配置libvirt对python的绑定。对于Xen、Hyper-V等的支持,配置程序会自动检查当前系统是否含有这些Hypervisor 相关的程序,如果检测成功,就会编译对应的驱动。

真正编译libvirt的命令为“make”,命令行操作如下:


[root@jay-linux libvirt-1.0.0]# make -j 4

make  all-recursive

make[1]: Entering directory `/root/kvm_demo/libvirt-1.0.0′

Making all in gnulib/lib

make[2]: Entering directory `/root/kvm_demo/libvirt-1.0.0/gnulib/lib’

GEN    alloca.h

GEN    c++defs.h

GEN    warn-on-use.h

<!– 此处省略编译过程中的数百行输出信息 –>

Making all in examples/systemtap

make[2]: Entering directory `/root/kvm_demo/libvirt-1.0.0/examples/systemtap’

make[2]: Nothing to be done for `all’.

make[2]: Leaving directory `/root/kvm_demo/libvirt-1.0.0/examples/systemtap’

make[2]: Entering directory `/root/kvm_demo/libvirt-1.0.0′

make[2]: Leaving directory `/root/kvm_demo/libvirt-1.0.0′

make[1]: Leaving directory `/root/kvm_demo/libvirt-1.0.0′


(4)安装libvirt

在配置和编译时都不需要超级用户(root)权限,但是在安装libvirt时一般都需要root用户权限。执行 make install 命令即可完成libvirt安装,命令行操作如下:


[root@jay-linux libvirt-1.0.0]# make install

Making install in gnulib/lib

make[1]: Entering directory `/root/kvm_demo/libvirt-1.0.0/gnulib/lib’

make  install-am

make[2]: Entering directory `/root/kvm_demo/libvirt-1.0.0/gnulib/lib’

make[3]: Entering directory `/root/kvm_demo/libvirt-1.0.0/gnulib/lib’

if test yes = no; then \

case ‘linux-gnu’ in \

darwin[56]*) \

need_charset_alias=true ;; \

<!– 此处省略安装过程中的数百行输出信息 –>

make[2]: Entering directory `/root/kvm_demo/libvirt-1.0.0′

make[2]: Nothing to be done for `install-exec-am’.

/bin/mkdir -p ‘/usr/local/lib/pkgconfig’

/usr/bin/install -c -m 644 libvirt.pc ‘/usr/local/lib/pkgconfig’

make[2]: Leaving directory `/root/kvm_demo/libvirt-1.0.0′

make[1]: Leaving directory `/root/kvm_demo/libvirt-1.0.0′


(5)检查已经安装的libvirt

libvirt的安装会给系统安装上libvirtd、virsh等可执行程序,也会安装libvirt 的API程序库,还会安装对python的绑定,检查这些安装后的文件,命令行操作如下:


[root@jay-linux libvirt-1.0.0]# which libvirtd

/usr/local/sbin/libvirtd

[root@jay-linux libvirt-1.0.0]# libvirtd –version

libvirtd (libvirt) 1.0.0

[root@jay-linux libvirt-1.0.0]# which virsh

/usr/local/bin/virsh

[root@jay-linux libvirt-1.0.0]# virsh –version

1.0.0

 

[root@jay-linux libvirt-1.0.0]# ls /usr/local/include/libvirt/

libvirt.h  libvirt-qemu.h  virterror.h

 

[root@jay-linux libvirt-1.0.0]# ls /usr/local/lib/libvirt*

/usr/local/lib/libvirt.a        /usr/local/lib/libvirt-qemu.so           /usr/local/lib/libvirt.so.0

/usr/local/lib/libvirt.la       /usr/local/lib/libvirt-qemu.so.0         /usr/local/lib/libvirt.so.0.1000.0

/usr/local/lib/libvirt-qemu.a   /usr/local/lib/libvirt-qemu.so.0.1000.0

/usr/local/lib/libvirt-qemu.la  /usr/local/lib/libvirt.so

 

/usr/local/lib/libvirt:

connection-driver

 

[root@jay-linux libvirt-1.0.0]# ls /usr/local/lib64/python2.6/site-packages/*virt*

/usr/local/lib64/python2.6/site-packages/libvirtmod.la       /usr/local/lib64/python2.6/site-packages/libvirtmod.so

/usr/local/lib64/python2.6/site-packages/libvirtmod_qemu.la  /usr/local/lib64/python2.6/site-packages/libvirt.py

/usr/local/lib64/python2.6/site-packages/libvirtmod_qemu.so  /usr/local/lib64/python2.6/site-packages/libvirt_qemu.py


如果安装后立即使用libvirt这些程序库时,遇到找不到对应库文件的错误提示,这时可能需要运行 ldconfig 等工具来更新刚才安装的共享库。

(6)从libvirt的git代码仓库编译libvirt

从git源代码仓库编译和安装libvirt,与从libvirt的源码tar.gz包编译安装的过程是完全类似的。这里只介绍一些在编译前的配置(configure)时的一些不同之处。使用 libvirt.git 源码仓库配置时,是先运行其自带的 autogen.sh 这个脚本,它会默认会先下载 git://git.sv.gnu.org/gnulib.git ,然后根据模板生成configure配置脚本和初始化一些Makefile文件,最后自动运行 configure 文件进行对编译环境的配置。

从git源码仓库安装libvirt的基本操作命令行如下(省略命令执行的输出信息):


[root@jay-linux kvm_demo]# cd libvirt.git

[root@jay-linux libvirt.git]# ./autogen.sh

[root@jay-linux libvirt.git]# make

[root@jay-linux libvirt.git]# make install


默认状态下,配置和编译后安装的目录与Linux操作系统发行版提供的默认目录可能是不一致的,例如:RHEL 6.3中用系统的RPM包安装的libvirtd、virsh等可执行程序被安装 /usr/sbin/ 目录下,libvirt.so、libvirt-qemu.so等共享库文件被安装在 /usr/lib64/ 目录下,而从前面步骤(5)中可知自己编译安装时,默认会将libvirtd、virsh等安装在 /usr/local/sbin 目录下,而libvirt.so、libvirt-qemu.so 等被安装在 /usr/local/lib/ 目录下。如果想保持对操作系统发型版中安装可执行程序和共享库的目录的一致性, autogen.sh 脚本提供了“–system”参数,带有这个参数来配置,就会尽可能保证安装目录与原生系统的一致性,其命令行操作如下(省略了部分命令执行的输出信息):


[root@jay-linux libvirt.git]# ./autogen.sh –system

[root@jay-linux libvirt.git]# make

[root@jay-linux libvirt.git]# make install

[root@jay-linux libvirt.git]# which libvirtd

/usr/sbin/libvirtd

[root@jay-linux libvirt.git]# which virsh

/usr/bin/virsh

[root@jay-linux libvirt.git]# ls /usr/lib64/libvirt*

/usr/lib64/libvirt.a        /usr/lib64/libvirt-qemu.so           /usr/lib64/libvirt.so

/usr/lib64/libvirt.la       /usr/lib64/libvirt-qemu.so.0         /usr/lib64/libvirt.so.0

/usr/lib64/libvirt-qemu.a   /usr/lib64/libvirt-qemu.so.0.1000.0  /usr/lib64/libvirt.so.0.1000.0

/usr/lib64/libvirt-qemu.la  /usr/lib64/libvirt-qemu.so.0.9.10    /usr/lib64/libvirt.so.0.9.10

 

/usr/lib64/libvirt:

connection-driver


2. 用软件包安装libvirt

在很多流行的Linux发型版(如RHEL 6.x、Fedora 17、Ubuntu 12.10等)上都提供了libvirt相关的软件包,按照安装普通软件包的方式安装libvirt相关的软件包即可。在笔者当前使用的 RHEL 6.3 中可以使用 yum 或 rpm 工具来安装对应的RPM包,查看某系统中已经安装的libvirt相关的RPM包,命令行如下所示:


[root@rhel6u3-ga ~]# rpm -qa | grep libvirt

libvirt-python-0.9.10-21.el6.x86_64

libvirt-java-javadoc-0.4.7-1.el6.noarch

libvirt-qmf-0.3.0-6.el6.x86_64

libvirt-client-0.9.10-21.el6.x86_64

libvirt-lock-sanlock-0.9.10-21.el6.x86_64

libvirt-java-devel-0.4.7-1.el6.noarch

libvirt-0.9.10-21.el6.x86_64

libvirt-snmp-0.0.2-3.el6.x86_64

libvirt-java-0.4.7-1.el6.noarch

libvirt-devel-0.9.10-21.el6.x86_64

libvirt-cim-0.6.1-3.el6.x86_64


当然,RHEL 6.3 中默认采用QEMU/KVM的虚拟化方案,所以应该安装QEMU相关的软件包,查看这些软件包的命令行操作如下:


[root@rhel6u3-ga ~]# rpm -qa | grep qemu

qemu-img-0.12.1.2-2.295.el6.x86_64

qemu-kvm-0.12.1.2-2.295.el6.x86_64

gpxe-roms-qemu-0.9.7-6.9.el6.noarch


由于libvirt是跨平台的,而且还支持微软公司的Hyper-V虚拟化,所以你也可以在Windows上安装libvirt,甚至编译libvirt。可以到libvirt官方的网页中查看和下载能在Windows上运行的libvirt安装程序,http://libvirt.org/sources/win32_experimental/ 。不过,由于libvirt主要还是基于Linux开发的,而且支持它的公司(Redhat等)中的开发者和个人开发者大多数都是Linux程序员,故libvirt的Windows版本还是处于开发中的,开发进度并不如Linux上libvirt开发得快,前面提到能下载的libvirt Windows版也是实验性的版本,而不是正式产品的发行版,其功能并不保证非常完善。