KVM虚拟机突然无法读取或启动失败,核心原因通常集中在权限配置、虚拟化支持未开启或磁盘镜像文件受损这三类问题上,按顺序排查即可解决绝大部分故障。
先从最简单的查起,KVM不认盘先看权限和放行
多数情况下,KVM虚拟机无法读取第一个拦路虎不是硬件,而是Linux系统下的SELinux或AppArmor在作怪,想确认是不是这个原因,直接看系统日志最快。
- 执行
journalctl -xe查看最近的错误输出 - 再执行
dmesg | grep -i kvm检查内核模块是否正常加载 - 查看SELinux状态用
getenforce,如果返回Enforcing,就有很大概率拦截了虚拟机的磁盘访问
我建议你直接测试一下:临时把SELinux设为宽容模式(setenforce 0),再去启动虚拟机,如果能正常启动,问题就出在策略上,不用完全关闭SELinux,用 audit2why -a 查看具体拦截原因,然后针对性放行即可。
磁盘镜像文件的属主和权限也经常被忽略,确镜像文件至少被libvirt用户或qemu用户可读,简单粗暴的做法是:
chown libvirt-qemu:libvirt-qemu /var/lib/libvirt/images/.qcow2 chmod 644 /var/lib/libvirt/images/.qcow2
注意,目录权限比文件权限更关键,镜像文件所在的目录需要有执行权限,否则虚拟机同样无法读取。
KVM虚拟机启动失败?核心焦点是CPU虚拟化嵌套和BIOS设置
启动失败和无法读取不太一样,后者是找不到磁盘,前者是启动到一半直接崩,我经常遇到的场景是用户新装了一台宿主机,结果虚拟机开机卡在CPU初始化阶段。
这通常指向宿主机BIOS里没打开VT-x或AMD-V,你先确认这点:
- 执行
grep -E -c '(vmx|svm)' /proc/cpuinfo - 返回0就说明BIOS完全没开虚拟化,必须重启进BIOS找Intel Virtualization Technology或SVM Mode开启
- 返回大于0但虚拟机仍启动失败,则检查是否是嵌套虚拟化的问题
很多人在云服务器或已有虚拟机里再装KVM,不明白嵌套虚拟化怎么弄
,这时你需要编辑虚拟机XML配置,把CPU模式改为host-passthrough:
<cpu mode='host-passthrough' check='none'/>
修改后重启libvirtd服务,让CPU特性完全透传给KVM虚拟机,业内专家指出,嵌套虚拟化不开启是KVM启动失败的常见隐藏因素,尤其是在测试环境中。
排查存储池和镜像损坏,KVM虚拟机无法读取磁盘文件和快照
如果权限和虚拟化都没问题,虚拟机还是不读盘,就要把重心放在存储池和镜像文件本身,KVM虚拟机启动失败还有另一个常见原因快照文件丢失或损坏。
具体排查步骤:
- 执行
virsh vol-list --pool default查看磁盘卷是否存在 - 用
qemu-img info /var/lib/libvirt/images/你的虚拟机.qcow2检查镜像格式是否完整 - 如果看到”Format: qcow2″和”Virtual size”正常,再检查是否有backing file关联
快照导致的启动失败很隐蔽,表现是虚拟机开机后直接进入grub救援模式或直接黑屏,行业共识认为,backing file路径变动是快照链断裂的主因,一旦原始镜像默认路径被移动,后面所有增量快照都会失效。
解决方案是重新指定backing file路径:
qemu-img rebase -u -b /新路径/原始镜像.qcow2 /var/lib/libvirt/images/快照链.qcow2
这操作不需要修改快照内部数据,只修正引用关系,KVM虚拟机就能重新识别磁盘。
系统层面引导失败,重点查grub和initramfs完整性
排除以上三项后,KVM虚拟机无法开机就要往系统内部去看,把问题限定在:启动时能看见BIOS信息,但进入系统阶段卡死或直接kernel panic。
这里有两种主流场景:
- 内核模块不匹配:宿主机更新过内核,但虚拟机内的virtio驱动还是老版本,导致磁盘控制器识别异常,解决方法是启动虚拟机时在grub菜单选旧内核进入,然后更新virtio驱动
- initramfs损坏:这会导致KVM虚拟机无法读取根文件系统,启动时提示”unable to find root device”
急救方式比较直接,使用宿主机上的 guestfish 或 virt-rescue 工具挂载虚拟机磁盘,重新生成initramfs:
virt-rescue -d 虚拟机名称 # 进入救援环境后执行 mkinitrd -f /boot/initramfs-$(uname -r).img $(uname -r)
该操作完成后重启,多数引导层面的KVM虚拟机启动失败都能恢复。
| 故障类别 | 典型符号 | 排查优先级 |
|---|---|---|
| 权限/SELinux | 日志提示Permission denied | 最高 |
| CPU虚拟化 | 启动即崩溃,无图形界面 | 高 |
| 磁盘镜像 | 提示No such file或格式错误 | 中 |
| 系统引导 | 卡在内核加载之后 | 低 |
对比场景:自建KVM与商用方案在稳定性上的选择
排查完这些技术点之后,你需要知道一个现实:相当一部分KVM不读虚拟机的案例,其实是宿主机的存储子系统本身存在瓶颈,比如说,使用普通机械硬盘做KVM存储池,当多台虚拟机并发启动时,磁盘I/O等待会导致虚拟机超时,看起来就像是无法读取。
这种情况下,一种方案是给宿主机换用SSD或者NVMe,并定期执行 fstrim 回收未使用空间,另一种方案是把镜像文件迁移到其他存储位置:
virsh blockcopy --domain 虚拟机名称 /var/lib/libvirt/images/原镜像.qcow2 /新路径/目标镜像.qcow2 --wait --finish
完成后再编辑虚拟机配置指向新路径,在预算有限的前提下,自建KVM稳定性和成本可以兼顾,但需要考虑是否要引入商用虚拟化平台,近年来,国内不少中小团队更倾向于在KVM之上叠加Proxmox VE做统一管理,这样既能保留KVM底层性能,又能获得网页管理和备份快照能力,避免单点手工配置带来的启动失败风险。
KVM虚拟机启动失败后的数据保全思路
启动失败不等于数据丢失,不要急着删掉镜像重建虚拟机,你应该先把磁盘镜像备份一份,再尝试修复操作,共享存储环境下的备份要注意,多个宿主机同时挂载同一镜像会导致锁冲突,这是KVM不读虚拟机的另一个隐藏原因。
确认没有其他宿主机占用同一个镜像,再执行 virsh start,否则会出现”Failed to acquire lock”错误。
对于已经启动失败的虚拟机,按顺序操作:
- 先检查
/var/log/libvirt/qemu/虚拟机名称.log里的最后几行错误 - 再确认CPU型号是否超出宿主机物理CPU能力范围(尤其在你迁移过虚拟机之后)
- 最后用
virsh edit 虚拟机名称把<vcpu>数量调低,排除资源不足导致的启动失败
这三步能解决相当一部分莫名其妙的KVM启动失败问题。
高频问题解答
KVM无法读取虚拟机的报错”internal error process exited while connecting to monior”是什么意思?
这是libvirt无法正常启动qemu进程的通用报错,大概率是配置文件中引用了不存在的设备或路径,执行 virsh dumpxml 虚拟机名称 检查磁盘源路径是否存在,同时查看宿主机上的 df -h 确认对应存储空间是否已满。
KVM虚拟机启动失败会不会影响同一宿主机上的其他虚拟机?
正常隔离情况下不会,单台虚拟机的启动失败被限制在自身配置范围内,但如果是存储池层面的损坏(如宿主机磁盘坏道),会影响所有虚拟机,验证方法很简单,启动另一台正常的虚拟机,如果能正常运行则问题定位在特定虚拟机的配置或镜像,而非基础设施。
为什么在BIOS里已经开了VT-d,KVM虚拟机还是不认直通的PCIe设备?
VT-d开启只代表硬件支持,Linux内核还需要加载vfio模块并在grub中添加iommu参数,执行 dmesg | grep -i iommu 查看是否正常初始化,没有输出就需要修改grub命令行,加入 intel_iommu=on iommu=pt 参数后更新引导配置并重启宿主机,直通功能才能生效。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/743707.html





