在 debian/ubuntu 下使用 libvirt 启动虚拟机报文件没有权限的问题
问题描述:
环境信息:
- OS:Debian 或 Ubuntu
- 磁盘文件:Disk Type 使用 Volume,而不是直接指定镜像文件。(File 模式下没有问题)
- Apparmor 打开(这是默认行为)
虚拟机描述文件中的 disk 相关信息类似这样:
<disk type='volume' device='disk'>
<driver name='qemu' type='qcow2' discard='unmap'/>
<source pool='kvm' volume='win7.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
</disk>
错误信息:
虚拟机启动时,报如下错误:
error: Failed to start domain Win7
error: internal error: process exited while connecting to monitor: 2025-04-03T16:23:52.876344Z qemu-system-x86_64: -blockdev {"driver":"file","filename":"/data/kvm/win7.qcow2","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}: Could not open '/data/kvm/win7.qcow2': Permission denied
dmesg 中可以看到如下错误:
[1042732.266614] audit: type=1400 audit(1743668632.876:344): apparmor="DENIED" operation="open" profile="libvirt-99c17aad-cb2e-4bb3-b4d8-eec394cb189e" name="/data/kvm/win7.qcow2" pid=1749356 comm="qemu-system-x86" requested_mask="r" denied_mask="r" fsuid=64055 ouid=64055
原因
Libvirt 在 Debian/Ubuntu 中默认使用了 Apparmor 来控制权限,防止对非授权目录和文件的访问。
按照预期,Libvirt 会使用 virt-aa-helper 自动将虚拟机所使用到的磁盘镜像的路径添加到允许访问的白名单中。File 模式的磁盘文件之所以没这个问题,就是因为 virt-aa-helper 会自动将文件加入到白名单中。
如果查看 /etc/apparmor.d/libvirt/libvirt-${vm-uuid}.files,可以看到类似下面的内容:
DO NOT EDIT THIS FILE DIRECTLY. IT IS MANAGED BY LIBVIRT.
"/var/log/libvirt/**/Win7.log" w,
"/var/lib/libvirt/qemu/domain-Win7/monitor.sock" rw,
"/var/lib/libvirt/qemu/domain-21-Win7/*" rw,
"/run/libvirt/**/Win7.pid" rwk,
"/run/libvirt/**/*.tunnelmigrate.dest.Win7" rw,
"/data/kvm/win7.qcow2" rwk,
"/dev/vhost-net" rw,
"/var/lib/libvirt/qemu/domain-21-Win7/{,**}" rwk,
"/var/lib/libvirt/qemu/channel/target/domain-21-Win7/{,**}" rwk,
"/var/lib/libvirt/qemu/domain-21-Win7/master-key.aes" rwk,
"/dev/net/tun" rwk,
可以看到 /data/kvm/win7.qcow2 rkw
就是磁盘镜像的路径,其中 rkw 表示 read lock write 权限。
然而,针对 Volume 类型的磁盘镜像,相关实现存在 bug,导致不会将路径添加到允许访问的白名单中。这就是为什么,使用 Volume 类型的磁盘镜像会报没有权限的原因。
解决方案
方案1:关闭 Apparmor(不推荐)
- 修改 /etc/libvirt/qemu.conf,将 security_driver 设置为 none,并确保没有被注释掉
sudo systemctl restart libvirtd.service
这样,libvirtd 将不会使用 apparmor 来做权限限制。
方案2:修改 Apparmor 策略,添加指定的 Storage Pool 目录
- 修改
/etc/apparmor.d/local/abstractions/libvirt-qemu
- 添加
"/data/kvm/**" rwk,
,其中 ** 代表所有文件和子目录下的文件,rwk 代表 read write lock sudo systemctl reload apparmor.service
使配置生效
参考
- Libvirt Bug Discussion: https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/1677398
- Libvirt Gitlab Upstream Bug: https://gitlab.com/libvirt/libvirt/-/issues/135
在 debian/ubuntu 下使用 libvirt 启动虚拟机报文件没有权限的问题在 debian/ubuntu 下使用 libvirt 启动虚拟机报文件没有权限的问题在 debian/ubuntu 下使用 libvirt 启动虚拟机报文件没有权限的问题在 debian/ubuntu 下使用 libvirt 启动虚拟机报文件没有权限的问题在 debian/ubuntu 下使用 libvirt 启动虚拟机报文件没有权限的问题在 debian/ubuntu 下使用 libvirt 启动虚拟机报文件没有权限的问题在 debian/ubuntu 下使用 libvirt 启动虚拟机报文件没有权限的问题在 debian/ubuntu 下使用 libvirt 启动虚拟机报文件没有权限的问题在 debian/ubuntu 下使用 libvirt 启动虚拟机报文件没有权限的问题