Libvirt (简体中文)

Related articles

翻译状态: 本文是英文页面 Libvirt翻译,最后翻译时间:2016-01-23,点击这里可以查看翻译后英文页面的改动。

Libvirt 是一组软件的汇集,提供了管理虚拟机和其它虚拟化功能(如:存储和网络接口等)的便利途径。这些软件包括:一个长期稳定的 C 语言 API、一个守护进程(libvirtd)和一个命令行工具(virsh)。Libvirt 的主要目标是提供一个单一途径以管理多种不同虚拟化方案以及虚拟化主机,包括:KVM/QEMUXenLXCOpenVZVirtualBox hypervisors详见这里)。

Libvirt 的一些主要功能如下:

  • VM management(虚拟机管理):各种虚拟机生命周期的操作,如:启动、停止、暂停、保存、恢复和迁移等;多种不同类型设备的热插拔操作,包括磁盘、网络接口、内存、CPU等。
  • Remote machine support(支持远程连接):Libvirt 的所有功能都可以在运行着 libvirt 守护进程的机器上执行,包括远程机器。通过最简便且无需额外配置的 SSH 协议,远程连接可支持多种网络连接方式。
  • Storage management(存储管理):任何运行 libvirt 守护进程的主机都可以用于管理多种类型的存储:创建多种类型的文件镜像(qcow2,vmdk,raw,...),挂载 NFS 共享,枚举现有 LVM 卷组,创建新的 LVM 卷组和逻辑卷,对裸磁盘设备分区,挂载 iSCSI 共享,以及更多......
  • Network interface management(网络接口管理):任何运行 libvirt 守护进程的主机都可以用于管理物理的和逻辑的网络接口,枚举现有接口,配置(和创建)接口、桥接、VLAN、端口绑定。
  • Virtual NAT and Route based networking(虚拟 NAT 和基于路由的网络):任何运行 libvirt 守护进程的主机都可以管理和创建虚拟网络。Libvirt 虚拟网络使用防火墙规则实现一个路由器,为虚拟机提供到主机网络的透明访问。

安装

基于守护进程/客户端的架构的 libvirt 只需要安装在需要要实现虚拟化的机器上。注意,服务器和客户端可以是相同的物理机器。

服务端

安装 libvirt 以及至少一个管理程序(hypervisor):

  • 其他虚拟机后端,包括 LXC, VirtualBoxXen。请参见它们各自的安装说明。
注意: Libvirt 的 LXC 驱动 并不依赖 lxc 提供的用户空间工具,因此,如果计划使用这个驱动并不需要安装该工具。
警告: Libvirt 默认未支持 Xen。需要用 ABS 编辑 libvirtPKGBUILD ,去掉 --without-xen 选项后重新构建(built)libvirt。

其它虚拟机管理程序列表见这里

对于网络连接,安装这些包:

客户端

客户端是用于管理和访问虚拟机的用户界面。

兼容 libvirt 的软件列表见 这里.

配置

对于系统 级别的管理任务(如:全局配置和镜像 位置),libvirt 要求至少要设置授权启动守护进程

注意: 对于用户会话 级别的管理任务,守护进程的安装和设置不是 必须的。授权总是仅限本地,前台程序将启动一个 libvirtd 守护进程的本地实例。

设置授权

来自 libvirt:连接授权

Libvirt 守护进程允许管理员分别为客户端连接的每个网络 socket 选择不同授权机制。这主要是通过 libvirt 守护进程的主配置文件 /etc/libvirt/libvirtd.conf 来实现的。每个 libvirt socket 可以有独立的授权机制配置。目前的可选项有 nonepolkitsasl

由于 libvirt 在安装时将把 polkit 作为依赖一并安装, polkit 通常是 unix_sock_auth 参数的默认值(来源)。基于文件的权限 仍然有效。

使用 polkit

Note: A system reboot may be required before authenticating with polkit works correctly.

