libvirt学习笔记
libvirt是广泛使用的、通用虚拟化管理工具,它提供多种命令行工具、多种语言的编程API。
libvirt的目标是:提供一个通用、稳定的抽象层,来安全有效的远程管理一个节点(node)之上的域(domains),因此它需要提供全套的API来完成管理,这些API必须完成Domain的创建、修改、配置、监控、迁移、停止。
libvirt可以管理的虚拟化机制(hypervisor或container)包括:KVM/QEMU、Xen、LXC、OpenVZ、VirtualBox、VMware ESX/GSX、VMware Workstation/Player、Microsoft Hyper-V、IBM PowerVM。
术语 | 说明 |
node | 一台物理机器 |
hypervisor |
node上面的一个软件层,它能虚拟化node,并在其上建立多个虚拟机 libvirt通过所谓driver和各种不同的hypervisor打交道 |
domain | 运行在受hypervisor管理的虚拟化node之上的一个操作系统,当基于容器虚拟化时,则是一个子系统 |
libvirt的二进制组件可能已经随操作系统安装,如果没有,你可以:
1 |
sudo apt-get install libvirt-bin |
可以安装virt-install,这是一个用来创建基于KVM、XEN或者Linux容器的客户机的工具:
1 |
sudo apt-get install virtinst |
可以安装virt-manager,它提供了基于libvirt的图形化管理工具:
1 |
sudo apt-get install virt-manager |
可以安装virt-viewer,它用于连接到虚拟机的Graphical Console:
1 2 3 4 |
# 安装 sudo apt-get install virt-viewer # 使用 virt-viewer -c qemu:///system |
virsh是libvirt提供的一个命令行工具,利用它你可以通过命令行,交互式的管理你的虚拟机(Domain)。使用此命令,你可以创建、暂停、关闭domain,可以列出当前的domain。
libvirt会在宿主机上运行一个libvirtd守护进程,此进程可以被本地/远程的virsh调用。libvirtd则可以直接调用qemu-kvm来操控客户机。大部分virsh命令需要libvirtd处于运行状态才可用。
使用virsh的define、edit、start、shutdown|destroy、reboot、suspend、resumen、undefined子命令,分别可以定义、编辑、启动、关闭、暂停、唤醒、删除Domain。这些命令比较简单,参考virsh命令详解一节。
快照可以分为三个级别:
- 卷管理器(Volume Manager) 级别,例如LVM的Snapsot功能
- 文件系统级别,常用的Ext3不支持,OCFS2支持
- 文件级别,Raw格式的镜像不支持快照,qcow2格式则支持,且快照分为两类:
- 内部快照:保存在qcow2文件内部的快照:
- 虚拟机状态快照(VM State snapshot):整个虚拟机的状态,不仅仅是磁盘
- 磁盘状态快照(Disk State snapshot):仅仅针对磁盘的快照
- 外部快照:将原先(Backing)的qcow2镜像设置为只读,新的改变保存到另外的qcow2文件
- 内部快照:保存在qcow2文件内部的快照:
使用virsh save / virsh restore命令,可以仅仅将Domain的内存状态保存,然后停止Domain,最后恢复。恢复时假设磁盘没有任何改动:
1 2 3 4 5 |
# 保存内存快照 virsh save fedora-10 fedora-10.vmstate # 恢复内存快照 virsh restore fedora-10.vmstate |
内部快照、外部快照使用同一组命令来管理的。这些快照默认包含内存、磁盘、设备等全部状态。内部快照示例:
1 2 3 4 5 6 7 8 9 10 11 12 |
# 创建一个快照 virsh snapshot-create fedora-10 # Domain snapshot 1473667716 created # 列出Domain的快照 virsh snapshot-list fedora-10 # Name Creation Time State # ------------------------------------------------------------ # 1473667716 2016-09-12 16:08:36 +0800 running # 创建的是内部快照,可以使用底层命令查看 qemu-img info ~/Vmware/KVM/fedora-10/hda.img |
注意,一旦创建了快照,Domain就不能被undefine。
要删除内部快照,可以执行:
1 2 |
virsh snapshot-delete fedora-10 1473667716 # Domain snapshot 1473667716 deleted |
执行下面的命令创建一个外部快照:
1 2 3 |
# 这里我们仅针对vda磁盘创建了快照,内存状态没有做快照 snapshot-create-as fedora-10 blankos "Initial snapshot" --diskspec=vda,file=/home/alex/Vmware/KVM/fedora-10/blankos.vda.qcow2 --disk-only --atomic |
现在查看客户机关联的块设备:
1 2 3 4 |
virsh domblklist fedora-10 # Target Source # ------------------------------------------------ # vda /home/alex/Vmware/KVM/fedora-10/blankos.vda.qcow2 |
可以发现关联性转移到外部快照上了,原先的磁盘镜像成为Backing file。注意:Domain的后续写操作都发生在新创建的磁盘上
要删除外部快照,执行:
1 |
virsh snapshot-delete fedora-10 --metadata blankos |
我们来创建三个快照:
1 2 3 4 |
DIR=/home/alex/Vmware/KVM/fedora-10 virsh snapshot-create-as fedora-10 snap0 "snap0" --diskspec=vda,file=$DIR/snap0.vda.qcow2 --disk-only --atomic virsh snapshot-create-as fedora-10 snap1 "snap1" --diskspec=vda,file=$DIR/snap1.vda.qcow2 --disk-only --atomic virsh snapshot-create-as fedora-10 snap2 "snap2" --diskspec=vda,file=$DIR/snap2.vda.qcow2 --disk-only --atomic |
查看当前快照:
1 2 |
# 默认的,新创建的快照作为当前快照 virsh snapshot-current fedora-10 --name |
查看快照链(Backing chain):
1 2 3 4 5 6 7 |
virsh snapshot-list fedora-10 --tree # vda.qcow2 是base # snap0 # | # +- snap1 # | # +- snap2 这个是top |
libvrit支持多种方式来管理磁盘的快照链:
方式一:基于blockcommit,合并到base镜像
我们可以清理快照链条,将snap2、snap1、snap0中的变更都提交到vda.qcow2中
1 2 3 |
# 必须在Domain运行着的情况下执行命令 virsh blockcommit fedora-10 vda --base $DIR/vda.qcow2 --top $DIR/snap2.vda.qcow2 --wait --verbose # 目前带--delete参数会导致 error: unsupported flags (0x2) in function qemuDomainBlockCommit |
提交后,可以安全的删除快照及其元数据(snapshot-delete --metadata),libvrit是分开管理backing链和snapshot列表的。
方式二:基于blockpull,合并到top镜像
也可以反过来,把base一直pull到top位置(必须是叶子节点)的snapshot,然后此snapshot就成为完整的磁盘镜像了(不依赖backing镜像):
1 |
virsh blockpull fedora-10 --path $DIR/snap2.vda.qcow2 --base $DIR/vda.qcow2 --wait –verbose |
方法三:基于blockcopy,可以在线迁移磁盘
首先,需要取消Domain定义,将其变为transient的:
1 2 3 4 |
# 导出Domain配置 virsh dumpxml --inactive fedora-10 $DIR/domain.xml # 取消定义 virsh undefine fedora-10 |
然后执行拷贝:
1 2 3 |
# --shallow 浅拷贝,copy.vda.qcow2与snap2.vda.qcow2将具有相同的backing chain即base ⇦ snap0 ⇦ snap1 # --pivot 操作完成后,此Domain改用copy virsh blockcopy --domain fedora-10 vda $DIR/copy.vda.qcow2 --wait --verbose --shallow --pivot |
拷贝完成后,瞬时的Domain使用copy继续运行:
1 2 3 4 |
virsh domblklist fedora-10 # Target Source # ------------------------------------------------ # vda /home/alex/Vmware/KVM/fedora-10/copy.vda.qcow2 |
而原先的磁盘可以迁移走了。
要通过virsh来访问远程宿主机上的Domain时,需要提供URI。URI的格式如下:
1 |
driver[+transport]://[username@][hostname][:port]/[path][?extraparameters] |
URI各部分说明如下:
部分 | 说明 | ||||||||
driver | 驱动,不同驱动对应了不同的Hypervisor | ||||||||
transport |
传输协议,主要包括以下几种:
|
要连接到远程宿主机,可以使用-c选项或者connect子命令:
1 |
virsh -c qemu+ssh://root@zircon.local/system |
使用该transport时,需要注意配置文件:
1 2 3 4 |
# 这些项都是默认值 unix_sock_group = "libvirtd" unix_sock_ro_perms = "0777" unix_sock_rw_perms = "0770" |
也就是说,用户必须加入到libvirtd组,才可以使用unix传输,否则会报错:error: Failed to connect socket to '/var/run/libvirt/libvirt-sock': Permission denied。执行下面的命令添加用户到组:
1 |
sudo usermod -a -G libvirtd alex |
注意:连接到qemu时,不指定主机名默认使用unix socket。
在目标宿主机上,修改配置文件:
1 2 |
# 启用TCP监听 libvirtd_opts="-d -l" |
然后再修改配置文件:
1 2 3 4 5 6 7 |
# 默认TCP监听是禁用的 listen_tcp = 1 # 可以修改监听地址和端口 listen_addr = "0.0.0.0" tcp_port = "16509" # 可以不启用验证,但是缺乏安全性,所有流量都是明文 auth_tcp = "none" |
最后重启libvirtd即可。
相关文章:Linux知识集锦 - cgroup
libvirt基于cgroup来限制客户机对宿主机资源的访问。libvirt不会尝试加载任何controllers,它只会检测哪些controllers被mount。
QEMU驱动支持cpuset, cpu, memory, blkio, devices这几个controller,修改配置文件/etc/libvirt/qemu.conf可以针对QEMU禁用某些controller。
LXC驱动支持 cpuset, cpu, cpuacct, freezer, memory, blkio,devices 这几个controller, 其中cpuacct, devices, memory是必须的,如果这几个controller没有被mount则容器不会被启动。
libvrit引入两个概念,以方便cgroups管理:
- partitions:不包含任何进程的cgroup,仅仅包含资源控制规则,它可以包含多个子目录,这些子目录要么是partition要么是consumers
- consumers:是包含了单个虚拟机/容器进程的cgroup
对于不使用systemd的宿主机,consumers命名规则为 $VMNAME.libvirt-{qemu,lxc} ,其中VMNAME为虚拟机的名称。默认的,所有consumer都挂在名为machine的partition下:
1 2 |
ls /sys/fs/cgroup/cpu/machine # fedora-10.libvirt-qemu ... |
直到cgroups布局后,你就可以直接读写cgroups文件系统,来控制客户机的资源访问。但是virsh也提供了一些命令在运行时控制资源访问。
- 对于CPU访问控制,可以使用virsh schedinfo命令
- 对于块设备的访问控制,可以使用virsh blkiotune命令
- 对于网卡流量的控制,可以使用domiftune或者tc命令
该命令最常见的调用形式为: virsh [OPTION]... <command> <domain> [ARG]... 。其中:
- command 是一个virsh子命令
- domain 是操控的虚拟机的名称、ID或者UUID
- ARG是针对特定子命令的参数
- OPTION为一般性选项
选项 | 说明 |
-c | --connect URI 连接到指定的URI,而不是默认的连接。此选项的效果如同调用了connect子命令 |
-d | --debug LEVEL 设置调试级别,级别范围0-4,默认4 |
-k | --keepalive-interval INTERVAL 设置确认服务器连接未断开的心跳的发送间隔,单位秒,设置为0则不检测 |
-K | --keepalive-count COUNT 确认连接端口之前,发送心跳的次数 |
-l | --log FILE 输出日志到文件 |
-q | --quiet 安静模式,避免不必要的信息打印 |
-t | --timing 为每个命令打印消耗的时间信息 |
子命令 | 说明 | ||
help |
显示帮助信息:
|
||
quit, exit | 退出交互式的Terminal | ||
version | 显示版本信息:libvir库版本、API版本、运行中的hypervisor版本 | ||
cd | 改变当前目录,禁用与交互式的terminal | ||
pwd | 打印当前目录名 | ||
connect |
connect [URI] [--readonly] (重)连接到一个hypervisor,URI指明如何连接到hypervisor,例如: |
||
uri | 打印当前连接到的hypervisor的URI | ||
hostname | 打印hypervisor的主机名 | ||
capabilities | 打印一个描述当前连接到的hypervisor的能力(capabilities)的XML文档 | ||
list | 列出存在的Domain,如果不指定参数,则打印所有运行中的Domain信息 |
子命令 | 说明 | ||
autostart | autostart [--disable] domain 用于配置一个Domain随着宿主机而启动 |
||
console | console domain [devname] [--safe] [--force] 连接到客户机的虚拟串口控制台: devname 设置为一个备选控制台、串口/并口设备的别名,如果不指定则连接到primary控制台 |
||
create | create FILE [--console] [--paused] [--autodestroy] [--pass-fds N,M,...] 从XML文件FILE创建一个Domain。创建XML的简便方法是调用 dumpxml 子命令来获得既有实例的XML配置: --paused 新的Domain将会暂停,不指定则运行 --console 创建后连接到Domain的console --autodestroy 如果virsh断开到libvirt的连接,则自动销毁此domain |
||
define | define FILE 从XML文件FILE定义一个Domain,此Domain会注册,但是不会自动启动。如果Domain已经在运行,则对其配置的变更在下次启动时生效 |
||
undefine | undefine domain [--managed-save] [--snapshots-metadata] [ {--storage volumes | --remove-all-storage} --wipe-storage] 解除一个Domain的定义,如果此Domain正在运行,它会被转换为transient的;如果Domain没有运行,则移除它的配置 |
||
desc | desc domain [[--live] [--config] | [--current]] [--title] [--edit] [--new-desc new_desc_msg] 显示或者修改Domain的描述、标题,标题通常比较简短 |
||
destroy | destroy domain [--graceful] 立即终止一个Domain,客户机将没有反应时间,相当于拔掉机器的电源 --graceful 避免极度的手段销毁(SIGKILL),如果客户机一段时间后没有关闭,返回一个错误消息 |
||
reboot | reboot domain [--mode MODE-LIST] 重启一个Domain,效果类似于执行reboot命令 |
||
reset | reset domain 重置一个Domain,效果类似于按主机上的重置按钮,客户机将没有反应时间 |
||
shutdown | shutdown domain [--mode MODE-LIST] 优雅的关闭Domain,此命令将和客户机协商以关机,因此不一定成功,可能消耗较长时间 |
||
start | start name-or-uuid [--console] [--paused] [--autodestroy] [--bypass-cache] [--force-boot] [--pass-fds N,M,...] 启动一个已经定义的Domain: --paused 此Domain将会暂停 --console 连接到客户机的控制台 --autodestroy 当virsh断开到libvirtd的连接后,自动销毁Domain |
||
suspend | suspend domain 暂停一个运行中的Domain,它会维持在内存中,但不再参与调度 |
||
resume | resume domain 从暂停中恢复 |
||
dumpxml | dumpxml domain [--inactive] [--security-info] [--update-cpu] [--migratable] 输出Domain的XML配置信息到屏幕: --migratable 输出一个可迁移的配置 --inactive dump出Domain下次启动时使用的配置,而不是当前正在使用的配置 --update-cpu 根据宿主机的CPU,更新Domain配置中的CPU部分 |
||
edit | edit domain 编辑一个Domain的XML配置,并在下次启动Domain时生效 |
||
save |
save domain state-file [--bypass-cache] [--xml file] [{--running | --paused}] [--verbose] 保存一个运行中的Domain的内存(而不是磁盘)状态到一个状态文件中,以便后续恢复。一旦被保存,则Domain不再继续运行,分配给Domain的内存可以被其它程序使用。该命令类似于Hibernate功能 state-file 状态文件路径 可以基于domjobinfo子命令监控进度,或者利用domjobabort子命令取消保存,对当前Terminal发送SIGINT(Ctrl + C)也会取消保存 |
||
restore |
restore state-file [--bypass-cache] [--xml file] [{--running | --paused}] 将Domain从virsh save状态中还原 |
||
domblkstat |
domblkstat domain [block-device] [--human] 输出块设备的统计信息 输出列说明: 举例: virsh domblkstat fedora-10 vda |
||
domblkerror |
domblkerror domain 显示块设备错误 |
||
domblkinfo |
domblkinfo domain block-device 显示块设备的尺寸相关信息 |
||
domblklist |
domblkinfo domain block-device 以表格形式打印与Domian相关联的块设备的简要信息 |
||
blockcommit |
blockcommit domain path [bandwidth] {[base] | [--shallow]} [top] [--delete] [--wait [--verbose] [--timeout seconds] [--async]] 减少backing镜像链条的长度,将top(最新的)中的变化提交到backing镜像中去。默认的:
path 磁盘的全限定路径,<target dev='name'/>的name或者<source file='name'/>的file |
||
blockpull |
blockpull domain path [bandwidth] [base] [--wait [--verbose] [--timeout seconds] [--async]] 从backing镜像链生成一个磁盘。默认的:
path 磁盘的全限定路径,<target dev='name'/>的name或者<source file='name'/>的file |
||
blockcopy |
blockcopy domain path dest [bandwidth] [--shallow] [--reuse-external] [--raw] [--wait [--verbose] [{--pivot | --finish}] [--timeout seconds] [--async]] 拷贝磁盘的backing镜像链到dest。默认的:
domain 操作针对的Domain 该命令主要用途是虚拟机的在线磁盘映像拷贝(live disk image copying)或镜像(mirroring),在存储迁移时很有用。应用场景包括:
一个blockcopy操作可以分为两个阶段:
|
||
domifstat |
domifstat domain interface-device 输出网络接口的统计信息 输出列说明: 举例: virsh domifstat fedora-10 tap0 |
||
domif-setlink |
domif-setlink domain interface-device state [--config] 修改网络接口的状态 |
||
domif-getlink |
domif-getlink domain interface-device [--config] 获得网络接口的状态 |
||
domiflist |
domiflist domain [--inactive] 以表格形式打印与Domian相关联的网络接口的简要信息 |
||
dommemstat |
dommemstat domain [--period seconds] [[--config] [--live] | [--current]] 获得运行中的Domain的内存统计信息 |
||
blkdeviotune |
blkdeviotune domain device [[--config] [--live] | [--current]] [[total-bytes-sec] | [read-bytes-sec] [write-bytes-sec]] [[total-iops-sec] | [read-iops-sec] [write-iops-sec]] 查询或者设置Domain的某个块设备的I/O参数: |
||
domiftune |
domiftune domain interface-device [[--config] [--live] | [--current]] [--inbound average,peak,burst] [--outbound average,peak,burst] 查询或者修改网络接口的带宽参数: 举例: virsh domiftune fedora-10 tap0 |
||
schedinfo |
schedinfo domain [[--config] [--live] | [--current]] [[--set] parameter=value]... schedinfo [--weight number] [--cap number] domain 显示或者设置Domain进程在宿主机中调度参数,可用参数: --live 影响正在运行的Domain cpu_shares 处理器占用权重,范围0-262144,负值被转换为正值因此-1即262144,超过最大值都相当于262144 |
||
screenshot |
screenshot domain [imagefilepath] [--screen screenID] 对Domain当前Console进行截屏,并保存到文件 |
||
send-key |
send-key domain [--codeset codeset] [--holdtime holdtime] keycode.. 将keycode的序列转换为按键动作,并发送到Domainkey,可用参数: 举例:
|
子命令 | 说明 |
migrate |
migrate [--live] [--offline] [--direct] [--p2p [--tunnelled]] [--persistent] [--undefinesource] [--suspend] [--copy-storage-all] [--copy-storage-inc] [--change-protection] [--unsafe] [--verbose] [--compressed] [--abort-on-error] domain desturi [migrateuri] [graphicsuri] [listen-address] [dname] [--timeout seconds] [--xml file] 将客户机迁移到另外一台宿主机上,可用参数: 注意:
|
migrate-compcache |
migrate-compcache domain [--size bytes] 设置或者取得在线迁移过程中,重复的用来压缩被传输的内存页的缓存的大小,单位字节 |
migrate-setmaxdowntime |
migrate-setmaxdowntime domain downtime 设置domain在线迁移时,能够容忍的最大宕机时间,单位毫秒 |
migrate-compcache | |
migrate-setspeed |
migrate-setspeed domain bandwidth 设置domain迁移到其它宿主机上时,最大使用的带宽,单位MiB/s |
migrate-getspeed |
migrate-getspeed domain 获取domain迁移时的最大带宽 |
子命令 | 说明 | ||
attach-device |
attach-device domain FILE [[[--live] [--config] | [--current]] | [--persistent]] 为domain添加一个新的设备 |
||
attach-disk |
attach-disk domain source target [[[--live] [--config] | [--current]] | [--persistent]] [--driver driver] [--subdriver subdriver] [--cache cache] [--type type] [--mode 添加一个磁盘,参数与磁盘的XML配置元素对应 |
||
attach-interface |
attach-interface domain type source [[[--live] [--config] | [--current]] | [--persistent]] [--target target] [--mac mac] [--script script] [--model model] [--config] 添加一个磁盘,参数与网络接口的XML配置元素对应 |
||
detach-device |
detach-device domain FILE [[[--live] [--config] | [--current]] | [--persistent]] 移除一个设备 |
||
detach-disk |
detach-disk domain target [[[--live] [--config] | [--current]] | [--persistent]] 移除一个磁盘 |
||
detach-interface |
detach-interface domain type [--mac mac] [[[--live] [--config] | [--current]] | [--persistent]] 移除一个网络接口 |
||
update-device |
update-device domain file [--force] [[[--live] [--config] | [--current]] | [--persistent]] 更新设备的配置,可用参数: |
||
change-media |
change-media domain path [--eject] [--insert] [--update] [source] [--force] [[--live] [--config] | [--current]] 改变光驱或者软驱的媒体(盘),可用参数: 举例:
|
子命令 | 说明 |
net-autostart |
net-autostart network [--disable] 启用/禁用虚拟网络的自动启动 |
net-create |
net-create file 从XML配置创建一个临时的虚拟网络并立即启动 |
net-define |
net-define file 从XML配置文件创建一个永久的虚拟网络 |
net-destroy |
net-destroy network 根据名称或者UUID停止一个虚拟网络 |
net-dumpxml |
net-dumpxml network [--inactive] 导出虚拟网络的XML配置 |
net-edit |
net-edit network 编辑一个虚拟网络的配置 |
net-info |
net-info network 显示一个虚拟网络的详细信息 |
net-list |
net-list [--inactive | --all] [--persistent] [<--transient>] [--autostart] [<--no-autostart>] 显示虚拟网络的列表 |
net-start |
net-start network 启动一个虚拟网络 |
net-undefine |
net-undefine network 取消虚拟网络的定义 |
net-update |
net-update network command section xml [--parent-index index] [[--live] [--config] | [--current]] 更新虚拟网络的指定配置片断,可用参数: |
这些子命令用来管理Domain的快照,快照是Domain的磁盘、内存、设备在某一个时刻的状态,这些状态可以在未来恢复。每个快照由唯一性的名字来识别。
子命令 | 说明 |
snapshot-create |
snapshot-create domain [xmlfile] {[--redefine [--current]] | [--no-metadata] [--halt] [--disk-only] [--reuse-external] [--quiesce] [--atomic] [--live]} 为domain创建一个快照,创建快照期间客户机通常处于暂停状态。新创建的快照将成为当前快照,可以通过子命令snapshot-current查看。子命令参数: |
snapshot-create-as |
snapshot-create-as domain {[--print-xml] | [--no-metadata] [--halt] [--reuse-external]} [name] [description] [--disk-only [--quiesce]] [--atomic] [[--live] [--memspec memspec]] [--diskspec] diskspec]... 以指定的name和description创建快照 |
snapshot-current |
snapshot-current domain {[--name] | [--security-info] | [snapshotname]} 查看和设置当前快照:如果不指定snapshotname,则输出Domain当前快照的XML。否则把snapshotname设置为当前快照 |
snapshot-edit |
snapshot-edit domain [snapshotname] [--current] {[--rename] | [--clone]} 编辑snapshotname的XML信息 |
snapshot-info |
snapshot-info domain {snapshot | --current} 输出当前快照或者指定快照的基本信息 |
snapshot-list |
snapshot-list domain [--metadata] [--no-metadata] [{--parent | --roots | [{--tree | --name}]}] [{[--from] snapshot | --current} [--descendants]] [--leaves] [--no-leaves] p[--inactive] [--active] [--disk-only] [--internal] [--external] 列出Domain所有可用的快照,默认输出列:快照名称、创建时间、Domain的状态 --parent 输出parent列,显示父快照名称 |
snapshot-dumpxml |
snapshot-dumpxml domain snapshot [--security-info] 显示指定快照的XML |
snapshot-parent |
snapshot-parent domain {snapshot | --current} 显示父快照的名称 |
snapshot-revert |
snapshot-revert domain {snapshot | --current} [{--running | --paused}] [--force] 恢复Domain到指定的快照状态,此最后一次快照以来对Domain的变更将消失 |
snapshot-delete |
snapshot-delete domain {snapshot | --current} [--metadata] [{--children | --children-only}] 删除Domian的快照 |
子命令 | 说明 | ||
find-storage-pool-sources |
find-storage-pool-sources type [srcSpec] 返回一个XML,描述所有能够找到的type类型的存储池 |
||
find-storage-pool-sources-as |
find-storage-pool-sources-as type [host] [port] [initiator] 类似上面,host port initiator限制查询条件 |
||
pool-autostart |
pool-autostart pool-or-uuid [--disable] 配置存储池的自动启动 |
||
pool-build |
pool-build pool-or-uuid [--overwrite] [--no-overwrite] 构建一个存储池 |
||
pool-create |
pool-create file 从配置文件定义并启动一个存储池 |
||
pool-create-as |
pool-create-as name --print-xml type [source-host] [source-path] [source-dev] [source-name] [<target>] [--source-format format] 类似上面,但是通过命令行来指定所需参数: |
||
pool-define |
pool-define file 定义,但不启动池 |
||
pool-define-as |
pool-define-as name --print-xml type [source-host] [source-path] [source-dev] [source-name] [<target>] [--source-format format] 类似上面,但是通过命令行来指定所需参数: |
||
pool-destroy |
pool-destroy pool-or-uuid 停止一个存储池,池中的数据不会消失 |
||
pool-delete |
pool-delete pool-or-uuid 销毁池使用的所有资源,但是池本身仍然存在,你可以在其中存储新的卷 |
||
pool-dumpxml |
pool-dumpxml [--inactive] pool-or-uuid 打印池的配置信息 |
||
pool-edit |
pool-edit pool-or-uuid 编辑池的XML配置 |
||
pool-info |
pool-info pool-or-uuid 显示池的基本信息 |
||
pool-list |
pool-list [--inactive] [--all] [--persistent] [--transient] [--autostart] [--no-autostart] [[--details] [<type>] 列出libvirt所知道的全部存储池 |
||
pool-name pool-uuid |
pool-name uuid 显示指定uuid对应的池名称,或者显示池名称对应的UUID |
||
pool-refresh |
pool-refresh pool-or-uuid 刷新池中卷的列表 |
||
pool-start |
pool-start pool-or-uuid 启动一个存储池 |
||
pool-undefine |
pool-undefine pool-or-uuid 解除一个存储池的定义 |
||
vol-create |
vol-create pool-or-uuid FILE [--prealloc-metadata] 在池中创建一个卷,对于基于目录/文件系统的池,卷的本质就是一个镜像文件。可用参数: 示例: vol-create default definitions/volumes/fedora-10.xml |
||
vol-create-from |
vol-create-from pool-or-uuid FILE [--inputpool pool-or-uuid] vol-name-or-key-or-path [--prealloc-metadata] 创建一个卷,使用另外一个卷vol-name-or-key-or-path作为输入 |
||
vol-create-as |
vol-create-as pool-or-uuid name capacity [--allocation size] [--format string] [--backing-vol vol-name-or-key-or-path] [--backing-vol-format string] [--prealloc-metadata] 创建一个卷,从命令行参数读取配置信息
|
||
vol-clone |
vol-clone [--pool pool-or-uuid] vol-name-or-key-or-path name [--prealloc-metadata] 克隆一个既有的卷,没有vol-create-from强大但是比它简单。可用参数: |
||
vol-delete |
vol-delete [--pool pool-or-uuid] vol-name-or-key-or-path 删除一个卷,底层的镜像文件将被删除,示例:
|
||
vol-upload |
vol-upload [--pool pool-or-uuid] [--offset bytes] [--length bytes] vol-name-or-key-or-path local-file 上传本地文件的内容到一个卷,可用参数: |
||
vol-download |
vol-download [--pool pool-or-uuid] [--offset bytes] [--length bytes] vol-name-or-key-or-path local-file 下载存储卷中的内容到本地文件 |
||
vol-wipe |
vol-wipe [--pool pool-or-uuid] [--algorithm algorithm] vol-name-or-key-or-path 擦除一个卷的内容,可用参数: |
||
vol-dumpxml |
vol-dumpxml [--pool pool-or-uuid] vol-name-or-key-or-path 打印卷的XML配置,示例:
|
||
vol-info |
vol-info [--pool pool-or-uuid] vol-name-or-key-or-path 显示卷的基本信息 |
||
vol-list |
vol-list [--pool pool-or-uuid] [--details] 列出一个存储池中的卷,示例:
|
||
vol-pool |
vol-pool [--uuid] vol-key-or-path 根据卷的名称或者路径,返回其所在存储池的信息 |
||
vol-path |
vol-path [--pool pool-or-uuid] vol-name-or-key 返回指定卷的路径 |
||
vol-name vol-key |
vol-name vol-key-or-path 查询卷的名称或者key |
||
vol-resize |
vol-resize [--pool pool-or-uuid] vol-name-or-path pool-or-uuid capacity [--allocate] [--delta] [--shrink] 重新设定卷的容量,以字节为单位,可用参数: |
模拟器QEMU和hypervisor KVM可以被libvirt管理。
如果driver检测到/usr/bin/qemu-system-*则QEMU可用;如果driver检测到设备节点/dev/kvm和可执行文件/usr/bin/qemu-kvm则支持KVM全虚拟化和客户机硬件加速。
QEMU的驱动是一个多实例驱动,包含一个系统级别的特权驱动(system实例)和多个用户级别的非特权驱动。驱动的URI的协议名为qemu,URI示例:
1 2 3 4 5 6 7 8 9 10 11 12 |
# 本地访问per-user的实例 qemu:///session # 本地访问per-user的实例 qemu+unix:///session # 本地访问系统级实例 qemu:///system # 本地访问系统级实例 qemu+unix:///system # 基于 TLS/x50的远程访问 qemu://example.com/system # 基于SSH隧道远程访问 qemu+ssh://root@example.com/system |
virsh domxml-from-native 命令可以将QEMU命令行选项转换为libvirt的Domain配置格式:
- 将QEMU命令行保存到文件qemu.cmd: /usr/bin/qemu-system-x86_64 -name fedora-10 -enable-kvm -cpu Haswell -daemonize -display none -m 512 -drive file=/home/alex/Vmware/KVM/fedora-10/hda.img,index=0,media=disk,if=virtio -netdev bridge,id=tap0,br=br0 -device virtio-net-pci,netdev=tap0,mac=DE:AD:BE:EF:F1:00
- 执行命令: virsh domxml-from-native qemu-argv ~/Vmware/KVM/fedora-10/qemu.cmd ~/Vmware/KVM/fedora-10/domain.xml
生成的配置文件内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'> <name>fedora-10</name> <uuid>51480ab5-864e-4eb7-9e1c-55b56105139e</uuid> <memory unit='KiB'>524288</memory> <currentMemory unit='KiB'>524288</currentMemory> <vcpu placement='static'>1</vcpu> <os> <type arch='x86_64' machine='pc'>hvm</type> </os> <features> <acpi/> </features> <cpu mode='custom' match='exact'> <model fallback='allow'>Haswell</model> </cpu> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>destroy</on_crash> <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> <disk type='file' device='disk'> <driver name='qemu' type='raw'/> <source file='/home/alex/Vmware/KVM/fedora-10/hda.img'/> <target dev='vda' bus='virtio'/> </disk> <controller type='usb' index='0'/> <controller type='pci' index='0' model='pci-root'/> <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> <graphics type='sdl'/> <video> <model type='cirrus' vram='9216' heads='1'/> </video> <memballoon model='virtio'/> </devices> <qemu:commandline> <qemu:arg value='-daemonize'/> <qemu:arg value='-display'/> <qemu:arg value='none'/> <qemu:arg value='-netdev'/> <qemu:arg value='bridge,id=tap0,br=br0'/> <qemu:arg value='-device'/> <qemu:arg value='virtio-net-pci,netdev=tap0,mac=DE:AD:BE:EF:F1:00'/> </qemu:commandline> </domain> |
可以看到,很多QEMU选项没有对应到常规的Domain配置元素,而是使用qemu:commandline的形式,在启动客户机的时候直接传递给QEMU了。因此,新建客户机时,不要使用这种导入配置的方法,而应调用libvirt API或者手工创建Domain的XML配置。
注意:virsh自动导入得到XML配置存在不少错误,需要调整后才能使用。上例修改后的配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'> <name>fedora-10</name> <memory unit='KiB'>524288</memory> <currentMemory unit='KiB'>524288</currentMemory> <vcpu placement='static'>1</vcpu> <os> <type arch='x86_64' machine='pc'>hvm</type> </os> <features> <acpi/> </features> <cpu mode='custom' match='exact'> <model fallback='allow'>SandyBridge</model> </cpu> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>destroy</on_crash> <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <!-- 镜像格式要设置对 --> <source file='/home/alex/Vmware/KVM/fedora-10/hda.img'/> <target dev='vda' bus='virtio'/> <boot order='1'/> <!-- 要指定启动顺序,否则不会从此硬盘启动系统 --> </disk> <controller type='usb' index='0'/> <controller type='pci' index='0' model='pci-root'/> <!-- 把基于qemu:commandline的网络配置改为标准的Domain配置方式 --> <interface type='bridge'> <mac address='DE:AD:BE:EF:F1:00'/> <source bridge='br0'/> <target dev='tap0'/> <model type='virtio'/> </interface> <!-- 添加串口控制台配置,去掉视频相关配置 --> <serial type='pty'> <target port='0'/> </serial> <console type='pty'> <target type='serial' port='0'/> </console> <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> <memballoon model='virtio'/> </devices> </domain> |
类似的,可以把Domain配置文件转换为QEMU命令行:
1 |
virsh domxml-to-native qemu-argv ~/Vmware/KVM/fedora-10/domain.xml |
libvirt使用XML文件描述一个Domain的全部配置信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<!-- 任何Domain配置的根元素都是domin,它有两个属性: type 驱动(hypervisor)的类型,可选值:xen | kvm | qemu | lxc | kqemu id 正在运行的Domain的唯一标识,整数。非活动Domain没有id --> <domain type='kvm' id='1'> <!-- 在单个node下唯一的虚拟机名字 --> <name>fedora-10</name> <!-- RFC 4122兼容的、虚拟机的全局唯一标识,如果在定义/创建虚拟机时不指定,则会自动生成一个 --> <uuid>4dea22b31d52d8f32516782e98ab3fa0</uuid> <!-- 虚拟机的简短描述,可以多行 --> <title>A short description</title> <!-- 虚拟机的描述--> <description>Some human readable description</description> <!-- 元数据:由应用程序使用,子树必须使用应用程序自己的名字空间 --> <metadata> <app1:foo xmlns:app1="http://app1.org/app1/">..</app1:foo> <app2:bar xmlns:app2="http://app1.org/app2/">..</app2:bar> </metadata> </domain> |
下面介绍如何配置Domain各方面的细节。
虚拟机可以不同的方式启动,各有其优缺点。
对于全虚拟化的hypervisor可以选择通过BIOS启动,BIOS定义启动优先级,来确定从软盘、硬盘、光驱还是网络获取启动镜像(boot image)。配置示例:
1 2 3 4 5 6 7 8 9 10 |
<os> <type>hvm</type> <loader readonly='yes' secure='no' type='rom'>/usr/lib/xen/boot/hvmloader</loader> <nvram template='/usr/share/OVMF/OVMF_VARS.fd'>/var/lib/libvirt/nvram/guest_VARS.fd</nvram> <boot dev='hd'/> <boot dev='cdrom'/> <bootmenu enable='yes' timeout='3000'/> <smbios mode='sysinfo'/> <bios useserial='yes' rebootTimeout='0'/> </os> |
各子元素的说明如下:
元素 | 说明 |
type |
指定需要被启动的虚拟机操作系统的类型: 元素属性: |
loader |
指定虚拟机固件镜像的(宿主机的)绝对路径。用于Xen全虚拟化、QEMU/KVM的BIOS文件路径设置 元素属性: |
boot |
此元素可以出现多次,其dev属性可以是fd/hd/cdrom/network,用来确定优先从哪种设备启动虚拟机,写在最前面的那种设备优先级高 如果同一类型的设备配置了多个,它们将依据总线顺序排列,第一个被标记为可启动的。该元素难以细粒度的控制启动顺序,可以使用Per-device的boot元素代替(后者与此元素互斥) |
smbios | 产生客户机可见的SMBios信息,引用一个sysinfo元素 |
bootmenu | 可以使用一个交互式的启动菜单 |
bios | useserial:可以设置为yes/no,来启用/禁用Serial Graphics Adapter ,SGA允许用户通过串口看到BIOS信息 rebootTimeout 如果启动失败,多久重启,单位毫秒,-1禁止重启 |
当启动基于容器虚拟化的Domain时,需要指定一个init程序:
1 2 3 4 5 6 7 8 |
<os> <type arch='x86_64'>exe</type> <!-- init binary --> <init>/bin/systemd</init> <!-- argumsnts --> <initarg>--unit</initarg> <initarg>emergency.service</initarg> </os> |
如果你要启用user namespace映射,可以:
1 2 3 4 5 |
<idmap> <!-- start容器内第1个用户的ID,target容器内第1个用户映射到宿主机的用户的ID,count容器最多映射宿主机多少用户--> <uid start='0' target='1000' count='10'/> <gid start='0' target='1000' count='10'/> </idmap> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<os> <smbios mode='sysinfo'/> </os> <!-- type属性必须,它的值决定子元素第布局--> <sysinfo type='smbios'> <bios> <entry name='vendor'>LENOVO</entry> </bios> <system> <entry name='manufacturer'>Fedora</entry> <entry name='product'>Virt-Manager</entry> <entry name='version'>0.9.4</entry> </system> <baseBoard> <entry name='manufacturer'>LENOVO</entry> <entry name='product'>20BE0061MC</entry> <entry name='version'>0B98401 Pro</entry> <entry name='serial'>W1KS427111E</entry> </baseBoard> </sysinfo> |
配置示例如下:
1 2 3 4 5 |
<vcpu placement='static' cpuset="1-4,^3,6" current="1">2</vcpu> <vcpus> <vcpu id='0' enabled='yes' hotpluggable='no' order='1'/> <vcpu id='1' enabled='no' hotpluggable='yes'/> </vcpus> |
此元素定义客户机最大的虚拟CPU的数量,有效值的范围是1-hypervisor支持的最大数量。属性说明如下:
属性 | 说明 |
cpuset |
逗号分隔的,Domain进程及虚拟CPU默认能够Pin到的物理CPU序号。可以用-指定范围,^进行排除 Domain进程及虚拟CPU的Pin策略可以由cputune指定,如果cputune的emulatorpin属性被设置,则当前属性被忽略 |
current |
启用比最大数量更少的虚拟CPU |
placement |
指定Domain进程的CPU placement mode,static/auto |
此元素控制每个单独虚拟CPU的状态,每个vcpu子元素对应一个虚拟CPU,vcpu子元素的属性说明如下:
属性 | 说明 |
id | 虚拟CPU的标识符,libvirt在其它地方(例如pinning)引用之。有效值范围0到最大虚拟CPU数-1之间 |
enabled | 控制此虚拟CPU是否启用,yes/no |
hotpluggable | 此虚拟CPU是否可以热拔插,注意,所有enabled=no的CPU都是可以热拔插的,yes/no |
order | 此虚拟CPU的顺序号,此值越小,则CPU越先被热插 |
cputune元素可以对Domain的虚拟CPU进行微调,配置示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<cputune> <vcpupin vcpu="0" cpuset="1-4,^2"/> <vcpupin vcpu="1" cpuset="0,1"/> <vcpupin vcpu="2" cpuset="2,3"/> <vcpupin vcpu="3" cpuset="0,4"/> <emulatorpin cpuset="1-3"/> <iothreadpin iothread="1" cpuset="5,6"/> <iothreadpin iothread="2" cpuset="7,8"/> <shares>2048</shares> <period>1000000</period> <quota>-1</quota> <emulator_period>1000000</emulator_period> <emulator_quota>-1</emulator_quota> <iothread_period>1000000</iothread_period> <iothread_quota>-1</iothread_quota> <vcpusched vcpus='0-4,^3' scheduler='fifo' priority='1'/> <iothreadsched iothreads='2' scheduler='batch'/> </cputune> |
各子元素说明如下:
元素 | 说明 |
vcpupin | 指定虚拟CPU与物理CPU之间的Pin关系。不指定的情况下,虚拟CPU可以Pin到所有物理CPU |
emulatorpin | 模拟器线程被Pin到哪些物理CPU,模拟器线程是Domain执行序列中除了虚拟CPU、IO线程之外的部分 如果此属性未指定,且vcpu的cpuset属性没有设置,则默认Pin到所有物理CPU |
iothreadpin | IO线程被Pin到哪些物理CPU 如果此属性未指定,且vcpu的cpuset属性没有设置,则默认Pin到所有物理CPU |
shares | 此Domain占用CPU时间的权重,这是一个相对值,它对应的具体时长取决于其它虚拟机的设置 2048比1024多获得1倍CPU时间 |
period |
用来指定强制的interval,单位毫秒,可取值 [1000, 1000000]之间。在一个period内,Domain中的每个虚拟CPU消耗的带宽不得超过quota 仅QEMU 0.9.4+、LXC 0.9.10+支持 |
quota | 用来指定最大允许带宽,单位毫秒,可取值 [1000, 18446744073709551],负值表示不限制 |
emulator_period | 与上面类似,但是针对模拟器线程 |
emulator_quota | |
iothread_period | 与上面类似,但是针对IO线程 |
iothread_quota | |
vcpusched | 指定特定虚拟CPU的调度类型: scheduler,调度类型,可选batch, idle, fifo, rr vcpus,针对的虚拟CPU priority,对于实时调度器fifo, rr必须,值范围一般1-99之间,取决于宿主机内核 |
iothreadsched | 与上面类似 |
IO线程是一种专门的事件循环线程,用于提高磁盘Block I/O的scalability,这些线程会分配给支持的磁盘设备。每个物理CPU只有1-2个IO线程,每个IO线程也可能分配给多个磁盘设备。配置示例:
1 2 3 4 5 6 7 8 9 10 |
<!-- 分配给Domain使用的IO线程数--> <iothreads>4</iothreads> <!-- 定义每个IO线程的ID --> <iothreadids> <iothread id="2"/> <iothread id="4"/> <iothread id="6"/> <iothread id="8"/> </iothreadids> |
配置示例如下:
1 2 3 |
<maxMemory slots='16' unit='KiB'>1524288</maxMemory> <memory unit='KiB'>524288</memory> <currentMemory unit='KiB'>524288</currentMemory> |
各元素说明如下:
元素 | 说明 |
memory | 在启动时,分配给Domain的内存的数量 unit,单位,Ki按1024,K按1000计,可用B|KB|MB|GB|TB dumpCore,在Domain崩溃后,是否包含其内存映像到生成的coredump中,仅QEMU |
maxMemory | 运行期间允许的最大内存,仅QEMU |
currentMemory | 当前实际分配给Domain的内存,默认与memory相同 |
memoryBacking元素控制虚拟内存页如何映射到宿主机的内存页,配置示例:
1 2 3 4 5 6 7 8 9 |
<memoryBacking> <hugepages> <!-- 为了除4之外的numa节点分配1G的巨页 --> <page size="1" unit="G" nodeset="0-3,5"/> <page size="2" unit="M" nodeset="4"/> </hugepages> <nosharepages/> <locked/> </memoryBacking> |
子元素说明如下:
元素 | 说明 |
hugepages |
在Linux 64位系统里面,默认内存是以4K的页面(Page)来管理的,当系统有非常多的内存的时候,管理这些内存的消耗就比较大。HugePage使用2M大小的页面来减小管理开销。HugePage管理的内存并不能被Swap,这就避免了swap引发的性能问题。如果系统经常碰到因为swap引发的性能问题可以考虑启用HugePage 告知hypervisor,客户机的内存基于hugepage而不是宿主机Native页大小来分配。从1.2.5开始,可以为每个numa节点更加细致的设置huagepages: |
nosharepages | nosharepages,用于提示hypervisor禁止此Domain的共享页面(内存合并,KSM) |
locked |
如果hypervisor支持,设置此元素可以禁止属于Domain的内存页被swap out 对于QEMU/KVM,使用此设置前你需要设置memtune的hard_limit,并且设置maxMemory=Domain所需内存+QEMU进程本身所需内存。注意:启用locked且设置过多的内存可能导致宿主机内核内存溢出 |
memtune提供Domain的内存微调参数,如果不设置这些参数,则使用OS提供的默认值。对于QEMU/KVM,这些参数限制包含QEMU进程本身的内存消耗
1 2 3 4 5 6 |
<memtune> <hard_limit unit='G'>1</hard_limit> <soft_limit unit='M'>128</soft_limit> <swap_hard_limit unit='G'>2</swap_hard_limit> <min_guarantee unit='bytes'>67108864</min_guarantee> </memtune> |
子元素说明如下:
元素 | 说明 |
hard_limit | 限制客户机能够使用的最大内存,对于QEMU/KVM建议不要设置 |
soft_limit | 出现内存争用时的软限制 |
swap_hard_limit | 最大内存 + 交换文件总大小限制 |
min_guarantee | 确保最小低分配给客户机的内存,仅VMware ESX、OpenVZ支持 |
numatune元素通过控制针对Domain进程的numa策略来影响宿主机的性能,配置示例如下:
1 2 3 4 5 |
<numatune> <memory mode="strict" nodeset="1-4,^3"/> <memnode cellid="0" mode="strict" nodeset="1"/> <memnode cellid="2" mode="preferred" nodeset="2"/> </numatune> |
子元素说明如下:
元素 | 说明 |
memory | 如何在numa主机上为Domain分配内存: mode,可选值interleave,strict,preferred,默认strict nodeset,影响的numa节点 |
memnode | 类似,针对单个numa节点设置 |
blkiotune元素能够微调Domain的Blkio cgroup可调整参数,如果不指定此元素,则使用OS默认值。配置示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<blkiotune> <weight>800</weight> <device> <path>/dev/sda</path> <weight>1000</weight> </device> <device> <path>/dev/sdb</path> <weight>500</weight> <read_bytes_sec>10000</read_bytes_sec> <write_bytes_sec>10000</write_bytes_sec> <read_iops_sec>20000</read_iops_sec> <write_iops_sec>20000</write_iops_sec> </device> </blkiotune> |
子元素说明如下:
元素 | 说明 |
weight | Domain的整体I/O权重,值范围[100, 1000],自2.6.39内核之后,值范围[10, 1000] |
device |
此元素可以有多个,用来设置Domain针对宿主机每一个块设备的I/O权重。子元素: |
对CPU型号、特性的要求,以及它的拓扑结构的要求,可以使用如下方式配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<cpu match='exact'> <model fallback='allow'>core2duo</model> <vendor>Intel</vendor> <topology sockets='1' cores='2' threads='1'/> <feature policy='disable' name='lahf_lm'/> </cpu> <cpu mode='host-model'> <model fallback='forbid'/> <topology sockets='1' cores='2' threads='1'/> </cpu> <cpu mode='host-passthrough'> <feature policy='disable' name='lahf_lm'/> </cpu> |
cpu元素是描述客户机CPU需求的容器元素,它的属性如下:
元素 | 说明 | ||
model |
指定客户机要求的CPU型号,可用型号的列表在/usr/share/libvirt/cpu_map.xml 属性列表: |
||
vendor | 设置客户机要求CPU的厂商,可用厂商列在cpu_map.xml | ||
topology | 规定总的CPU插槽数,每个CPU的核心数,每个核心的硬件线程数 | ||
feature | 可以包含多个这样的元素,用来细粒度的规定CPU的特性: name 特性名称 policy 策略:force强制要求此特性,即使宿主机不支持;require如果宿主机支持则要求此特性;optional可有可无;disable此特性在客户机上禁用;forbid如果宿主机支持此特性则客户机失败 |
||
numa |
仅适用于QEMU/KVM,指定客户机的numa拓扑,举例:
每个cell子元素对应一个numa 节点(cell): |
你可能需要覆盖某些事件发生时采取的动作,注意并非所有hypervisors支持所有事件和动作。使用 virsh reboot 或者 virsh shutdown 可以触发事件。配置示例:
1 2 3 4 |
<on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <on_lockfailure>poweroff</on_lockfailure> |
事件类型采用元素表示:
元素 | 说明 |
on_poweroff | 指定客户机请求断开电源时采取的动作 |
on_reboot | 指定客户机请求重启时采取的动作 |
on_crash | 指定客户机崩溃时采取的动作 |
这几种事件都支持的动作包括:
- destroy,终止Domain并释放一切相关资源
- restart,Domain被终止,并以相同的配置再次启动
- preserve,Domain被终止但是其资源被保留供分析
- rename-restart,以另外一个名字重启Domain
on_crash支持额外的动作:
- coredump-destroy,崩溃Domain的core被dump出来,然后destroy
- coredump-restart,崩溃Domain的core被dump出来,然后重启
仅QEMU支持,强制启用/禁止客户机BIOS的电源管理功能:
1 2 3 4 5 6 |
<pm> <!-- 是否启用ACPI的S4睡眠状态 --> <suspend-to-disk enabled='no'/> <!-- 是否启用ACPI的S3睡眠状态 --> <suspend-to-mem enabled='yes'/> </pm> |
Hypervisor能够启用/禁用一些CPU/机器特性。配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<features> <pae/> <!-- 物理地址扩展,允许32位客户机访问超过4GB内存 --> <acpi/> <!-- 对于电源管理有用,例如可以优雅的关闭KVM客户机 --> <apic/> <!-- 支持可编程的中断请求管理 --> <hap/> <!-- 根据state=on|off,启禁硬件辅助paging --> <privnet/> <!-- 总是创建私有的网络命名空间,如果任何网络接口设备被添加,则自动设置。仅和容器虚拟化相关 --> <hyperv> <!-- 调整Windows客户机的性能,仅QEMU2.x --> <relaxed state='on'/> <vapic state='on'/> <spinlocks state='on' retries='4096'/> <vpindex state='on'/> <runtime state='on'/> <synic state='on'/> <reset state='on'/> <vendor_id state='on' value='KVM Hv'/> </hyperv> <kvm> <hidden state='on'/> <!-- 从标准的MSR发现中隐藏KVM的Hypervisor --> </kvm> <pvspinlock state='on'/> <!-- 通知客户机,宿主机支持半虚拟化的自旋锁 --> </features> |
客户机的时间通常是基于宿主机时间来初始化的,大部分OS期望硬件中存储的是UTC时间,然而Windows期望的则是“本地时间”。
配置示例:
1 2 3 4 5 6 |
<clock offset='localtime'> <timer name='rtc' tickpolicy='catchup' track='guest'> <catchup threshold='123' slew='120' limit='10000'/> </timer> <timer name='pit' tickpolicy='delay'/> </clock> |
clock的offset属性控制客户机的时间如何与宿主机同步:
- utc,客户机启动时总是基于UTC时间来同步
- localtime,客户机启动时基于宿主机的timezone配置来同步时间
- timezone,客户机基于指定的时区来同步
- variable,客户机的时钟相对于UTC或者localtime(由basis属性指定,默认utc)具有一定的偏移,偏移量单位秒,由adjustment指定
提供给客户机的所有设备,都在 <devices> 元素中配置。本章后续内容讲述各种设备的XML配置信息。
可以使用下面的元素来指定模拟器全限定的路径:
1 2 3 |
<devices> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> </devices> |
capabilities的XML配置指明了特定Domain类型-体系结构组合对应的最佳模拟器。
任何软盘、硬盘、光盘或者半虚拟化的驱动器,都是通过 disk 元素来指定的。配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
<devices> <!-- 后端支持是文件的磁盘,使用外部快照 --> <disk type='file' snapshot='external'> <!-- xen的驱动微调 --> <driver name="tap" type="aio" cache="default"/> <!-- 磁盘的源——文件的位置 --> <source file='/var/lib/xen/images/fv0' startupPolicy='optional'> <seclabel relabel='no'/> </source> <!-- 磁盘在客户机中的期望设备名,总线类型 --> <target dev='hda' bus='ide'/> <!-- IO节流阀 --> <iotune> <total_bytes_sec>10000000</total_bytes_sec> <read_iops_sec>400000</read_iops_sec> <write_iops_sec>100000</write_iops_sec> </iotune> <!-- 该磁盘可以作为启动盘,顺序2 --> <boot order='2'/> <!-- 启用磁盘加密 --> <encryption type='...'> ... </encryption> <shareable/><!-- 磁盘可以被多个Domain共享--> <serial>...</serial><!-- 指定磁盘序列号 --> </disk> <!-- 该磁盘的源位于网络上 --> <disk type='network'> <!-- QEMU驱动微调,指定AIO基于pthread --> <driver name="qemu" type="raw" io="threads" ioeventfd="on" event_idx="off"/> <!-- 基于sheepdog的网络源 --> <source protocol="sheepdog" name="image_name"> <host name="hostname" port="7000"/><!-- 磁盘源所在的主机 --> </source> <target dev="hdb" bus="ide"/> <boot order='1'/> <transient/> <address type='drive' controller='0' bus='1' unit='0'/> </disk> <disk type='network'> <driver name="qemu" type="raw"/> <source protocol="rbd" name="image_name2"> <host name="hostname" port="7000"/> <snapshot name="snapname"/> <config file="/path/to/file"/> </source> <target dev="hdc" bus="ide"/> <!-- 提供网络身份验证信息 --> <auth username='myuser'> <secret type='ceph' usage='mypassid'/> </auth> </disk> <!-- 定义一个光驱设备 --> <disk type='block' device='cdrom'> <driver name='qemu' type='raw'/> <target dev='hdd' bus='ide' tray='open'/> </disk> <!-- 定义一个光驱设备,使用ISO镜像文件 --> <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <!-- 使用镜像文件 --> <source file='/home/alex/Vmware/KVM/coreos.iso'/> <target dev='hdd' bus='ide'/> <readonly/> </disk> <!-- 从libvirt管理的存储池中取得源 --> <disk type='volume' device='disk'> <driver name='qemu' type='qcow2'/> <source pool="default" volume="coreos.qcow2" /> <target dev='vda' bus='virtio'/> <boot order='1'/> </disk> <!-- 来自iscsi池的源 --> <disk type='network' device='disk'> <driver name='qemu' type='raw'/> <source protocol='iscsi' name='iqn.gmem.cc.example:iscsi-nopool/2'> <host name='example.com' port='3260'/> </source> <auth username='myuser'> <secret type='iscsi' usage='libvirtiscsi'/> </auth> <target dev='vda' bus='virtio'/> </disk> <!-- 来自iscsi池的源,lun与disk不同的是,客户机的请求直接pass through到物理设备 --> <disk type='network' device='lun'> <driver name='qemu' type='raw'/> <source protocol='iscsi' name='iqn.gmem.cc.example:iscsi-nopool/1'> <host name='example.com' port='3260'/> </source> <auth username='myuser'> <secret type='iscsi' usage='libvirtiscsi'/> </auth> <target dev='sdb' bus='scsi'/> </disk> <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/var/lib/libvirt/images/domain.qcow'/> <!-- 多级嵌套的backing store --> <backingStore type='file'> <format type='qcow2'/> <source file='/var/lib/libvirt/images/snapshot.qcow'/> <backingStore type='block'> <format type='raw'/> <source dev='/dev/mapper/base'/> <backingStore/> </backingStore> </backingStore> <target dev='vdd' bus='virtio'/> </disk> </devices> |
属性 | 说明 |
type |
磁盘的来源(source)类型。有效值:file,block,dir,network,volume 其中volume表示磁盘的来源是存储池中的一个卷 |
device |
客户机看到的磁盘类别。有效值:floppy,disk,cdrom,lun,默认disk 仅当type=block|network且protocol=iscsi时;或者type=volume且使用protocol=iscsi、mode=host的source pool时可设置为lun,lun的行为与disk相同,除了来自客户机的SCSI命令被接收并pass through到物理设备。lun仅被raw设备识别,不能被分区识别 |
rawio | 仅当device=lun时使用,是否启用rawio,有效值:yes/no |
snapshot | 指定快照行为: internal 使用内部快照 external 使用外部快照 no 该磁盘不参与快照 |
指定磁盘的来源(source),其包含的属性依赖于disk的type属性:
disk.type | 属性 | 说明 |
file | file | 指定虚拟磁盘对应的镜像文件的全限定路径 |
block | dev | 指定虚拟设备映射到的宿主机块设备的全限定路径 |
dir | dir | 指定宿主机目录,此目录作为客户机的磁盘使用 |
network | protocol | 访问磁盘映像的协议,有效值:nbd、iscsi、rbd、sheepdog、gluster |
name | 如果protocol=rbd、sheepdog、gluster,则此属性必须,用于指定什么卷/镜像被使用 对于protocol=iscsi,name可能包含一个逻辑单元号( logical unit number,LUN),例如xx:iscsi-pool/1,不指定LUN则默认0 |
|
volume | pool | 指定由libvirt管理的存储池(storage pool)的名称,磁盘来源位于此池中 |
volume | 指定用作磁盘来源的,由libvirt关联的存储卷( storage volume )的名称 | |
mode | 指示如何将LUN暴露为磁盘来源: direct host,默认值 |
source子元素可以包含以下子元素:
子元素 | 说明 |
host | 当disk.type=network时,可以包含若干各host子元素,用来指定需要连接的主机。host具有以下属性: name,主机名 port,监听端口 transport,传输协议类型 socket,UNIX套接字路径 |
紧跟着source元素,用于指定磁盘使用的backing store ,backing store是构成磁盘的逻辑成分(类似于QEMU的backing file)。如果不指定此元素,则意味着source是自包含的。backingStore元素的属性列表如下:
属性 | 说明 |
type | backing store使用的磁盘类型,类似于disk.type |
index |
backingStore可以有下列子元素:
元素 | 说明 |
format | 其type属性指定backing store内部的镜像格式,例如raw、qcow2 |
source | 类似于disk.source |
backingStore | 如果此backing store也不是自包含,而依赖于其它backing store时,使用此元素递归的指定 |
此子元素控制虚拟磁盘在什么总线/设备下暴露给客户机。属性如下:
属性 | 说明 |
dev | 磁盘在客户机下的逻辑名称,此名称并不确保映射到相应的设备名称,你只能将其作为设备的“顺序提示” |
bus | 设置模拟的磁盘类型,有效值包括ide、scsi、virtio、xen、usb、sata、sd。如果不指定,bus的值根据dev的风格来推断,例如hda可以推断出ide |
tray | 可移动磁盘(光盘、软盘)的一个状态字段,有效值包括open、closed,默认closed |
removable | 设置USB磁盘的可移除标记,on/off,默认off |
针对单块磁盘进行IO微调,与 blkiotune 功能类似,但是后者针对Domain全局。
目前可设置的微调项都是针对QEMU的IO throttling微调,这些微调由子元素指定,取值0表示无限制。子元素列表:
元素 | 说明 |
total_bytes_sec | 每秒钟I/O吞吐量的限制。total_bytes_sec不能与后两者同时出现 |
read_bytes_sec | |
write_bytes_sec | |
total_iops_sec | 每秒钟I/O操作次数的限制。total_iops_sec不能与后两者同时出现 |
read_iops_sec | |
write_iops_sec | |
total_bytes_sec_max | 与上面类似,但是限制最大值 |
read_bytes_sec_max | |
write_bytes_sec_max | |
total_iops_sec_max | |
write_iops_sec_max | |
size_iops_sec |
与hypervisor驱动相关的更多细节配置,属性列表:
属性 | 说明 |
name type |
如果hypervisor支持多个backend驱动,则name属性指定primary后端驱动的名称,而type则指定一个子类型。例如:
|
cache |
控制IO缓存策略,有效值包括
最后两种几乎不会使用 writethrough、none、directsync的安全性好,只要客户机操作系统是现代且行为正常的 —— 必要时会执行flush writeback的安全性次之,它给提示后端写缓存的存在,依赖于客户机发送必须的flush命令来保证客户机磁盘的数据完整性 —— 这是现代文件系统应有的正常行为。但是,在报告(给客户端应用程序)IO操作完成,到数据提交到宿主机磁盘,存在一个时间窗口。如果宿主机宕机,可能导致数据丢失 unsafe安全性差,和writeback的差异在于,客户机的flush命令被忽略 性能上: writeback > none > writethrough |
error_policy | 当磁盘出现读写错误时hypervisor的处理策略,有效值:stop、report、ignore、enospace |
io |
控制AIO的策略,QEMU支持:
native的性能更好 |
copy_on_read |
当读取backing文件时,是否将读取的内容复制到当前的镜像文件中,当backing文件位于慢速网络中时可以设置为on 仅用于QEMU/KVM |
iothread | 将磁盘分配给Domain的iothreads元素定义的IO线程 |
用于指定该磁盘是可启动的,order属性指定其启动顺序。
指定卷如何被加密。
指定此磁盘不能被客户机修改,对于device=cdrom的设备默认true。
假设hypervisor和OS支持的话,指示此设备可以被多个Domain共享。指定此元素,应当同时禁用磁盘的缓存。
指示当客户机退出时,对磁盘的所有修改将回退。对于某些hypervisor,把磁盘标记为transient会禁止快照与迁移。
指定磁盘的序列号。
指定磁盘的世界范围名称(World Wide Name),此值必须唯一,由16位16进制数字组成。
指定磁盘的生产厂商,不超过8个可打印字符
指定磁盘的产品名称,不超过16个可打印字符
很多设备可以提供一个address 子元素,来指明设备挂载客户机虚拟总线的什么位置上。如果不指定address,libvirt会生成一个合适的地址。该子元素的属性列表如下:
属性 | 说明 |
type | 必须,有效值包括: pci 可配额外属性domain/bus/slot/function/multifunction drive 可配额外属性controller/bus/target/unit ccid 用于智能卡,可配额外属性bus/slot usb 可配额外属性bus/port,其中port位点号分隔的单字节数字,例如1.2或者2.1.3.1 |
bus | 磁盘绑定到的总线,对于PCI范围在0-0xff之间,对于其它为2位的bus号 |
slot | 磁盘绑定到总线上的slot,范围在0x0-0x1f之间,对于其它为2位的slot号 |
function | 磁盘的function号,范围在0-7之间 |
对于disk.type=network,且protocol为rbd、iscsi的磁盘,可以指定此子元素,提供访问磁盘源时使用的凭据。
用于QEMU/KVM,覆盖块设备的属性。属性列表:
属性 | 说明 |
logical_block_size | 报告给客户机的逻辑块大小。对于Linux来说,BLKSSZGET ioctl会返回此值,表示最小单元的磁盘IO大小 |
physical_block_size | 报告给客户机的物理块大小。对于Linux来说,BLKPBSZGET ioctl会返回此值,表示硬件扇区的大小 |
使用filesystem元素可以把宿主机上的目录直接暴露给客户机访问,配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<devices> <filesystem type='template'> <source name='my-vm-template'/><!-- OpenVZ模板名称 --> <target dir='/'/> </filesystem> <filesystem type='mount' accessmode='passthrough'> <driver type='path' wrpolicy='immediate'/> <source dir='/export/to/guest'/> <!-- 指定宿主机目录 --> <target dir='/import/from/host'/> <readonly/> </filesystem> <filesystem type='file' accessmode='passthrough'> <driver name='loop' type='raw'/> <driver type='path' wrpolicy='immediate'/> <source file='/export/to/guest.img'/> <target dir='/import/from/host'/> <readonly/> </filesystem> </devices> |
filesystem元素的属性列表:
属性 | 说明 |
type |
指定文件系统的来源,有效值包括: |
accessmode | 访问源的安全模式,有效值包括: passthrough 默认值,基于客户机用户的权限访问源 mapped 基于hypervisor(QEMU进程)的权限访问源 squash 类似于passthrough,只是忽略chown之类操作的错误 |
子元素列表:
元素 | 说明 |
driver |
指定hypervisor驱动的更多细节,属性列表: 对于LXC,支持type=loop&format=raw,或者type=nbd;QEMU支持type=path|handle,不支持format |
source | 标注宿主机上的资源,该资源暴露为客户机的文件系统,属性列表: name 仅用于filesystem.type=template,指定模板的名字 dir 仅用于filesystem.type=mount,指定宿主机目录 usage 仅用于filesystem.type='ram' 以KiB(可以使用units属性指定单位)限制内存用量 |
target | 对于QEMU,指定文件系统在客户机的挂载点 |
readonly | 文件系统对于客户机是否只读,仅QEMU/KVM |
space_hard_limit | 文件系统对于客户机的容量软硬限制 |
space_soft_limit |
有几种方式(type)来指定客户机能够看到的网络接口,网络接口的容器元素是 interface 。每个interface元素可以拥有一个address子元素,指定其在PCI上的slot。interface元素的属性列表:
属性 | 说明 |
type | 网络接口的类型,有效值: network 虚拟网络 bridge 直接桥接VM到局域网 |
trustGuestRxFilters |
如果设置为true,则宿主机能够检测到并信任来自客户机的关于接口MAC地址变更的报告,并接收filters 对此设置的支持,取决于客户机的网络设备型号,以及宿主机的连接类型。当前只有virtio型号和macvtap宿主机连接类型支持 |
对于基于动态地址分配/无线网络的宿主机获得连接性的虚拟机,推荐此方式。
虚拟网络提供一个其详细信息由一个命名网络定义(named network definition)所描述的连接。依据虚拟网络的转发模式(forward mode)设置,它可能是:
- 完全隔离的,不配置 <forward> 元素
- NAT到一个指定的网络设备或者默认路由,配置 <forward mode='nat'>
- 不基于NAT来路由,配置 <forward mode='route'/>
- 直接连接到宿主机的网络接口(通过macvtap)或桥接设备,配置 <forward mode='bridge|private|vepa|passthrough'/>
对于转发模式设置为bridge | private | vepa | passthrough的网络,宿主机在libvirt管理范围之外应拥有必要的DNS、DHCP服务。对于转发模式设置为isolated | nat |routed的网络,libvirt提供的虚拟网络中包含了DHCP和DNS。虚拟网络自动分配的IP地址范围可以通过命令
1 |
virsh net-dumpxml [networkname] |
得到。一个开箱即用的、称为default的虚拟网络NAT到宿主机默认路由,其IP地址范围是192.168.122.0/24,在宿主机中你可以ifconfig看到一个名为virbr0的网络接口,与这个default虚拟网络有关。要自定义虚拟网络,需要修改其它类型(network XML)的配置文件L。
每个客户机会有一个命名为 vnetN 的tun设备,你可以利用target元素覆盖此命名。
类似于direct类型的接口,network类型的接口可以指定一个virtualport子元素,用于将配置信息转发给vepa(802.1Qbg)或 802.1Qbh兼容的交换机,或Open vSwich虚拟交换机。
配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<devices> <interface type='network'> <!-- 如果接口的source是一个网络,则可以设置soure元素的portgroup属性,一个网络可能定义了多个portgroup, 每个portgroup包含些许不同的配置信息,用于不同类别的网络连接 --> <source network='default'/> </interface> <interface type='network'> <!-- --> <source network='default' portgroup='engineering'/> <target dev='vnet7'/> <!-- 设置虚拟网卡的名称 --> <mac address="00:11:22:33:44:55"/><!-- 设置虚拟网卡的MAC地址 --> <virtualport> <parameters instanceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/> </virtualport> </interface> </devices> |
对于基于静态地址的有线网络的宿主机获得连接性的虚拟机,推荐此方式。
该方式将虚拟机直接桥接到宿主机所在的局域网,libvirt假设宿主机上的网桥设备enslaved了1-N个物理网卡。客户机的IP地址范围与宿主机局域网的IP地址范围一样。
在Linux系统中,网桥通常是标准的Linux主机网桥(host bridge)。如果主机支持Open vSwitch,则可以添加 <virtualport type='openvswitch'/> 子元素以连接到Open vSwitch网桥。
每个客户机会有一个命名为 vnetN 的tun设备,你可以利用target元素覆盖此命名。此tun设备会自动enslaved到宿主机网桥。
配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<interface type='bridge'> <!-- 桥接到宿主机的br0网桥 --> <source bridge='br0'/> </interface> <interface type='bridge'> <source bridge='br1'/> <!-- 设置客户机中虚拟网卡的名称和MAC --> <target dev='vnet7'/> <mac address="00:11:22:33:44:55"/> </interface> <interface type='bridge'> <source bridge='ovsbr'/> <!-- 连接到Open vSwitch --> <virtualport type='openvswitch'> <!-- interfaceid是此虚拟网卡的唯一标识,如果不指定自动生成;profileid作为虚拟网卡的port-profile发送给vSwitch --> <parameters profileid='menial' interfaceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/> </virtualport> </interface> |
提供一个虚拟局域网并NAT到外面的世界,此虚拟网络使用10.0.2.x网段。默认路由10.0.2.2,DNS服务器10.0.2.3,客户机地址从10.0.2.15开始。此网络仅仅用于没有特权的宿主机用户。配置示例:
1 2 3 4 |
<interface type='user'/> <interface type='user'> <mac address="00:11:22:33:44:55"/> </interface> |
如果hypervisor支持,则可以设置虚拟网卡的型号。示例:
1 2 3 |
<interface type='network'> <model type='ne2k_pci'/> </interface> |
QEMU支持的型号包括 ne2k_isa i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio。
可以设置网卡是启用还是断开的:
1 2 3 |
<interface type='network'> <link state='down'/> </interface> |
网络设备、具有网络特性的hostdev设备可以配置一个或者多个IP地址,某些hypervisor会忽略这些配置。配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<devices> <interface type='network'> <source network='default'/> <target dev='vnet0'/> <ip address='192.168.122.5' prefix='24'/> <!-- peer指定点对点连接中对端的IP地址 --> <ip address='192.168.122.5' prefix='24' peer='10.0.0.10'/> <!-- route仅用于LXC --> <route family='ipv4' address='192.168.122.0' prefix='24' gateway='192.168.122.1'/> <route family='ipv4' address='192.168.122.8' gateway='192.168.122.1'/> </interface> <hostdev mode='capabilities' type='net'> <source> <interface>eth0</interface> </source> <ip address='192.168.122.6' prefix='24'/> <route family='ipv4' address='192.168.122.0' prefix='24' gateway='192.168.122.1'/> <route family='ipv4' address='192.168.122.8' gateway='192.168.122.1'/> </hostdev> </devices> |
配置图形(Graphical)设备,可以让你与客户机进行图形化的交互。客户机通常提供一个framebuffer或者text console,作为人机接口。配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 |
<!-- 基于SDL的图形接口,弹出QEMU的图形化控制台窗口 --> <graphics type='sdl' display=':0' xauth='/home/alex/.Xauthority'/> <!-- 基于VNC的图形接口 --> <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' sharePolicy='allow-exclusive'> <listen type='address' address='0.0.0.0'/> </graphics> <graphics type='rdp' autoport='yes' multiUser='yes'/> <graphics type='desktop' fullscreen='yes'/> <graphics type='spice'> <listen type='network' network='rednet'/> </graphics> |
根据强制属性type的取值,grpahics的属性、子元素有所差异:
type | 说明 | ||||||||||||
sdl | 在宿主机的桌面上显示一个窗口,额外属性: display 使用哪个显示器 xauth 验证标识符 fullscreen 是否全屏,yes/no |
||||||||||||
vnc | 启动一个VNC服务器,额外属性: port 监听端口,-1表示自动分配 autoport 表示自动分配端口 passwd VNC密码明文 keymap 使用的keymap passwdValidTo 密码有效期限(UTC),示例'2010-04-09T15:51:00' sharePolicy 显示共享策略,allow-exclusive独占并丢弃其它连接,force-shared禁止独占,ignore无条件允许任何连接 socket 对于QEMU,可以指定一个UNIX domain socket而非TCP/IP |
||||||||||||
spice |
启动一个SPICE服务器,额外属性: 如果SPICE同时配置了普通端口、TLS安全端口。则可以利用channel子元素限制某个通道使用的端口。可用的通道名包括main, display, inputs, cursor, playback, record,smartcard,usbredir。配置示例:
SPICE支持音频、图片、流的压缩。你可以设置以下子元素的compression属性: 配置示例:
可以使用streaming子元素设置流模式,其mode属性可以取值filter, all,off,配置示例:
基于Spice agent的复制/粘贴功能可以利用clipboard子元素设置,默认启用,配置示例:
鼠标模式可以利用mouse子元素设置,mode取值client,server,配置示例:
文件传输功能可以利用filetransfer设置,默认启用,配置示例:
SPICE支持服务器端的基于OpenGL的加速渲染(仅QEMU),配置示例: <gl enable='yes'/> |
||||||||||||
rdp | 启用一个RDP服务器,额外属性: port 监听端口,-1表示自动分配 autoport 表示自动分配端口 replaceUser 布尔值,是否允许多个用户同时连接 |
||||||||||||
desktop | 保留给VirtualBox Domain,配置类似于sdl |
用于指明在何处监听客户机连接。
video是描述视频设备的容器,为了向后兼容,如果配置了graphics却没有配置video,libvirt会根据客户机的类型自动添加一个video。配置示例:
1 2 3 4 5 6 7 8 9 10 |
<!-- 默认第一个配置video是主视频设备,可以用primary属性覆盖 --> <video primary='yes'> <model type='vga' vram='16384' heads='1'> <acceleration accel3d='yes' accel2d='yes'/> </model> </video> <video> <!-- 下面的配置是KVM客户机的默认值 --> <model type='cirrus' vram='16384' heads='1' /> </video> |
子元素说明如下:
元素 | 说明 |
model | type 视频设备类型,可选值:vga、cirrus、vmvga、xen、vbox、qxl、virtio,基于hypervisor来选择 vram 现存容量 heads 设置屏幕的数量 |
acceleration | accel2d 启用2D加速,仅vbox accel3d 启用3D加速,仅vbox、QEMU |
libguestfs是一组工具集,用来(在不启动客户机的情况下)访问、修改虚拟机的磁盘文件,通过libguestfs你可以好对磁盘进行以下操作:
- 查看或者修改文件
- 创建虚拟磁盘
- 改变虚拟磁盘大小
- 执行磁盘备份、克隆等操作
libguestfs支持多种虚拟磁盘格式,包括Vmware、Hyper-V。日常工作中我们主要使用libguestfs提供的命令行guestfish。libguestfs不依赖于libvirt。
与libguestfs类型工具包括:
- kpartx 需要root权限,并且将文件系统挂载到宿主机的内核中。相比之下libguestfs把文件系统隔离在appliance中,安全性高
- vdfuse 该工具类似于kpartx,但是仅仅针对VirtualBox虚拟磁盘
- qemu-nbd 用QEMU提供的工具,基于QEMU支持的磁盘格式(raw、qcow2)构建网络块服务器。libguestfs可以与之配合使用:
1guestfish -a nbd://remote
执行下面的命令安装libguestfs:
1 |
sudo apt-get install libguestfs-tools |
在Ubuntu下,需要执行:
1 |
sudo chmod 0644 /boot/vmlinuz* |
否则在使用过程中你会遇到cp: cannot open '/boot/vmlinuz-4.4.0-38-generic' for reading: Permission denied错误。
执行下面的命令,以编辑一个虚拟磁盘:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# 附加-v参数,可以看到很多调试信息,例如appliance的启动过程日志 guestfish -a vda.qcow2 # 出现提示符 ><fs> # 添加一个磁盘,只能在run之前执行 # add-drive filename [readonly:true|false] [format:..] [iface:..] [name:..] [label:..] [protocol:..] [server:..] add-drive vdb,qcow2 format:qcow2 # 执行run命令,一个appliance(类似于微型虚拟机)会被启动 ><fs> run # 列出设备 ><fs> list-devices # 输出:/dev/sda # 列出分区 ><fs> list-partitions # 输出: # /dev/sda1 # /dev/sda2 # 显示各分区详细信息 ><fs> part-list /dev/sda # [0] = { # part_num: 1 # part_start: 1048576 # part_end: 525336575 # part_size: 524288000 # } # [1] = { # part_num: 2 # part_start: 525336576 # part_end: 17179869183 # part_size: 16654532608 # } # 测试第一个分区是否可启动 ><fs> part-get-bootable /dev/sda 1 # 其它分区相关命令: part-add,part-del,part-disk,part-get-bootable,part-get-gpt-type,part-get-mbr-id, # part-get-name,part-get-parttype,part-init,part-list,part-set-bootable,part-set-gpt-type, # part-set-mbr-id,part-set-name,part-to-dev,part-to-partnum # 操作LVM # 显示物理卷详细信息 pvs-full # 显示逻辑卷组详细信息 vgs-full # 其它LVM相关命令: # lvcreate, lvcreate-free, lvm-canonical-lv-name, lvm-clear-filter, lvm-remove-all, lvm-set-filter, # lvremove, lvrename, lvresize, lvresize-free, lvs, lvs-full, lvuuid, pvcreate, pvremove, pvresize, # pvresize-size, pvs, pvs-full, pvuuid, vg-activate, vg-activate-all, vgchange-uuid, vgchange-uuid-all, # vgcreate, vglvuuids, vgmeta, vgpvuuids, vgremove, vgrename, vgs, vgs-full, vgscan, vguuid # 列出文件系统 ><fs> list-filesystems # 输出: # /dev/sda1: ext4 # /dev/fedora_bogon/root: xfs # /dev/fedora_bogon/swap: swap # 挂载文件系统 ><fs> mount /dev/fedora_bogon/root / # 列出目录 ><fs> ls / # 创建新目录 ><fs> mkdir /temp # 其它支持的文件系统命令包括:cp chown chmod cp # 下载文件到当前目录 download /root/.bash_history test # 上传文件到虚拟磁盘 upload test /temp/test # 查看文件内容 cat /temp/test # 退出 ><fs> quit |
执行run子命令后,需要等待一会,这时libguestfs在启动一个 appliance。再此appliance中会运行一个Linux内核,LVM、ext2等用户空间工具,以及一个守护程序guestfsd。宿主机进程基于RPC与这个守护进程通信,完成对磁盘镜像的操作。
该命令可以把虚拟磁盘挂载到宿主机的目录上:
1 2 3 4 5 6 7 |
# 创建挂载点 mkdir vda # 挂载一个文件系统 guestmount -a vda.qcow2 --rw -m /dev/fedora_bogon/root vda # 现在你可以在宿主机中修改虚拟磁盘中的文件 # 操作完毕后,取消挂载 guestunmount vda |
该命令可以用来快速的创建虚拟机磁盘镜像:
1 2 3 4 5 6 7 8 9 |
# 列出所有支持的客户机类型 virt-builder --list # 创建一个Fedora 24的虚拟磁盘镜像,第一次使用某个客户机类型,需要从网络上下载镜像文件 virt-builder fedora-24 -o fedora-24.qcow2 --format qcow2 --size 20G --hostname fedora-24-01 # 设置主机名 --root-password file:/tmp/pswd # 设置root密码,密码从文件中读取 --install "apache2" # 安装软件 --firstboot /tmp/fb.sh # 第一次启动时执行的脚本 |
命令 | 说明 |
virt-ls | 列出虚拟磁盘中的文件,示例: virt-ls -a vda.qcow2 / |
virt-cat | 查看虚拟磁盘中某个文件的内容,示例: virt-cat -a vda.qcow2 /root/.bashrc |
virt-copy-in | 拷贝目录或者文件到虚拟磁盘中,示例: virt-copy-in -a vda.qcow2 hello /root/ |
virt-copy-out | 从虚拟磁盘中拷贝文件到本地,示例: virt-copy-out -a vda.qcow2 /root/hello . |
virt-df | 显示虚拟磁盘文件系统的剩余空间情况 |
virt-diff | 显示两个Domain或者虚拟磁盘中同一文件的差异 |
virt-edit | 编辑一个文件 |
virt-format | 执行格式化操作 |
virt-inspector | 显示虚拟磁盘中操作系统的版本、以及其它信息 |
virt-make-fs | 从一系列文件,或者tar来创建一个文件系统 |
virt-resize | 改变虚拟磁盘的尺寸 |
virt-sparsify | 稀疏化,虚拟磁盘中的空闲空间将归还给宿主机 |
virt-tar-in | 打包并上传 |
virt-tar-out | 打包并下载 |
virt-win-reg | 导入导出Windows的注册表键值 |
通过配置libvirt的虚拟局域网,可以简化Domain的网络接口配置,比QEMU的脚本方式好很多。此外虚拟局域网还提供DHCP服务。
libvirt引入了virtual network switch的概念,这是运行在宿主机上的软件。客户机可以“插入”到这个交换机上并传递流量。在Linux宿主机上,这个交换机表现为网络接口——默认情况下名字为virbr0,这个接口实质上是一个网桥。
默认情况下虚拟网络交换机工作在NAT模式下,实质上是基于宿主机的iptables设置IP遮掩(不使用SNAT/DNAT),客户机对外通信时,使用宿主机的IP地址。
与NAT不同,这种模式直接转发客户机的IP封包,不进行NAT转换。这需要物理网络的路由器配置适当的路由,让客户机子网的流量流向所在的宿主机。
这种模式下,虚拟网络交换机不把客户机的IP封包转发到真实网络上去。只有宿主机、各客户机之间可以进行通信。
每个虚拟网络交换机可以设置一个用于动态分配的IP地址范围,供连接到此交换机的客户机使用,客户机可以通过DHCP服务自动获得IP地址。
libvirt基于dnsmasq实现DHCP和DNS,对于每个需要DHCP的虚拟网络交换机,libvirt在宿主机上启动一个dnsmasq实例。
除了简单的DNS请求转发,dnsmasq可以做更多的事情:
- 它可以读取宿主机的 /etc/hosts 中条目,来应答DNS查询请求
一个可能的虚拟网络架构的逻辑图如下:
对应的物理拓扑如下:
其中:
- VLAN 1,这个虚拟局域网通过网桥virbr0与eth1进行桥接,并基于NAT连接到真实局域网lan2
- VLAN 2,这个虚拟局域网桥接到virbr0,但是与真实局域网完全隔离
- Guest A,该虚拟机的:
- eth0桥接到宿主机的网桥eth0,后者直接连接到真实网卡pth0,从而与lan1互联
- eth1桥接到virbr0,可以基于NAT受限访问lan2
- Guest B,基于NAT、隔离网络
- Guest C,基于隔离网络
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# 列出所有活动的虚拟局域网,libvrit默认创建一个桥接到virbr0的vlan,名为default virsh net-list # Name State Autostart Persistent # ---------------------------------------------------------- # default active yes yes # 列出所有虚拟局域网 virsh net-list --all # 显示一个虚拟局域网的详细信息 net-info default # Name: default # UUID: e9e308a3-dea9-46dc-bc92-fad27f2a970a # Active: yes # Persistent: yes # Autostart: yes # Bridge: virbr0 # 导出一个虚拟局域网的XML virsh net-dumpxml default # 定义一个新的虚拟局域网 virsh net-define /home/alex/Vmware/KVM/vlans/default.xml # 解除虚拟局域网定义 virsh net-undefine default # 关闭一个虚拟局域网 virsh net-destroy default # 将一个虚拟局域网标记为自动启动 net-autostart default # 启动虚拟局域网,启动后,宿主机上可能出现一个网桥设备 net-start default |
类似于Domain,虚拟局域网的配置也是存放在XML文件中的。每个虚拟局域网对应一个XML配置文件,根元素为network。包括属性:
属性 | 说明 |
ipv6 | yes/no,设置为yes时定义一个虚拟网络,该网络不指定网关的IPv6地址,但是允许客户机-客户机之间的通讯 |
trustGuestRxFilters | yese/no,设置连接到此VLAN的Domain的interface元素的同名属性 |
包含以下基本子元素:
子元素 | 说明 |
name | 此VLAN的短名,此名字被用作构成持久化配置文件的名字 |
uuid | 全局唯一的VLAN标识符,例如3e3fce45-4f53-4fa7-bb32-11f34168b82a |
以下子元素用于配置VLAN的连通性:
子元素 | 说明 | ||||
bridge | 说明如何创建让VLAN连接到物理网络的、宿主机上的网桥设备(虚拟网络交换机): name 网桥设备的名称,这样所有使用此VLAN的客户机可以相互通信,网桥本身可以连接到真实局域网(LAN),取决于宿主机的配置 当使用mode=nat|route指定forward子元素,或者不指定forward子元素(隔离的VLAN)时,如果你不指定name属性,则libvirt会自动创建为网桥生成唯一名称并记住。libvirt推荐以virbr前缀指定name stp 是否启用 Spanning Tree Protocol,默认on delay 网桥转发的延迟秒数,默认0 macTableManager 告知libvirt,如何管理MAC地址表(用于判断数据包的出口),默认值kernel,可设置为libvirt。设置为libvirt可以提高性能,但是导致vlan tagging, multicast等功能失效。需要内核版本3.17+ |
||||
domain | DHCP相关配置: name 定义DHCP服务器的DNS Domain(域名) localOnly 如果设置为yes,则name对应子域名的解析均由VLAN自己的DNS服务器负责,与宿主机的DNS无关;如果设置为no,则无法解析的DNS请求转发给宿主机DNS处理 |
||||
forward |
通过配置此元素,可以让VLAN连接到物理网络。如果不指定此子元素,则VLAN与其它网络隔离(isolated mode) nat 所有连接到此VLAN的客户机、物理网络之间的流量,均forward到宿主机的IP路由栈。从宿主机外部看来,所有客户机均使用宿主机的IP地址。这种mode适合多个客户机需要访问物理网络,而宿主机仅仅允许用于一个公共IP地址的应用场景。如果网络分配的IPv6地址,那么IPv6流量通过plain路由转发,因为IPv6没有NAT的概念。同一VLAN上地址相互通信,不进行NAT route 来自客户机的流量forward到宿主机的IP路由栈,但是不进行NAT。要使用这种方式,LAN路由器必须包含适当的路由表项,将流量返回给宿主机(进而转发给对应客户机)。使用此方式,则客户机的入站/出站会话不受限制 open 类似于route,但是libvirt不会在宿主机上应用任何Firewall规则,也不支持设置dev属性 bridge 桥接到既有网桥,该模式下libvirt不去创建网桥设备: 当配置了
<bridge name='br'/> 时:桥接到一个宿主机既有(非libvirt管理)的网桥 dev
如果不设置dev,默认值为*,这就意味着:从虚拟机中访问任何非10.0.0.0/16网段时,不管路由出口是哪个网卡,封包到达宿主机后,会强制进行SNAT —— 哪怕目标地址在另外一台虚拟机上。这会让Flannel的host-gw模式失效,因为,Flannel的容器网络CIDR肯定不是10.0.0.0/16,这意味着跨节点(虚拟机)的CNI通讯会发生NAT,这显然是不期望发生的。 示例:
|
||||
bandwidth |
配置虚拟网络的QoS,仅支持fowward mode=route|nat或者隔离网络。配置示例:
|
||||
ip |
设置虚拟局域网的子网、网桥(DHCP服务器)的IP地址、DHCP和DNS配置 ip子元素 该元素设置子网、网桥地址:
ip/dhcp子元素 设置DHCP自动分配的地址范围、静态映射MAC地址到IP:
|
||||
dns |
配置虚拟网络的DNS服务器,示例:
|
||||
mac |
设置网桥的MAC地址,示例:
|
当你创建一个新的虚拟网络后,libvrit会在 /etc/libvirt/qemu/networks 目录中生成一个XML文件,该文件基于virsh net-define指定的那个配置文件。
基于NAT转发,启用DHCP,静态映射MAC到IP地址的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<network> <name>default</name> <forward mode='nat'> </forward> <bridge name='virbr0' stp='off' delay='0'/> <mac address='DE:AD:BE:EF:F1:00'/> <ip address='10.0.0.1' netmask='255.0.0.0'> <dhcp> <range start='10.0.0.100' end='10.0.0.200'/> <host mac="DE:AD:BE:EF:F1:10" ip="10.0.0.10" /> <host mac="DE:AD:BE:EF:F1:11" ip="10.0.0.11" /> </dhcp> </ip> </network> |
使用宿主机既有网桥的例子:
1 2 3 4 5 6 |
<network> <name>default</name> <forward mode="bridge"/> <!-- br1是宿主机上既有的网桥,它可能直接连接到物理网络 --> <bridge name="br1"/> </network> |
macvtap直连,需要 2.6.34+内核、仅支持QEMU/KVM。通过macvtap可以通过一组物理网络接口(不需要网桥)之一,直接连接到物理网络。客户机将直接具有物理网络的子网IP地址,并且与物理网络中其它机器互联互通。示例:
1 2 3 4 5 6 7 |
<network> <name>direct-macvtap</name> <forward mode="bridge"> <interface dev="eth0"/> <interface dev="eth1"/> </forward> </network> |
通过存储池,libvirt集中管理物理机器上的存储资源,供客户机使用。存储池被划分为卷(volume),卷则可以作为块设备分配给客户机使用。
libvirt支持以下类型的存储池后端:
后端类型 | 说明 |
目录 | 将宿主机的一个目录作为池看待,该目录中的文件可以包含各种客户机磁盘文件、镜像文件 |
本地文件系统 | 将宿主机上一个格式化好的文件系统作为池看待,文件系统类型可以是ext2,ext3,vfat |
网络文件系统 | 使用远端网络文件系统服务器的导出目录作为存储池。默认为 NFS 网络文件系统 |
逻辑卷 | 使用已经创建好的 LVM 卷组,或者提供一系列生成卷组的源设备,libvirt 会在其上创建卷组,生成存储池 |
磁盘 | 使用磁盘作为存储池 |
iSCSI | 使用 iSCSI 设备作为存储池 |
其它 | SCSI、Multipath、RBD、Sheepdog、Gluster 、ZFS |
通常存储管理员负责维护存储设备,例如NFS服务器。而宿主机的管理员定义存储池,存储池包含了NFS shares到挂载目录的映射。当存储池启动时,libvirt会自动执行挂载操作。一旦存储池启动完毕,NFS share中的文件被当作卷看待,你可以在客户机的Domain配置文件中引用卷的路径,作为块设备的source。
使用NFS时,基于libvirt的API可以在池中创建/删除卷(即NFS上的文件),但是不能超过池的尺寸限制(NFS share有容量控制)。注意不是所有类型的池支持卷的创建/删除操作。
你可以通过XML文件来定义存储池,使用virsh命令可以定义、启动、停止、解除定义池,就像操作Domain、虚拟网络一样。你的配置文件被libvrit修改后,存放在 /etc/libvirt/storage/ 目录中。配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<!-- 基于本地目录的存储池 --> <pool type="dir"> <name>virtimages</name> <target> <path>/var/lib/virt/images</path> </target> </pool> <!-- 基于iscsi的存储池 --> <pool type="iscsi"> <name>virtimages</name> <source> <host name="iscsi.example.com"/> <device path="iqn.2013-06.com.example:iscsi-pool"/> <auth type='chap' username='myuser'> <secret usage='libvirtiscsi'/> </auth> </source> <target> <path>/dev/disk/by-path</path> </target> </pool> <!-- 基于本地文件系统的池 --> <pool type="fs"> <name>sda</name> <source> <!-- 使用的文件系统 --> <device path="/dev/sda3"/> </source> <target> <!-- 指定挂载点 --> <path>/home/alex/Vmware/libvirt/images/sda</path> <permissions> <mode>0777</mode> </permissions> </target> </pool> |
一个存储池配置的根元素为pool,最基础的配置项如下:
1 2 3 4 5 6 7 |
<pool type="iscsi"> <name>virtimages</name> <uuid>3e3fce45-4f53-4fa7-bb32-11f34168b82b</uuid> <allocation>10000000</allocation> <capacity>50000000</capacity> <available>40000000</available> </pool> |
属性和子元素说明如下:
属性/子元素 | 说明 |
@type | 存储池类型,支持取值dir, fs, netfs, disk, iscsi, logical, scsi,mpath,rbd,sheepdog,gluster,zfs |
name | 对于宿主机来说,唯一的名称 |
uuid | 全局唯一的UUID,如果忽略libvirt会自动生成 |
allocation | 当前分配给池的容量,单位字节。创建池时不能使用此元素 |
capacity | 池的总容量,单位字节。创建池时不能使用此元素 |
available | 设置可以分配给新的卷使用的空闲容量。创建池时不能使用此元素 |
存储池具有最多一个(某些类型的池后端没有)source子元素,用于描述池的来源。source包含的内容取决于池的type。 配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!-- disk池配置 --> <source> <device path='/dev/mapper/mpatha' part_separator='no'/> <format type='gpt'/> </source> <!-- SCSI池配置 --> <source> <adapter type='scsi_host' name='scsi_host1'/> </source> <source> <adapter type='scsi_host'> <parentaddr unique_id='1'> <address domain='0x0000' bus='0x00' slot='0x1f' addr='0x2'/> </parentaddr> </adapter> </source> |
各子元素说明如下:
source的子元素 | 说明 |
device | 对于fs, logical, disk, iscsi, zfs类型的池后端,指定存储池的后端物理设备。对于某些池后端,该元素可能出现多次。支持以下属性: path,指向物理设备的全限定路径,或者iSCSI全限定名称(IQN) part_separator,yes/no,用于disk后端 |
dir | 对于 dir, netfs, gluster类型的池后端,指定存储池对应的文件目录。仅能出现一次。支持以下属性: path,目录的全限定名称。对于Samba share,路径不包含起始的斜杠 |
adapter | 对于scsi类型的池后端,指定存储池使用的SCSI适配器 |
host | 对于 netfs, iscsi, rbd, sheepdog, gluster类型的池后端,如果存储池位于远程机器上,指定远程机器的信息,必须和device或者dir元素联用。支持以下属性: name 远程机器的IP或者主机名 port 监听端口,可选,默认值依据远程协议确定 |
auth | 提供访问池后端所需的身份验证信息。支持以下属性: type 可以是chap或者ceph,分别用于iscsi、rbd username 用户名 secret 密码信息(libvirt secret object) |
name | 对于logical, rbd, sheepdog, gluster类型的池后端,依据已命名元素提供池的源 |
format |
指定源的格式 对于fs池后端,指定的是文件系统的类型:auto ext2 ext3 ext4 ufs iso9660 udf gfs gfs2 vfat hfs+ xfs ocfs2 对于netfs池后端,指定的是网络协议的类型:auto nfs glusterfs cifs 对于logical池后端,只能是lvm2 对于disk池后端,指定的是分区表类型:dos dvh gpt mac bsd pc98 sun lvm2 |
vendor | 指定存储设备的供应商信息 |
product | 指定存储设备的产品信息 |
对于dir, fs, netfs, logical, disk, iscsi, scsi, mpath类型池后端,可以具有单个target子元素。该元素描述如何映射存储池的source到宿主机的文件系统命名空间。配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<target> <path>/dev/disk/by-path</path> <permissions> <owner>107</owner> <group>107</group> <mode>0744</mode> <label>virt_image_t</label> </permissions> <timestamps> <atime>1341933637.273190990</atime> <mtime>1341930622.047245868</mtime> <ctime>1341930622.047245868</ctime> </timestamps> <encryption type='...'></encryption> </target> |
各子元素说明如下:
target的子元素 | 说明 |
path | 存储池映射到宿主机目录树的什么位置。对于:
|
permissions | 仅用于fs,dir池后端,指定池对应目录的文件模式 |
timestamps | 提供卷的时间戳信息 |
encryption | 指定卷的加密方式 |
存储卷,通常对应一个文件或者设备节点。注意:当创建了存储池后,池中的镜像文件会被libvirt自动识别,并创建相应的卷定义。
配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<!-- 基于文件的卷 --> <volume type='file'> <name>fedora-10.qcow2</name> <capacity unit='GiB'>16</capacity> <target> <path>/home/alex/Vmware/libvirt/images/fedora-10.qcow2</path> <format type='qcow2'/> <permissions> <mode>0666</mode> </permissions> </target> <backingStore> <path>/home/alex/Vmware/libvirt/images/fedora-base.qcow2</path> <format type='qcow2'/> <permissions> <mode>0666</mode> </permissions> </backingStore> </volume> <!-- 使用LUKS加密的卷--> <volume> <name>MyLuks.img</name> <capacity unit="G">5</capacity> <target> <path>/var/lib/virt/images/MyLuks.img</path> <format type='raw'/> <encryption format='luks'> <secret type='passphrase' uuid='f52a81b2-424e-490c-823d-6bd4235bc572'/> </encryption> </target> </volume> |
一个卷配置的根元素是volume,最基础的配置项如下:
1 2 3 4 5 6 |
<volume type='file'> <name>sparse.img</name> <key>/var/lib/xen/images/sparse.img</key> <allocation>0</allocation> <capacity unit="T">1</capacity> </volume> |
属性和子元素说明如下:
属性/子元素 | 说明 |
@type | 该属性仅能读取,显示卷的实际类型 |
name | 存储池范围内唯一的卷名称 |
key | 用于唯一性的识别卷,该子元素不能在创建卷的时候指定,它总是自动生成的 |
allocation | 指定分配给卷的存储空间,如果卷是稀疏分配的,该值可以小与卷的逻辑大小。可用属性: unit 计量单位 |
capacity | 指定卷的逻辑大小。可用属性: unit 计量单位 |
volume包含一个target子元素,指定卷如何映射到宿主机的文件系统中:
target的子元素 | 说明 |
path | 卷在本地文件系统的绝对路径。该元素为只读,在创建时不能指定,libvirt会根据卷的name元素自动生成此元素 |
format |
指定卷的格式: 对于dir,fs,nfs池后端,支持的卷格式包括: 对于disk池后端,支持的卷格式包括: 对于logical,iscsi,scsi,mpath,rbd,sheepdog,gluster,zfs池后端,不支持该元素 |
permissions | 指定卷的文件模式 |
compat | 兼容性级别,仅仅用于qcow2格式的卷 |
nocow | 关闭COW,仅仅支持btrfs文件系统中的、文件形式的卷 |
features | 特定于format的配置项 |
volume可能包含一个backingStore子元素,用来描述卷的copy-on-write后端存储,配置示例:
1 2 3 4 5 6 7 8 9 10 |
<backingStore> <path>/var/lib/virt/images/master.img</path> <format type='raw'/> <permissions> <owner>107</owner> <group>107</group> <mode>0744</mode> <label>virt_image_t</label> </permissions> </backingStore> |
在不同宿主机之间迁移客户机是比较复杂的问题,为了应对不同的需求,libvirt实现了多种解决方案。
从数据传输的角度来看,libvirt支持两种类型的迁移:
传输类型 | 说明 |
native |
使用Hypervisor本身的数据传输机制,直接在源、目标宿主机之前进行迁移。该方式可能不支持加密,但是需要最少的数据传输量 可能需要针对Hypervisor进行手工的网络相关的配置,某些Hypervisor需要打开大量的端口才能支持并发的迁移操作 |
tunnelled |
利用libvirt内置此RPC通信协议进行数据传输,总是支持数据加密。数据先从源客户机拷贝到源宿主机上的libvirt,再发送到目标主机的libvrit,最终发送给目标客户机,因此需要额外的数据传输量 不需要针对Hypervisor进行网络配置,仅仅需要开放一个端口 如果客户机内存很大,因而脏页变化频繁,额外的数据传输可能导致性能问题 |
从通信控制路径角度来看,libvirt支持三种类型的迁移:
通信控制路径 | 说明 |
受管直接迁移 |
由libvirt客户端进程控制迁移的各个阶段。libvirt客户端必须能够连接到源、目的客户机的libvirt守护进程,并通过身份验证。源、目的客户机上的libvirt守护进程不需要相互通信 如果libvirt客户端崩溃,或者丢失到libvirt守护进程的连接,则源宿主机上的迁移会取消,并在源宿主机上重启客户机的CPU |
受管点对点迁移 |
libvirt客户端仅仅与源宿主机上的libvirt守护进程通信,由后者控制迁移的整个过程。源宿主机的libvirt守护进程会连接到目的宿主机的libvirt守护进程执行迁移操作,libvirt客户端崩溃或者断开不会影响迁移过程的推进 注意,源宿主机上的libvirt守护进程使用自己的身份(通常是root)而不是客户端的身份连接到目标宿主机 |
非受管直接迁移 |
libvirt客户端、守护进程都不控制迁移过程,迁移由底层的Hypervisor负责。libvirt仅仅在Hypervisor的管理层次上触发迁移请求 即使libvirt客户端、守护进程都崩溃,迁移过程还会继续推进 |
迁移时,客户机的内存需要完整的在网络上传输,这可能导致客户机中的敏感信息被嗅探。
如果宿主机有多个网络接口,或者交换机支持Tagged虚拟局域网,最好将客户机的网络流量和迁移/管理网络流量隔离开来。
某些场景下,仅仅依靠网络隔离不能满足安全性需要,这时,需要使用libvirt的tunnelled传输,启用数据加密。
所谓离线迁移,就是把源主机的Domain状态设置为inactive,并且在迁移完毕后,Domain在源主机上继续运行,在目标主机上保持inactive状态。目前离线迁移不支持拷贝非共享存储。
开发虚拟机固件(Open Virtual Machine Firmware)是一个为虚拟机提供UEFI支持的项目。从Linux 3.9开始,配合最近版本的QEMU,能够支持PCI设备直通,例如将显卡直接分配给虚拟机,这样虚拟机就获得接近原生显卡的性能。
对于Intel CPU,除了CPU需要支持VT-x之外,还需要支持VT-d(Intel Virtualization Technology for Directed I/O )。此技术改善系统的安全性、可靠性,同时支持提升虚拟化环境下的IO性能。
Intel的VT-d和AMD的AMD-Vi,通称IOMMU。IOMMU特性不但要求CPU支持,主板、BIOS也需要配合。开启IOMMU能够实现PCI直通、内存保护(免于被恶意、缺陷设备错误修改)。
1 |
intel_iommu=on iommu=pt |
设置iommu=pt能够防止内核触碰不能直通的设备。
重启后,使用下面的命令确认IOMMU已经正确启用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
dmesg | grep -i -e DMAR -e IOMMU [ 0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-5.8.0-45-generic root=UUID=66acedc4-69d6-48b2-888c-9516089e004a ro quiet splash net.ifnames=0 biosdevname=0 intel_iommu=on iommu=pt vt.handoff=7 [ 0.010062] ACPI: DMAR 0x0000000073AE3000 0000C8 (v01 INTEL CML 00000002 INTL 01000013) [ 0.223797] Kernel command line: BOOT_IMAGE=/boot/vmlinuz-5.8.0-45-generic root=UUID=66acedc4-69d6-48b2-888c-9516089e004a ro quiet splash net.ifnames=0 biosdevname=0 intel_iommu=on iommu=pt vt.handoff=7 # IOMMU被启用 [ 0.223929] DMAR: IOMMU enabled [ 0.546449] DMAR: Host address width 39 [ 0.546450] DMAR: DRHD base: 0x000000fed90000 flags: 0x0 [ 0.546455] DMAR: dmar0: reg_base_addr fed90000 ver 1:0 cap 1c0000c40660462 ecap 19e2ff0505e [ 0.546456] DMAR: DRHD base: 0x000000fed91000 flags: 0x1 [ 0.546459] DMAR: dmar1: reg_base_addr fed91000 ver 1:0 cap d2008c40660462 ecap f050da [ 0.546460] DMAR: RMRR base: 0x0000007372c000 end: 0x0000007374bfff [ 0.546461] DMAR: RMRR base: 0x00000078000000 end: 0x0000007c7fffff [ 0.546462] DMAR: RMRR base: 0x00000073792000 end: 0x00000073811fff [ 0.546464] DMAR-IR: IOAPIC id 2 under DRHD base 0xfed91000 IOMMU 1 [ 0.546465] DMAR-IR: HPET id 0 under DRHD base 0xfed91000 [ 0.546465] DMAR-IR: Queued invalidation will be enabled to support x2apic and Intr-remapping. [ 0.549640] DMAR-IR: Enabled IRQ remapping in x2apic mode [ 4.330593] iommu: Default domain type: Passthrough (set via kernel command line) [ 4.510270] DMAR: No ATSR found [ 4.510351] DMAR: dmar0: Using Queued invalidation [ 4.510354] DMAR: dmar1: Using Queued invalidation # PCI设备被加入到的分组信息 [ 4.510868] pci 0000:00:00.0: Adding to iommu group 0 [ 4.510888] pci 0000:00:01.0: Adding to iommu group 1 [ 4.510901] pci 0000:00:02.0: Adding to iommu group 2 [ 4.510911] pci 0000:00:04.0: Adding to iommu group 3 [ 4.510928] pci 0000:00:12.0: Adding to iommu group 4 [ 4.510950] pci 0000:00:14.0: Adding to iommu group 5 [ 4.510963] pci 0000:00:14.2: Adding to iommu group 5 [ 4.510975] pci 0000:00:14.3: Adding to iommu group 6 [ 4.510997] pci 0000:00:15.0: Adding to iommu group 7 [ 4.511008] pci 0000:00:15.1: Adding to iommu group 7 [ 4.511031] pci 0000:00:16.0: Adding to iommu group 8 [ 4.511042] pci 0000:00:16.3: Adding to iommu group 8 [ 4.511087] pci 0000:00:1b.0: Adding to iommu group 9 [ 4.511121] pci 0000:00:1b.4: Adding to iommu group 9 [ 4.511161] pci 0000:00:1c.0: Adding to iommu group 10 [ 4.511197] pci 0000:00:1c.5: Adding to iommu group 10 [ 4.511226] pci 0000:00:1d.0: Adding to iommu group 11 [ 4.511265] pci 0000:00:1f.0: Adding to iommu group 12 [ 4.511277] pci 0000:00:1f.3: Adding to iommu group 12 [ 4.511290] pci 0000:00:1f.4: Adding to iommu group 12 [ 4.511301] pci 0000:00:1f.5: Adding to iommu group 12 [ 4.511316] pci 0000:00:1f.6: Adding to iommu group 12 [ 4.511321] pci 0000:01:00.0: Adding to iommu group 1 [ 4.511325] pci 0000:01:00.1: Adding to iommu group 1 [ 4.511330] pci 0000:01:00.2: Adding to iommu group 1 [ 4.511335] pci 0000:01:00.3: Adding to iommu group 1 [ 4.511350] pci 0000:02:00.0: Adding to iommu group 9 [ 4.511363] pci 0000:03:00.0: Adding to iommu group 9 [ 4.511373] pci 0000:04:00.0: Adding to iommu group 10 [ 4.511383] pci 0000:05:00.0: Adding to iommu group 10 [ 4.511392] pci 0000:05:01.0: Adding to iommu group 10 [ 4.511399] pci 0000:05:02.0: Adding to iommu group 10 [ 4.511409] pci 0000:05:04.0: Adding to iommu group 10 [ 4.511435] pci 0000:06:00.0: Adding to iommu group 10 [ 4.511458] pci 0000:3a:00.0: Adding to iommu group 10 [ 4.511471] pci 0000:6e:00.0: Adding to iommu group 10 [ 4.511484] pci 0000:6f:00.0: Adding to iommu group 11 # VT-d被启用 [ 4.511850] DMAR: Intel(R) Virtualization Technology for Directed I/O [ 4.711749] intel_iommu=on |
使用下面的脚本可以更加清楚的看到PCI设备是如何并映射到IOMMU分组的:
1 2 3 4 5 6 7 8 |
#!/bin/bash shopt -s nullglob for g in `find /sys/kernel/iommu_groups/* -maxdepth 0 -type d | sort -V`; do echo "IOMMU Group ${g##*/}:" for d in $g/devices/*; do echo -e "\t$(lspci -nns ${d##*/})" done; done; |
输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
IOMMU Group 0: 00:00.0 Host bridge [0600]: Intel Corporation Device [8086:9b44] (rev 02) # Nvidia显卡被分配在组1 IOMMU Group 1: 00:01.0 PCI bridge [0604]: Intel Corporation Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x16) [8086:1901] (rev 02) 01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GLM [Quadro RTX 5000 Mobile / Max-Q] [10de:1eb5] (rev a1) 01:00.1 Audio device [0403]: NVIDIA Corporation TU104 HD Audio Controller [10de:10f8] (rev a1) 01:00.2 USB controller [0c03]: NVIDIA Corporation TU104 USB 3.1 Host Controller [10de:1ad8] (rev a1) 01:00.3 Serial bus controller [0c80]: NVIDIA Corporation TU104 USB Type-C UCSI Controller [10de:1ad9] (rev a1) # Intel集成显卡被分配在组2 IOMMU Group 2: # 设备ID 00:02.0 VGA compatible controller [0300]: Intel Corporation Device [8086:9bf6] (rev 05) IOMMU Group 3: 00:04.0 Signal processing controller [1180]: Intel Corporation Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem [8086:1903] (rev 02) IOMMU Group 4: 00:12.0 Signal processing controller [1180]: Intel Corporation Comet Lake PCH Thermal Controller [8086:06f9] IOMMU Group 5: 00:14.0 USB controller [0c03]: Intel Corporation Comet Lake USB 3.1 xHCI Host Controller [8086:06ed] 00:14.2 RAM memory [0500]: Intel Corporation Comet Lake PCH Shared SRAM [8086:06ef] # 无线网卡被分到组6 IOMMU Group 6: 00:14.3 Network controller [0280]: Intel Corporation Wi-Fi 6 AX201 [8086:06f0] IOMMU Group 7: 00:15.0 Serial bus controller [0c80]: Intel Corporation Comet Lake PCH Serial IO I2C Controller #0 [8086:06e8] 00:15.1 Serial bus controller [0c80]: Intel Corporation Comet Lake PCH Serial IO I2C Controller #1 [8086:06e9] IOMMU Group 8: 00:16.0 Communication controller [0780]: Intel Corporation Comet Lake HECI Controller [8086:06e0] 00:16.3 Serial controller [0700]: Intel Corporation Device [8086:06e3] # 指纹识别器、三星硬盘被分到组9 IOMMU Group 9: 00:1b.0 PCI bridge [0604]: Intel Corporation Comet Lake PCI Express Root Port #17 [8086:06c0] (rev f0) 00:1b.4 PCI bridge [0604]: Intel Corporation Comet Lake PCI Express Root Port #21 [8086:06ac] (rev f0) 02:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller SM981/PM981/PM983 [144d:a808] 03:00.0 Non-Volatile memory controller [0108]: Silicon Motion, Inc. Device [126f:2262] (rev 03) # 雷电、读卡器被分到组10 IOMMU Group 10: 00:1c.0 PCI bridge [0604]: Intel Corporation Device [8086:06b8] (rev f0) 00:1c.5 PCI bridge [0604]: Intel Corporation Device [8086:06bd] (rev f0) 04:00.0 PCI bridge [0604]: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:15ea] (rev 06) 05:00.0 PCI bridge [0604]: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:15ea] (rev 06) 05:01.0 PCI bridge [0604]: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:15ea] (rev 06) 05:02.0 PCI bridge [0604]: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:15ea] (rev 06) 05:04.0 PCI bridge [0604]: Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] [8086:15ea] (rev 06) 06:00.0 System peripheral [0880]: Intel Corporation JHL7540 Thunderbolt 3 NHI [Titan Ridge 4C 2018] [8086:15eb] (rev 06) 3a:00.0 USB controller [0c03]: Intel Corporation JHL7540 Thunderbolt 3 USB Controller [Titan Ridge 4C 2018] [8086:15ec] (rev 06) 6e:00.0 Unassigned class [ff00]: Realtek Semiconductor Co., Ltd. RTS525A PCI Express Card Reader [10ec:525a] (rev 01) IOMMU Group 11: 00:1d.0 PCI bridge [0604]: Intel Corporation Comet Lake PCI Express Root Port #9 [8086:06b0] (rev f0) 6f:00.0 Non-Volatile memory controller [0108]: Silicon Motion, Inc. Device [126f:2262] (rev 03) # 有线网卡被分到组12 IOMMU Group 12: 00:1f.0 ISA bridge [0601]: Intel Corporation Device [8086:068e] 00:1f.3 Multimedia audio controller [0401]: Intel Corporation Comet Lake PCH cAVS [8086:06c8] 00:1f.4 SMBus [0c05]: Intel Corporation Comet Lake PCH SMBus Controller [8086:06a3] 00:1f.5 Serial bus controller [0c80]: Intel Corporation Comet Lake PCH SPI Controller [8086:06a4] 00:1f.6 Ethernet controller [0200]: Intel Corporation Ethernet Connection (10) I219-LM [8086:0d4e] |
需要注意,IOMMU组是直通的最小调度单元。也就是说,你可能被迫将多个设备一起直通给虚拟机,或者将设备放到其他PCI插槽。
为了将设备分配给虚拟机,它和它所在分组的所有其他设备的驱动,必须更换为一个占位符驱动(stub 或 VFIO驱动)。这样,宿主机就不会和该设备进行交互。大部分设备,可以在启动虚拟机之前,即席的完成驱动更换操作。
对于显卡,没有这么方便。GPU驱动通常对动态rebinding支持的不好,不能将宿主机上正在使用的GPU透明的直通给虚拟机。因此,我们需要在宿主机启动时,尽早将占位符驱动bind给GPU。这样,除非驱动被换回,或者虚拟机claim该GPU,它会保持inactive状态。
之所以要求尽早,是因为Linux现有的驱动机制是每个驱动在初始化时,自行去寻找没有初始化的,自己关注的硬件。因此驱动的初始化顺序非常关键。如果慢了,物理驱动就会抢先绑定设备。
从内核4.1开始,VFIO驱动vfio-pci被包含其中。可以用来代替pci-stub。
修改内核参数:
1 |
pci-stub.ids=8086:9bf6 |
pci-stub根据ID来识别设备,也就是说,我们需要提供用于直通的PCI设备的ID。对于上面的输出中,Intel显卡的ID是8086:9bf6。
如果要绑定多个设备,ID需要用逗号分隔。
随后我们需要执行下面的命令并重启:
1 |
sudo update-grub |
内核总是先初始化所有内建的驱动,然后才逐个初始化外部模块。 在外部模块中,我们可以通过softdep来增加模块间的依赖关键: 例如我们可以把vfio-pci列为nvidia的依赖,那么vfio-pci总会被在nvidia之前初始化,而确保能抢占到硬件。
我们首先需要弄清楚,需要直通的硬件,当前是被什么驱动所绑定:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
lspci -nnv 00:02.0 VGA compatible controller [0300]: Intel Corporation Device [8086:9bf6] (rev 05) (prog-if 00 [VGA controller]) DeviceName: Onboard IGD Subsystem: Hewlett-Packard Company Device [103c:8780] Flags: bus master, fast devsel, latency 0, IRQ 221 Memory at df000000 (64-bit, non-prefetchable) [size=16M] Memory at a0000000 (64-bit, prefetchable) [size=256M] I/O ports at 4000 [size=64] Expansion ROM at 000c0000 [virtual] [disabled] [size=128K] Capabilities: <access denied> # 当前使用的驱动 Kernel driver in use: i915 Kernel modules: i915 |
i915是内核builtin的驱动,无法通过修改softdep,改变驱动加载顺序。解决此问题,有两种方案:
- 将i915从内核剥离出来,编译为模块
- 将vfio-pci编译进内核
如果选择方案2,则使用内核参数: vfio-pci.ids=8086:9bf6 即可完成设备隔离。对于Ubuntu 20.04,vfio-pci已经默认编译到内核中。
libvirt提供钩子(Hooks)功能,你可以添加自定义的脚本,存放在/etc/libvirt/hooks目录下,以便在:
- libvirt守护程序启动、停止、reload时(对应daemon子目录)
- QEMU客户机启动、停止时(对应qemu子目录)
- 一个虚拟网络启动、停止时,或者一个网络接口接入、断开网络时(对应network子目录)
执行特定的逻辑。Hooks可以基于Bash或者Python编写。
报错:The virtual machine's operating system has attempted to enable promiscuous mode on adapter 'Ethernet0'.
要解决此问题,需要在宿主机上执行:
1 2 |
# vmnet0改为实际使用的Vmware虚拟网络 sudo chmod a+rw /dev/vmnet0 |
报错信息:error: unsupported configuration: Domain requires KVM, but it is not available. Check that virtualization is enabled in the host BIOS, and host configuration is setup to load the kvm modules.
解决办法:VM ⇨ Settings,弹出的对话框中,选择Processors,在面板右侧勾选Virtualize Intel VT-X/EPT or AMD-V/RVI
报错信息:error: internal error: cannot load AppArmor profile 'libvirt-cf9a1d56-306d-4a6f-8b0e-79ac070aa8fe'
这个错误与安全模块AppArmor有关,你可以简单的禁用libvirt的QEMU驱动的安全驱动来规避:
1 2 |
# 添加 security_driver = "none" |
并执行:
1 |
sudo touch /etc/apparmor.d/disable/usr.sbin.libvirtd |
然后重启libvirtd: sudo service libvirt-bin restart
报错信息:
error: internal error: process exited while connecting to monitor: failed to open /dev/net/tun: Operation not permitted
failed to launch bridge helper
qemu-system-x86_64: -netdev bridge,id=tap0,br=br0: Device 'bridge' could not be initialized
解决办法:
1 2 3 4 5 6 7 8 9 10 11 |
# 添加如下几行 user = "root" group = "root" cgroup_device_acl = [ "/dev/null", "/dev/full", "/dev/zero", "/dev/random", "/dev/urandom", "/dev/ptmx", "/dev/kvm", "/dev/kqemu", "/dev/rtc", "/dev/hpet", "/dev/net/tun" ] clear_emulator_capabilities = 0 |
报错信息:error: internal error: process exited while connecting to monitor
解决办法:从Domain配置文件中去掉 <qemu:arg value='-daemonize'/> 即可。
症状:无法启动成功,配置SDL则可以启动,但是需要Headless的服务器。
解决办法:配置一个graphics,类型为VNC。
这导致虚拟机无法启动,QEMU的SDL窗口不出现。
报错信息:error: internal error: process exited while connecting to monitor: Could not initialize SDL(No available video device) - exiting
解决办法:
- 首先在宿主机执行 env | egrep "DISPLAY|XAUTH" ,获取两个环境变量的值
- 然后修改Domain配置文件,把type=sdl的graphics元素的display和xauth属性修改为上面命令输出的环境变量值:
1<graphics type='sdl' display=':0' xauth='/home/alex/.Xauthority'/>
报错信息:
Booting from Hard Disk...
Boot failed: not abootable disk
No bootable device.
报错原因:可能是Domain配置文件搞错了镜像文件的格式。
解决办法:修改为正确的镜像格式,例如: <driver name='qemu' type='qcow2'/>
报错信息:error: internal error: cannot find character device <null>
解决办法:可能是你的Domain配置中缺少Console和串口的配置,添加:
1 2 3 4 5 6 |
<serial type='pty'> <target port='0'/> </serial> <console type='pty'> <target type='serial' port='0'/> </console> |
要退出从virsh console进入的控制台,可以按组合键 Ctrl+] 。
问题现象:光标在Escape character is ^]下面一行闪烁,但是按任何键都没有反应。
问题原因:客户机没有进行适当的配置。
解决办法: 通过其它方式登录到客户机,修改配置。
- 修改/etc/sysconfig/grub(该文件是指向/etc/default/grub的符号链接):
12# 修改这一行,在命令行尾部添加console=...这个内核参数GRUB_CMDLINE_LINUX="... console=ttyS0,115200" - 更新GRUB: grub2-mkconfig > /boot/grub2/grub.cfg
- 执行命令 echo ttyS0 >> /etc/securetty 并重启客户机
现在你可以使用virsh console连接到客户机,并执行Shell命令了。
当通过串口(上面的方式)连接到Linux时,缺乏协商机制(Negotiate About Window Size ,NAWS),Linux也不知道你的(通过串口连接的)控制台屏幕屏幕大小。
在这种情况下,通常会使用 stty -a命令显示的结果,来设置窗口尺寸,往往不靠谱,偏小。
你可以在.bashrc中增加 /usr/bin/resize > /dev/null,resize是来自xterm的工具,它可以使用VT100-style的光标位置来判断屏幕尺寸。resize会改变stty输出结果。
报错信息:unsupported configuration: deletion of 1 external disk snapshots not supported yet
解决办法:目前libvirt无法删除外部快照的磁盘文件,因此我们仅仅需要删除它的元数据,调用snapshot-delete时添加--metadata参数。磁盘文件可以手工删除。
问题现象:无法ping通网桥,无法ping通外网,Vmware无法桥接到libvirt创建的网桥
原因分析:
在我的机器上,外网是通过Wifi连接的。如果设置虚拟局域网为net-autostart,则虚拟局域网启动时Wifi可能尚未连接,这会导致客户机无法连通外网的情况,原因未知。
将Vmware workstation中的虚拟机也桥接到virbr0时,提示无法连接。出现这种现象的原因也未知,但是先启动一个libvirt管理的客户机“激活”一下VLAN,然后启动Vmware就没事了。
解决办法:在Wifi连接后,启动VLAN、一台libvirt管理的虚拟机,然后再启动Vmware。
设置NFS导出时,要启用no_root_squash选项,让NFS客户端(QEMU宿主机)以root权限访问NFS:
1 |
/home/alex/Vmware/libvirt/images/default 10.0.0.0/8(rw,no_root_squash) |
然后,参考本文针对问题《AppArmor导致无法启动QEMU虚拟机》、 《无法启动桥接的QEMU虚拟机》的解决方案。
可能是因为虚拟局域网配置错误:
1 2 3 4 5 6 |
<network> <name>default</name> <forward mode="bridge"> <interface dev="eth0"/> <!-- 必须和宿主机的以太网设备名称一致 --> </forward> </network> |
在Domain配置文件中指定宿主机集群中通用的机器类型,避免此问题:
1 2 3 |
<os> <type arch='x86_64' machine='pc-i440fx-2.0'>hvm</type> </os> |
报错信息:
unable to connect to server at 'Zircon:49152': Connection refused
unable to connect to server at 'centos.local:49152': No route to host
报错原因:默认情况下,迁移的源使用目的主机的主机名来建立迁移连接,出现此错误说明源无法正确连接到目标主机——Zircon,可以ping验证一下
解决方案:
- 修改目的主机libvirt的QEMU配置:
12# 指向目的主机可被迁移源访问的IP地址或者DNS名称migration_host = "zircon.local" -
老版本的libvirt可能不支持上述配置,这时可以配置DNS服务器或者迁移源的/etc/hosts文件
- No route to host错误可能是因为目标主机的防火墙导致,注意检查设置
问题现象:迁移进度到达100%报如上错误。这个报错很笼统,详细的错误信息可以在目的宿主机的客户机运行日志( /var/log/libvirt/qemu/$VM.log )中看到:
1 2 3 |
qemu: warning: error while loading state for instance 0x0 of device 'cpu' load of migration failed 2016-10-19 01:47:45.913+0000: shutting down |
可能是因为卷所在的物理磁盘空间不足。
Leave a Reply