Libvirt (简体中文)

Related articles

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

libvirt 是一个虚拟化 API 和虚拟机(VMs)管理后台,支持远程或本地访问,支持多种虚拟化后端 (QEMU/KVMVirtualBoxXen,等等) 。本文并不打算涉及有关 libvirt 的方方面面,仅讨论那些与通常的认知不同的地方或文档论述不详之处。

安装

服务器端需要从 官方仓库 同时安装下列包,它们组合起来共同作为虚拟化后端:

  • libvirt
  • virt-manager (一个图形界面程序,用于安装和管理虚拟机)(译注:非必须。如果不需要在服务器本地做GUI管理可不安装,已实证。)
  • bridge-utilsdnsmasq (用于网络共享)

客户端需要安装下列包:

注意: 服务器和客户端可以是同一台物理机器

为 Xen 构建 libvirt

目前,AUR中的libvirt-gitAUR官方仓库中的 libvirt 二者的 PKGBUILD 均在 make 过程中通过 --without-xen 标记禁用了对 Xen 的支持。如果你需要用 libvirt 管理 Xen, 你需要 获取完整的文件集 以提供对 Xen 的支持,并且需要用ABS(即 Arch Build System,Arch 构建系统)构建你自己的 libvirt。AUR中的xenAUR软件包要求 libvirt 构建时带有对 Xen 的支持。 The alternative XenAPI driver is lacking a package at the moment? (2010-05-23, friesoft)

配置

Libvirt 不是“开箱即用”的。你至少需要运行后台进程并且配置认证策略或者配置Unix 文件权限。同样也需要为 QEMU 打开 KVM 加速.

运行后台进程

/etc/libvirt/qemu.conf中修改默认的用户和用户组。 QEMU 默认是 nobody:nobody。

Systemd打开和启动 libvirtd.service

注意: Avahi 后台进程用于通过 DNS组播发现本地 libvirt 主机。可以在/etc/libvirt/libvirtd.conf中设置mdns_adv = 0 禁用此功能。

认证策略

创建下列文件,使libvirt用户组里面的非root用户可以管理虚拟机:

/etc/polkit-1/rules.d/50-org.libvirt.unix.manage.rules
polkit.addRule(function(action, subject) {
    if (action.id == "org.libvirt.unix.manage" &&
        subject.isInGroup("libvirt")) {
            return polkit.Result.YES;
    }
});

或者,用下列语句授予非root用户仅查看虚拟机的权限

org.libvirt.unix.monitor

更多信息请参阅:libvirt 的 wiki 站点

Unix 文件权限

注意: 这是#认证策略的替代方案

如果希望通过配置 Unix 文件权限的方式允许某些非 root 用户使用 libvirt,需按下列步骤设置:

首先,创建libvirt 用户组并将需授权访问 libvirt 的用户加入该组:

# groupadd libvirt
# gpasswd -a user libvirt

如果被加入的用户当前已登录,则需要注销后重新登录。或者,该用户也可以执行下列命令更新所属组:

$ newgrp libvirt

