Libvirt (简体中文)
Related articles
libvirt 是一个虚拟化 API 和虚拟机(VMs)管理后台,支持远程或本地访问,支持多种虚拟化后端 (QEMU/KVM, VirtualBox, Xen,等等) 。本文并不打算涉及有关 libvirt 的方方面面,仅讨论那些与通常的认知不同的地方或文档论述不详之处。
安装
服务器端需要从 官方仓库 同时安装下列包,它们组合起来共同作为虚拟化后端:
- libvirt
- virt-manager (一个图形界面程序,用于安装和管理虚拟机)(译注:非必须。如果不需要在服务器本地做GUI管理可不安装,已实证。)
- bridge-utils 或 dnsmasq (用于网络共享)
客户端需要安装下列包:
- virt-manager
- virtviewer(译注:非必须)
为 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
认证策略
创建下列文件,使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"
为 QEMU 打开 KVM 加速
以惯常方式(不带 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-manager 和 virsh 作为虚拟机管理工具,则很简单即可实现。
开机自动启动的命令:
$ virsh autostart <domain>
禁用开机自动启动的命令:
$ virsh autostart --disable <domain>
virt-manager 中,在引导 选项页下同样也有个自动启动勾选项。
使用
创建一个新虚拟机
创建新虚拟机需要准备安装介质,通常是一个标准的.iso
文件。将其复制到/var/lib/libvirt/images/
目录即可(或者在 virt-manager 中新建一个 存储池 目录,将其复制到该目录)。
然后运行virt-manager
连接到服务器,右击连接、选择新建。 输入自定义的连接名,选择 本地安装介质,按照向导继续。
在第四步中,应当取消 分配全部磁盘空间 选项。当虚拟机并不需要使用全部磁盘时,这样做可以节约空间,但也会导致磁盘碎片增多。此时,应密切关注宿主机的剩余磁盘空间总量,否则很容易导致为虚拟机分配了过量磁盘空间。
在第五步中,打开 高级选项 并确认 虚拟类型 选择了 kvm。如果该选项无效,查阅前文 为 QEMU 打开 KVM 加速 一节
在virt-manager中创建存储池
首先连接到一个现有的服务器。连接后,右击详情,进入存储,点击左下方的+图标,然后按向导指示继续。
用virt-manager管理VirtualBox
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=true
或rsync -S
参数),然后就可以将原始镜像融合进快照。
# virsh blockpull --domain archey --path /vms/archey.snapshot1
现在,数据块被从原始镜像中抽离出来,/vms/archey.snapshot1
这个文件成为新的虚拟机磁盘的镜像文件。查看其磁盘容量就知道。这些都完成后,原始磁盘镜像/vms/archey.img
以及快照元数据就可以安全地删除了。
virsh blockcommit
是blockpull
的反向操作,不过似乎在当前的 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
另外还要编辑/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
使用 Python
libvirt-python软件包中的/usr/lib/python2.7/site-packages/libvirt.py
提供了python2 的 API。
/usr/share/doc/libvirt-python-your_libvirt_version/examples/
中给出了若干通用范例。
#! /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创建网桥。 应当创建一个 Netctl 或 Systemd-networkd 的配置文件配置新创建的网桥,例如(使用 DHCP 的配置):
/etc/netctl/br0
Description="Bridge connection for kvm" Interface=br0 Connection=bridge BindsToInterfaces=(eno1) IP=dhcp
客户机配置
现在可以在虚拟机中激活桥接网卡了。
如果还有其它的 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> [...]