The libvirt daemon provides two polkit actions in /usr/share/polkit-1/actions/org.libvirt.unix.policy:

  • org.libvirt.unix.manage for full management access (RW daemon socket), and
  • org.libvirt.unix.monitor for monitoring only access (read-only socket).

The default policy for the RW daemon socket will require to authenticate as an admin. This is akin to sudo auth, but does not require that the client application ultimately run as root. Default policy will still allow any application to connect to the RO socket.

Arch defaults to consider anybody in the wheel group as an administrator: this is defined in /etc/polkit-1/rules.d/50-default.rules (see Polkit#Administrator identities). Therefore there is no need to create a new group and rule file if your user is a member of the wheel group: upon connection to the RW socket (e.g. via virt-manager) you will be prompted for your user's password.

Note: Prompting for a password relies on the presence of an authentication agent on the system. Console users may face an issue with the default pkttyagent agent which may or may not work properly.
Tip: If you want to configure passwordless authentication, see Polkit#Bypass password prompt.

As of libvirt 1.2.16 (commit:[1]), members of the libvirt group have passwordless access to the RW daemon socket by default. The easiest way to ensure your user has access is to ensure the libvirt group exists and they are a member of it. If you wish to change the group authorized to access the RW daemon socket to be the kvm group, create the following file:

/etc/polkit-1/rules.d/50-libvirt.rules
/* Allow users in kvm group to manage the libvirt
daemon without authentication */
polkit.addRule(function(action, subject) {
    if (action.id == "org.libvirt.unix.manage" &&
        subject.isInGroup("kvm")) {
            return polkit.Result.YES;
    }
});

Then add yourself to the kvm group and relogin. Replace kvm with any group of your preference just make sure it exists and that your user is a member of it (see Users and groups for more information).

Do not forget to relogin for group changes to take effect.

基于文件的权限授权

To define file-based permissions for users in the libvirt group to manage virtual machines, uncomment and define:

/etc/libvirt/libvirtd.conf
#unix_sock_group = "libvirt"
#unix_sock_ro_perms = "0777"  # set to 0770 to deny non-group libvirt users
#unix_sock_rw_perms = "0770"
#auth_unix_ro = "none"
#auth_unix_rw = "none"

While some guides mention changed permissions of certain libvirt directories to ease management, keep in mind permissions are lost on package update. To edit these system directories, root user is expected.

守护进程

Start both libvirtd.service and virtlogd.service. Optionally enable libvirtd.service. There is no need to enable virtlogd.service, since libvirtd.service, when enabled, also enables the virtlogd.socket and virtlockd.socket units.

非加密的 TCP/IP sockets

警告: 这种方法常用于在可信网络中快速连接远程虚拟机做协助。这是最不安全 的连接方式,应当仅仅 用于测试或用于安全、私密和可信的网络环境。这时 SASL 没有启用,所以所有的 TCP 通讯都是明文传输。在正式的应用场合应当始终 启用 SASL。

编辑 /etc/libvirt/libvirtd.conf

/etc/libvirt/libvirtd.conf
listen_tls = 0
listen_tcp = 1
auth_tcp=none

It is also necessary to start the server in listening mode by editing /etc/conf.d/libvirtd:

/etc/conf.d/libvirtd
LIBVIRTD_ARGS="--listen"

测试

To test if libvirt is working properly on a system level:

$ virsh -c qemu:///system

To test if libvirt is working properly for a user-session:

$ virsh -c qemu:///session

管理

Libvirt management is done mostly with three tools: virt-manager (GUI), virsh, and guestfish (which is part of libguestfsAUR).

virsh

The virsh program is for managing guest domains (virtual machines) and works well for scripting, virtualization administration. Though most virsh commands require root privileges to run due to the communication channels used to talk to the hypervisor, typical management, creation, and running of domains (like that done with VirtualBox) can be done as a regular user.

Virsh includes an interactive terminal that can be entered if no commands are passed (options are allowed though): virsh. The interactive terminal has support for tab completion.

From the command line:

$ virsh [option] <command> [argument]...

From the interactive terminal:

virsh # <command> [argument]...

Help is available:

$ virsh help [option*] or [group-keyword*]

存储池

A pool is a location where storage volumes can be kept. What libvirt defines as volumes others may define as "virtual disks" or "virtual machine images". Pool locations may be a directory, a network filesystem, or partition (this includes a LVM). Pools can be toggled active or inactive and allocated for space.

On the system-level, /var/lib/libvirt/images/ will be activated by default; on a user-session, virt-manager creates $HOME/VirtualMachines.

Print active and inactive storage pools:

$ virsh pool-list --all

用 virsh 新建存储池

If wanted to add a storage pool, here are examples of the command form, adding a directory, and adding a LVM volume:

$ virsh pool-define-as name type [source-host] [source-path] [source-dev] [source-name] [<target>] [--source-format format]
$ virsh pool-define-as poolname dir - - - - /home/username/.local/libvirt/images
$ virsh pool-define-as poolname fs - -  /dev/vg0/images - mntpoint

The above command defines the information for the pool, to build it:

$ virsh pool-build     poolname
$ virsh pool-start     poolname
$ virsh pool-autostart poolname

To remove it:

$ virsh pool-undefine  poolname
Tip: For LVM storage pools:
  • It is a good practice to dedicate a volume group to the storage pool only.
  • Choose a LVM volume group that differs from the pool name, otherwise when the storage pool is deleted the LVM group will be too.

用 virt-manager 新建存储池

First, connect to a hypervisor (e.g. QEMU/KVM system, or user-session). Then, right-click on a connection and select Details; select the Storage tab, push the + button on the lower-left, and follow the wizard.

存储卷

Once the pool has been created, volumes can be created inside the pool. If building a new domain (virtual machine), this step can be skipped as a volume can be created in the domain creation process.

用 virsh 新建卷

Create volume, list volumes, resize, and delete:

$ virsh vol-create-as      poolname volumename 10GiB
$ virsh vol-list           poolname
$ virsh vol-resize  --pool poolname volumename 12GiB
$ virsh vol-delete  --pool poolname volumename
$ virsh vol-dumpxml --pool poolname volumename  # for details.

virt-manager 后备存储类型的 bug

On newer versions of virt-manager you can now specify a backing store to use when creating a new disk. This is very useful, in that you can have new domains be based on base images saving you both time and disk space when provisioning new virtual systems. There is a bug (https://bugzilla.redhat.com/show_bug.cgi?id=1235406) in the current version of virt-manager which causes virt-manager to choose the wrong type of the backing image in the case where the backing image is a qcow2 type. In this case, it will errantly pick the backing type as raw. This will cause the new image to be unable to read from the backing store, and effectively remove the utility of having a backing store at all.

There is a workaround for this issue. qemu-img has long been able to do this operation directly. If you wish to have a backing store for your new domain before this bug is fixed, you may use the following command.

$ qemu-img create -f qcow2 -o backing_file=<path to backing image>,backing_fmt=qcow2 <disk name> <disk size>

Then you can use this image as the base for your new domain and it will use the backing store as a COW volume saving you time and disk space.

虚拟机

Virtual machines are called domains. If working from the command line, use virsh to list, create, pause, shutdown domains, etc. virt-viewer can be used to view domains started with virsh. Creation of domains is typically done either graphically with virt-manager or with virt-install (a command line program that is part of the virt-manager package).

Creating a new domain typically involves using some installation media, such as an .iso from the storage pool or an optical drive.

Print active and inactive domains:

# virsh list --all
Note: SELinux has a built-in exemption for libvirt that allows volumes in /var/lib/libvirt/images/ to be accessed. If using SELinux and there are issues with the volumes, ensure that volumes are in that directory, or ensure that other storage pools are correctly labeled.

用 virt-install 新建虚拟机

For an extremely detailed domain (virtual machine) setup, it is easier to #Create a new domain using virt-manager. However, basics can easily be done with virt-install and still run quite well. Minimum specifications are --name, --memory, guest storage (--disk, --filesystem, or --nodisks), and an install method (generally an .iso or CD).

Arch Linux install (two GiB, raw format volume create; user-networking):

$ virt-install  \
  --name arch-linux_testing \
  --memory 1024             \ 
  --vcpus=2,maxvcpus=4      \
  --cpu host                \
  --cdrom $HOME/Downloads/arch-linux_install.iso \
  --disk size=2,format=raw  \
  --network user            \
  --virt-type kvm

Fedora testing (Xen hypervisor, non-default pool, do not originally view):

$ virt-install  \
  --connect xen:///     \
  --name fedora-testing \
  --memory 2048         \
  --vcpus=2             \
  --cpu=host            \
  --cdrom /tmp/fedora20_x84-64.iso      \
  --os-type=linux --os-variant=fedora20 \
  --disk pool=testing,size=4            \
  --network bridge=br0                  \
  --graphics=vnc                        \
  --noautoconsole
$ virt-viewer --connect xen:/// fedora-testing

Windows:

$ virt-install \
  --name=windows7           \
  --memory 2048             \
  --cdrom /dev/sr0          \
  --os-variant=win7         \
  --disk /mnt/storage/domains/windows7.qcow2,size=20GiB \
  --network network=vm-net  \
  --graphics spice
Tip: Run osinfo-query --fields=name,version os to get argument for --os-variant; this will help define some specifications for the domain. However, --memory and --disk will need to be entered; one can look within the appropriate /usr/share/libosinfo/db/oses/os.xml if needing these specifications. After installing, it will likely be preferable to install the Spice Guest Tools that include the VirtIO drivers. For a Windows VirtIO network driver there is also virtio-winAUR. These drivers are referenced by a <model type='virtio' /> in the guest's .xml configuration section for the device. A bit more information can also be found on the QEMU article.

Import existing volume:

$ virt-install  \
  --name demo  \
  --memory 512 \
  --disk /home/user/VMs/mydisk.img \
  --import

用 virt-manager 新建虚拟机

First, connect to the hypervisor (e.g. QEMU/KVM system or user session), right click on a connection and select New, and follow the wizard.

  • On the fourth step, de-selecting Allocate entire disk now will make setup quicker and can save disk space in the interum; however, it may cause volume fragmentation over time.
  • On the fifth step, open Advanced options and make sure that Virt Type is set to kvm (this is usually the preferred method). If additional hardware setup is required, select the Customize configuration before install option.

管理虚拟机

启动虚拟机:

$ virsh start domain
$ virt-viewer --connect qemu:///session domain

Gracefully attempt to shutdown a domain; force off a domain:

$ virsh shutdown domain
$ virsh destroy  domain

Autostart domain on libvirtd start:

$ virsh autostart domain
$ virsh autostart domain --disable

Shutdown domain on host shutdown:

Running domains can be automatically suspended/shutdown at host shutdown using the libvirt-guests.service systemd service. This same service will resume/startup the suspended/shutdown domain automatically at host startup. Read /etc/conf.d/libvirt-guests for service options.

Edit a domain's XML configuration:

$ virsh edit domain
Note: Virtual Machines started directly by QEMU are not managable by libvirt tools.

网络

A decent overview of libvirt networking.

By default, when the libvird systemd service is started, a NAT bridge is created called default to allow external network connectivity (warning see: #"default" network bug). For other network connectivity needs, four network types exist that can be created to connect a domain to:

  • bridge — a virtual device; shares data directly with a physical interface. Use this if the host has static networking, it does not need to connect other domains, the domain requires full inbound and outbound trafficing, and the domain is running on a system-level. See Network bridge on how to add a bridge additional to the default one. After creation, it needs to be specified in the respective guest's .xml configuration file.
  • network — a virtual network; has ability to share with other domains. Use a virtual network if the host has dynamic networking (e.g. NetworkManager), or using wireless.
  • macvtap — connect directly to a host physical interface.
  • user — local ability networking. Use this only for a user session.

virsh has the ability to create networking with numerous options for most users, however, it is easier to create network connectivity with a graphic user interface (like virt-manager), or to do so on creation with virt-install.

Note: libvirt handles DHCP and DNS with dnsmasq, launching a separate instance for every virtual network. It also adds iptables rules for proper routing, and enables the ip_forward kernel parameter.

快照

Snapshots take the disk, memory, and device state of a domain at a point-of-time, and save it for future use. They have many uses, from saving a "clean" copy of an OS image to saving a domain's state before a potentially destructive operation. Snapshots are identified with a unique name.

Snapshots are saved within the volume itself and the volume must be the format: qcow2 or raw. Snapshots use deltas so they have the potentiality to not take much space.

创建快照

Tango-view-refresh-red.pngThis article or section is out of date.Tango-view-refresh-red.png

Reason: Some of this data appears to be dated. (Discuss in Talk:Libvirt (简体中文)#)

Once a snapshot is taken it is saved as a new block device and the original snapshot is taken offline. Snapshots can be chosen from and also merged into another (even without shutting down the domain).

Print a running domain's volumes (running domains can be printed with virsh list):

# virsh domblklist domain
 Target     Source
 ------------------------------------------------
 vda        /vms/domain.img

To see a volume's physical properties:

# qemu-img info /vms/domain.img
 image: /vms/domain.img
 file format: qcow2
 virtual size: 50G (53687091200 bytes)
 disk size: 2.1G
 cluster_size: 65536

Create a disk-only snapshot (the option --atomic will prevent the volume from being modified if snapshot creation fails):

# virsh snapshot-create-as domain snapshot1 --disk-only --atomic

List snapshots:

# virsh snapshot-list domain
 Name                 Creation Time             State
 ------------------------------------------------------------
 snapshot1           2012-10-21 17:12:57 -0700 disk-snapshot

One can they copy the original image with cp --sparse=true or rsync -S and then merge the the original back into snapshot:

# virsh blockpull --domain domain --path /vms/domain.snapshot1

domain.snapshot1 becomes a new volume. After this is done the original volume (domain.img and snapshot metadata can be deleted. The virsh blockcommit would work opposite to blockpull but it seems to be currently under development (including snapshot-revert feature, scheduled to be released sometime next year.

其他管理操作

Connect to non-default hypervisor:

$ virsh --connect xen:///
virsh # uri
xen:///

Connect to the QEMU hypervisor over SSH; and the same with logging:

$ virsh --connect qemu+ssh://username@host/system
$ LIBVIRT_DEBUG=1 virsh --connect qemu+ssh://username@host/system

Connect a graphic console over SSH:

$ virt-viewer  --connect qemu+ssh://username@host/system domain
$ virt-manager --connect qemu+ssh://username@host/system domain
Note: If you are having problems connecting to a remote RHEL server (or anything other than Arch, really), try the two workarounds mentioned in FS#30748 and FS#22068.

Connect to the VirtualBox hypervisor (VirtualBox support in libvirt is not stable yet and may cause libvirtd to crash):

$ virsh --connect vbox:///system

Network configurations:

$ virsh -c qemu:///system net-list --all
$ virsh -c qemu:///system net-dumpxml default

Python 连接代码

The libvirt-python package provides a python2 API in /usr/lib/python2.7/site-packages/libvirt.py.

General examples are given in /usr/share/doc/libvirt-python-your_libvirt_version/examples/

Unofficial example using qemu and openssh:

#! /usr/bin/env python2
# -*- coding: utf-8 -*-
import socket
import sys
import libvirt
if (__name__ == "__main__"):
   conn = libvirt.open("qemu+ssh://xxx/system")
   print "Trying to find node on xxx"
   domains = conn.listDomainsID()
   for domainID in domains:
       domConnect = conn.lookupByID(domainID)
       if domConnect.name() == 'xxx-node':
           print "Found shared node on xxx with ID " + str(domainID)
           domServ = domConnect
           break

参阅