将r730上的kvm虚拟机迁移到r710服务器上避坑: 一号坑: Machine Type(机器类型)不兼容: 原系统的机器类型可能是特定定制的(例如 pc-i440fx-rhel7.x.x)。Ubuntu 24.04 的 QEMU 无法识别这种类型。
修改方法: 找到 标签下的 ,将其修改为 Ubuntu 支持的通用类型,例如默认的 pc 或者较新的 q35。我的改为了:pc-i440fx-2.12
降低 CPU 模型以适配老旧的 R710 R710 的 CPU 架构较老(Westmere 架构),需要将 CPU 模型改为兼容模式(如 Westmere 或 Penryn),删掉那些新 CPU 特性要求:
XML
<model fallback='allow'>Westmere</model>
二号坑 Emulator(模拟器)路径变更: 不同系统的 QEMU 执行文件路径可能不同(例如某些系统是 /usr/libexec/qemu-kvm)。
修改方法: 确保 标签的值为 Ubuntu 的正确路径,通常是 /usr/bin/qemu-system-x86_64。 修正虚拟磁盘路径 找到 这一段,将 修正为你当前在 Ubuntu 上存放该 .qcow2 文件的真实绝对路径(例如你之前提到的 /home/qianlong/kvm/vdisks/kali2026.1kvm8901.qcow2):
XML
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/home/qianlong/kvm/vdisks/kali2026.1kvm8901.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</disk>三号坑 Ubuntu 特有的 AppArmor 安全策略 这是迁移到 Ubuntu 时最容易踩坑的地方。Ubuntu 默认使用 AppArmor 保护系统。如果你的虚拟机磁盘镜像(如 .qcow2)放在了非默认路径(默认是 /var/lib/libvirt/images/,如果你挂载到了自定义的数据盘如 /data/vms/),AppArmor 会直接拦截 QEMU 的读取请求,日志里会显示 Permission denied。
排查方式: 运行 dmesg | grep -i apparmor | grep DENIED,看看是否有针对你虚拟机镜像路径的拦截记录。
解决方式: 你需要修改 AppArmor 的 libvirt 配置,将你的自定义目录加入白名单。编辑 /etc/apparmor.d/local/usr.lib.libvirt.virt-aa-helper,添加你的镜像路径(例如加上一行 /data/vms/** rwk,),然后重启 AppArmor 服务。 sudo systemctl reload apparmor
四号坑 镜像文件权限与属主 在 Ubuntu 24.04 上,QEMU 进程通常以 libvirt-qemu 用户(属于 kvm 用户组)运行。 迁移过来的镜像文件可能还保留着 root 或原系统特定用户的权限,导致 QEMU 无法读取。
解决方式: 手动将镜像文件的属主改过来: 保留在家目录,修改目录穿透权限 如果你必须把镜像放在这个位置(例如这块硬盘空间很大),你需要逐级赋予外来用户“进入”目录的权限(即执行权限 x),并修改镜像文件的属主。
逐级开放目录的进入权限(o+x): 注意,这会让系统上其他用户也能通过已知路径访问你的家目录文件,请确保安全。
Bash chmod o+x /home/qianlong chmod o+x /home/qianlong/kvm chmod o+x /home/qianlong/kvm/vdisks 将镜像文件的属主改为 QEMU 进程账户:
Bash sudo chown libvirt-qemu:kvm /home/qianlong/kvm/vdisks/kali2026.1kvm8901.qcow2
五号坑 网络接口 (Bridge/NAT) 缺失 检查 XML 中的 部分。 如果你的虚拟机原来使用的是桥接网络(如 并指定了 br0),那么在新的 Ubuntu 24.04 宿主机上,必须提前配置好同名的网桥。如果宿主机的网桥不存在,虚拟机在初始化网卡设备时就会直接报错退出。
六号坑 在 KVM 虚拟化中,经常会使用模板克隆来节省空间。你的 kali2026.1kvm8901.qcow2 并不是一个包含完整系统数据的独立镜像,而是一个增量镜像(Differential Image)。
它在底层强烈依赖于一个基础模板文件:/home/disk/nvme1/kvm/vdisks/kali2026.1_template.raw。 在迁移到这台新的宿主机时,底层的 QEMU 进程按照这个写死的旧路径去寻找基础模板,但没有找到。这通常是因为该文件没有被拷贝过来,或者新服务器的目录结构不同(例如缺少 nvme1 这个挂载点)。
解决方法 你需要找到那个基础模板文件,并修正 .qcow2 文件中的路径指向。
步骤 1:定位基础模板文件 请先在当前的 Ubuntu 系统中找到 kali2026.1_template.raw 文件。假设你已经将它和现在的 .qcow2 文件放在了同一个目录下,即 /home/qianlong/kvm/vdisks/。
步骤 2:重置基础镜像路径(Rebase) 使用 qemu-img rebase 命令来修改 .qcow2 内部记录的基础镜像路径:
Bash
请将 -b 后面的路径替换为模板文件在你当前系统上的真实绝对路径 qemu-img rebase -u -b /home/qianlong/kvm/vdisks/kali2026.1_template.raw -F raw /home/qianlong/kvm/vdisks/kali2026.1kvm8901.qcow2 提示:-u 参数表示不安全模式(Unsafe mode),它的作用是强行改写路径指针而不去校验旧路径的数据,由于你的旧路径已经不存在了,必须加上这个参数。
步骤 3:验证路径修改 运行以下命令检查镜像信息:
Bash qemu-img info /home/qianlong/kvm/vdisks/kali2026.1kvm8901.qcow2 在输出的内容中,确认 backing file 这一项已经成功变更为你刚刚设置的新路径。
步骤 4:赋予基础镜像权限 因为虚拟机启动时不仅需要读取 .qcow2,还需要读取底层的 .raw 模板。请确保 libvirt-qemu 账户对基础模板文件同样具有权限:
Bash sudo chown libvirt-qemu:kvm /home/qianlong/kvm/vdisks/kali2026.1_template.raw sudo chown libvirt-qemu:kvm /home/qianlong/kvm/vdisks/kali2026.1kvm8901.qcow2
七号坑:既然修改完配置后,虚拟机依然提示 No bootable device(找不到引导设备) 既然修改完配置后,虚拟机依然提示 No bootable device(找不到引导设备),说明虚拟机的虚拟硬盘(即那条增量链)虽然能被 QEMU 打开,但系统在里面依然找不到有效的引导扇区(MBR/GPT)或内核。
1、可以通过以下步骤排查磁盘镜像的实际状态:1.1. 查看 qcow2 镜像状态:检查镜像基本信息。在宿主机终端运行以下命令,检查该虚拟磁盘的大小和格式:Bashqemu-img info /home/qianlong/kvm/vdisks/kali2026.1kvm8901.qcow2 验证成功: 终端正常输出镜像的虚拟大小、实际占用空间及文件格式。
2.检查底层模板文件自分区表:验证 raw 模板完整性。运行以下命令直接检查 .raw 模板的分区结构,看看它在 R710 上是否能被正常读取:Bashsudo fdisk -l /home/qianlong/kvm/vdisks/kali2026.1_template.raw 验证成功: 终端能够正常打印出类似 Linux 分区(如 /dev/loopXp1 或分区表详情)即说明模板完好;若报错则说明该文件在跨服务器拷贝时损坏或不完整。
3.检查模板镜像元数据:核对虚拟大小。运行以下命令查看 .raw 文件的基本属性:Bashqemu-img info /home/qianlong/kvm/vdisks/kali2026.1_template.raw
问题的原因已经找到了:从 qemu-img info 的输出可以看出,这个文件的后缀虽然叫 .raw,但它实际的文件格式是 qcow2。
因为 fdisk 只能直接读取纯 Raw 格式的绝对物理偏移,无法解析 qcow2 内部的封装结构,所以刚才直接用 fdisk 无法正确读取分区。
4、 修正文件后缀名避免误导:规范化命名(可选)。为了避免以后混淆,建议将模板文件的后缀名从 .raw 改为 .qcow2:Bashmv /home/qianlong/kvm/vdisks/kali2026.1_template.raw /home/qianlong/kvm/vdisks/kali2026.1_template.qcow2 (注意:改名后,需要同步修改子镜像 kali2026.1kvm8901.qcow2 内部的 backing file 指向路径,或者重新指定底层模板)。验证成功: 再次运行 qemu-img info 确认基础链条指向正常。
5、重新更新重置基础镜像路径(Rebase) qemu-img rebase -u -b /home/qianlong/kvm/vdisks/kali2026.1_template.qcow2 -F qcow2 /home/qianlong/kvm/vdisks/kali2026.1kvm8901.qcow2
6、赋予基础镜像权限 因为虚拟机启动时不仅需要读取 .qcow2,还需要读取底层的 .raw 模板。请确保 libvirt-qemu 账户对基础模板文件同样具有权限:
Bash sudo chown libvirt-qemu:kvm /home/qianlong/kvm/vdisks/kali2026.1_template.qcow2 sudo chown libvirt-qemu:kvm /home/qianlong/kvm/vdisks/kali2026.1kvm8901.qcow2 重新启动虚拟机,可以启动了
具体我的操作修改项如下: 1、virsh edit kali2026.1kvm8902 修改内容如下:
<domain type='kvm'>
<name>kali2026.1kvm8901</name>
<uuid>921fd605-7601-4052-87bd-7ada46849e74</uuid>
<memory unit='KiB'>4194304</memory>
<currentMemory unit='KiB'>4194304</currentMemory>
<vcpu placement='static'>4</vcpu>
<os>
**<type arch='x86_64' machine='pc-i440fx-2.12'>hvm</type>**
<boot dev='hd'/>
<boot dev='cdrom'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<cpu mode='custom' match='exact' check='partial'>
**<model fallback='allow'>Westmere</model>**
</cpu>
<clock offset='utc'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<pm>
<suspend-to-mem enabled='no'/>
<suspend-to-disk enabled='no'/>
</pm>
<devices>
**<emulator>/usr/bin/qemu-system-x86_64</emulator>**
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
**<source file='/home/qianlong/kvm/vdisks/kali2026.1kvm8901.qcow2'/>**
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<target dev='hda' bus='ide'/>
<readonly/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<controller type='usb' index='0' model='ich9-ehci1'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x7'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci1'>
<master startport='0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0' >
</controller>
<controller type='usb' index='0' model='ich9-uhci2'>
<master startport='2'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x1'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci3'>
<master startport='4'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<interface type='bridge'>
<mac address='52:54:00:28:45:98'/>
**<source bridge='br0'/>**
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<serial type='pty'>
<target type='isa-serial' port='0'>
<model name='isa-serial'/>
</target>
</serial>
<console type='pty'>
<target type='serial' port='0'/>
</console>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='8901' autoport='no' listen='0.0.0.0'>
<listen type='address' address='0.0.0.0'/>
</graphics>
<audio id='1' type='none'/>
<video>
<model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primar>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</memballoon>
</devices>
</domain>
2、使kvm可以访问/home目录 编辑 /etc/apparmor.d/local/usr.lib.libvirt.virt-aa-helper,添加你的镜像路径 加上一行 /home/qianlong/kvm/vdisks/** rwk, 然后重启 AppArmor 服务。 sudo systemctl reload apparmor
3、修改镜像文件权限与属主 chmod o+x /home/qianlong chmod o+x /home/qianlong/kvm chmod o+x /home/qianlong/kvm/vdisks 将镜像文件的属主改为 QEMU 进程账户:
Bash sudo chown libvirt-qemu:kvm /home/qianlong/kvm/vdisks/kali2026.1kvm8902.qcow2
4、重置基础镜像路径(Rebase) 使用 qemu-img rebase 命令来修改 .qcow2 内部记录的基础镜像路径 qemu-img rebase -u -b /home/qianlong/kvm/vdisks/kali2026.1_template.qcow2 -F qcow2 /home/qianlong/kvm/vdisks/kali2026.1kvm8902.qcow2
5、赋予基础镜像权限 因为虚拟机启动时不仅需要读取 .qcow2,还需要读取底层的 .raw 模板。请确保 libvirt-qemu 账户对基础模板文件同样具有权限:
Bash sudo chown libvirt-qemu:kvm /home/qianlong/kvm/vdisks/kali2026.1_template.qcow2 sudo chown libvirt-qemu:kvm /home/qianlong/kvm/vdisks/kali2026.1kvm8902.qcow2
6、重启kvm虚拟机 virsh start kali2026.1kvm8902