/etc/libvirt/libvirtd.conf文件中下列行的注释符(#号)删除(这些行可能位于文件中不同位置):

/etc/libvirt/libvirtd.conf
 #unix_sock_group = "libvirt"
 #unix_sock_ro_perms = "0777"
 #unix_sock_rw_perms = "0770"
 #auth_unix_ro = "none"
 #auth_unix_rw = "none"
注意: 还应当将 unix_sock_ro_perms 参数的值由 0777 改为 0770 ,目的是取消非 libvirt 组的其他用户的只读访问权限

为 QEMU 打开 KVM 加速

注意: KVMVirtualBox 有冲突,二者不能同时使用。

以惯常方式(不带 KVM 支持)运行 QEMU 模拟器会变态地慢!如果 CPU 支持,你一定要打开 KVM 支持。执行下列命令查看 CPU 是否支持 KVM:

egrep --color "vmx|svm" /proc/cpuinfo

如果上述命令有输出结果返回,则说明 CPU 支持 KVM 硬件加速。如果没有返回任何信息,则无法使用 KVM

KVM 无效时,可在 /var/log/libvirt/qemu/VIRTNAME.log 这个文件中读到下列信息:

/var/log/libvirt/qemu/VIRTNAME.log
Could not initialize KVM, will disable KVM support

KVM 官方 FAQ中包含更多相关信息

宿主机关机/启动时停止/恢复客户机

Systemd 的 libvirt-guests.service 这个服务程序可以支持在宿主机关机时自动地挂起或关闭客户机。同样也支持宿主机开机时自动恢复或启动客户机。

请查阅 /etc/conf.d/libvirtd-guests 中的 libvirt-guests 相关选项。

引导时启动 KVM 虚拟机

如果用 virt-managervirsh 作为虚拟机管理工具,则很简单即可实现。

开机自动启动的命令:

$ virsh autostart <domain>

禁用开机自动启动的命令:

$ virsh autostart --disable <domain>

virt-manager 中,在引导 选项页下同样也有个自动启动勾选项。

注意: 以命令行方式通过 QEMU 或 KVM 启动的虚拟机不能通过 virt-manager 管理

使用

创建一个新虚拟机

创建新虚拟机需要准备安装介质,通常是一个标准的.iso文件。将其复制到/var/lib/libvirt/images/ 目录即可(或者在 virt-manager 中新建一个 存储池 目录,将其复制到该目录)。

注意: SELinux要求虚拟机默认存储在/var/lib/libvirt/images/目录。如果启用了 SELinux并且 are having issues with virtual machines,需确保虚拟机位于该目录或确保添加了指向非默认目录的正确标签(译注:本段译文需斟酌)

然后运行virt-manager连接到服务器,右击连接、选择新建。 输入自定义的连接名,选择 本地安装介质,按照向导继续。

第四步中,应当取消 分配全部磁盘空间 选项。当虚拟机并不需要使用全部磁盘时,这样做可以节约空间,但也会导致磁盘碎片增多。此时,应密切关注宿主机的剩余磁盘空间总量,否则很容易导致为虚拟机分配了过量磁盘空间。

第五步中,打开 高级选项 并确认 虚拟类型 选择了 kvm。如果该选项无效,查阅前文 为 QEMU 打开 KVM 加速 一节

在virt-manager中创建存储池

首先连接到一个现有的服务器。连接后,右击详情,进入存储,点击左下方的+图标,然后按向导指示继续。

用virt-manager管理VirtualBox

注意: Libvirt对VirtualBox的支持尚不完备,有可能导致 libvirtd 进程崩溃。但通常这并不会导致灾难,重启进程即可恢复

virt-manager 不允许从图形用户界面程序连接 VirtualBox。但可以从命令行加载:

virt-manager -c vbox:///system

或者通过 SSH 管理远程系统:

virt-manager -c vbox+ssh://username@host/system

在线快照

Libvirt 可以在无需关闭虚拟机的情况下抓取虚拟机快照,这个功能称为外部快照(external snapshotting)。 当前该功能仅支持基于 qcow2 和 raw 文件的虚拟机镜像。

一旦快照创建完毕,KVM 将新建一个仅包含快照内容的块设备挂载到虚拟机,新产生的数据将直接写入这个新的磁盘,原始磁盘镜像将被置为离线,以便复制或备份。以后还可以重新将含快照的镜像与原始镜像融合而无需关闭虚拟机。(本段译文存疑-Aaron Chen)

以下演示其工作原理:

当前运行中的虚拟机:

# virsh list --all
 Id    Name                           State
 ----------------------------------------------------
 3     archey                            running

查看虚拟机的全部镜像文件:

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

注意看镜像文件的属性

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

创建一个 disk-only 类型的快照。开关参数--atomic将确保万一快照创建失败时虚拟机不被篡改

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

查看快照清单:

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

virsh 创建了一个新的镜像文件。注意观察它的属性:只有几 MB 大小,并且链接到其原始的“后备镜像/链”

# qemu-img info /vms/archey.snapshot1
 image: /vms/archey.snapshot1
 file format: qcow2
 virtual size: 50G (53687091200 bytes)
 disk size: 18M
 cluster_size: 65536
 backing file: /vms/archey.img

在这里,可以回过头来复制原始镜像(通过cp -sparse=truersync -S参数),然后就可以将原始镜像融合进快照。

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

现在,数据块被从原始镜像中抽离出来,/vms/archey.snapshot1 这个文件成为新的虚拟机磁盘的镜像文件。查看其磁盘容量就知道。这些都完成后,原始磁盘镜像/vms/archey.img 以及快照元数据就可以安全地删除了。

virsh blockcommitblockpull的反向操作,不过似乎在当前的 qemu-kvm 1.3 版中(连同快照恢复(snapshot-revert))功能都还处于开发阶段,按开发日程安排是在明年发布。

对于需要频繁在线备份的需求者来说,KVM的这一新功能十分便利而又不必冒文件系统损坏的风险。

远程访问libvirt

使用未加密的 TCP/IP socket (最简单,最不安全)

警告: 这一操作仅可应用于安全、私密、可信的网络环境

编辑/etc/libvirt/libvirtd.conf

/etc/libvirt/libvirtd.conf
listen_tls = 0
listen_tcp = 1
auth_tcp=none
警告: 这里的设置没有打开 SASL,因而所有的 TCP 传输都是明文传输!在真实的应用环境中,一定要始终打开 SASL。

另外还要编辑/etc/conf.d/libvirtd,以监听模式启动libvirtd服务

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

使用 SSH

通过SSH远程管理,需要openbsd-netcat软件包。

virsh连接到远程系统:

$ virsh -c qemu+ssh://username@host/IP address/system

如果出错了,可以如下方式获取日志:

$ LIBVIRT_DEBUG=1 virsh -c qemu+ssh://username@host/IP address/system

显示图形界面虚拟机控制台:

$ virt-viewer --connect qemu+ssh://username@host/IP address/system myvirtualmachine

显示虚拟机桌面管理工具:

$ virt-manager -c qemu+ssh://username@host/IP address/system
注意: 如果连接到远程的 RHEL (或者其他非 Arch 系统)服务器有问题,参阅FS#30748以及FS#22068

使用 Python

libvirt-python软件包中的/usr/lib/python2.7/site-packages/libvirt.py提供了python2 的 API。

/usr/share/doc/libvirt-python-your_libvirt_version/examples/中给出了若干通用范例。

使用qemuopenssh 的非官方范例:

#! /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

桥接网络

如果要在虚拟机中使用宿主机的物理网卡,需要在物理网卡(此处为eth0)和虚拟机的虚拟网卡之间创建网桥

宿主机配置

由于 libvirt 会创建一个名为virbr0的 NAT 网络,所以应该使用其他的名字比如br0或者virbr1创建网桥。 应当创建一个 NetctlSystemd-networkd 的配置文件配置新创建的网桥,例如(使用 DHCP 的配置):

/etc/netctl/br0
Description="Bridge connection for kvm"
Interface=br0
Connection=bridge
BindsToInterfaces=(eno1)
IP=dhcp

Tango-dialog-warning.png

Tango-dialog-warning.png

这篇文章或章节的内容已经过期.

请通过更新这篇文章和改正错误帮助改善 wiki。

小贴士: 建议在新建的虚拟网桥(例如br0)配置中打开生成树(STP-Spanning Tree Protocol)功能,以避免产生潜在的桥接环路。You can automatically enable STP by appending POST_UP="brctl stp $INTERFACE on" to the netcfg profile.

客户机配置

现在可以在虚拟机中激活桥接网卡了。

如果还有其它的 Linux 虚拟机要使用这个桥接网卡,可以把下面这段代码复制到该虚拟机的.xml配置文件中:

 [...]
 <interface type='bridge'>
   <source bridge='br0'/>
   <mac address='24:42:53:21:52:49'/>
   <model type='virtio' />
 </interface>
 [...]

这段代码在虚拟机中激活了一个virtio设备,因而在Windows虚拟机中需要为它安装额外的驱动程序(位于Windows KVM VirtIO drivers)或者移去<model type='virtio' />这行:

 [...]
 <interface type='bridge'>
   <source bridge='br0'/>
   <mac address='24:42:53:21:52:49'/>
 </interface>
 [...]

参阅