Rocky 10虚拟机性能排查:确认KVM加速还是QEMU模拟?

发布时间:2026/9/8 11:18:21
Rocky 10虚拟机性能排查:确认KVM加速还是QEMU模拟? Rocky Linux 升级换代后很多运维朋友第一反应是“系统变快了还是变慢了”但如果你手头跑的是虚拟机而且总感觉吞吐量上不去、CPU 占用莫名偏高那么先别急着优化内核参数也别急着换存储。先确认一个问题这台虚拟机真的跑在 KVM 上吗这篇文章围绕 Rocky 10 环境下的虚拟化排障展开重点解决一个很容易被忽略的问题虚拟机很慢时如何确认它到底跑在 KVM 硬件加速层还是掉进了 QEMU 纯软件模拟的“慢车道”。内容包含原理讲解、完整排查命令、XML 配置解读、修复方法以及一套可以直接落地的性能排查清单。无论你是刚接触 KVM 的新手还是维护过大量虚拟化节点的运维这篇文章都能帮你少走弯路。1. 虚拟机性能差的根源虚拟化层到底选对没有1.1 一个典型的排障场景假设你在一台 Rocky 10 宿主机上使用 libvirt 管理虚拟机创建了一台跑业务的 Linux 虚机。刚开始还能接受但业务量一上来虚拟机内部 CPU 使用率飙到 80% 以上io 等待也居高不下。你在宿主机上用 top 一看宿主机 CPU 占用却不高内存也不紧张磁盘也没达到瓶颈。这时候很多人会先去调虚拟机内存、加 CPU 核数甚至怀疑是 Rocky 10 的内核调度有问题。但真正的根因可能只是虚拟机创建时没有正确使用 KVM 加速导致整个客户机在纯软件模拟的环境下运行。CPU 的每条指令都需要 QEMU 在用户态翻译执行性能自然好不了。1.2 KVM、QEMU、TCG 到底是什么关系KVMKernel-based Virtual Machine是 Linux 内核自带的虚拟化模块它依赖 CPU 的硬件虚拟化扩展Intel VT-x 或 AMD SVM可以把 CPU 指令直接交给硬件执行性能接近物理机。QEMU 是一个完整的模拟器它既可以配合 KVM 工作也可以独立工作。QEMU 独立工作时使用 TCGTiny Code Generator模式也就是纯软件二进制翻译。TCG 模式下客户机的所有指令都要先翻译成宿主机指令再执行CPU 密集型的负载性能可能下降数倍甚至一个数量级。libvirt 是虚拟化管理层它负责统一管理 QEMU/KVM、LXC 等虚拟化方案向上提供 virsh、virt-manager 等管理工具。我们平时用 virt-install 创建虚拟机、用 virsh 修改虚拟机配置其实操作的都是 libvirt 生成的 XML 配置底层再调用 QEMU 进程启动虚拟机。这里有一个最关键的判断点当 libvirt 的 domain 配置里写着domain typeqemu时QEMU 会以 TCG 软件模拟模式运行完全没有使用 KVM 加速只有当domain typekvm时才会走 /dev/kvm 的硬件加速路径。1.3 为什么“图标显示正常”不等于“跑在 KVM 上”很多人在 virt-manager 里看到虚拟机列表是正常的就默认它跑在 KVM 上。其实 virt-manager 只是一个图形化管理前端它显示的“运行中”只代表 QEMU 进程启动了并不代表底层使用了 KVM 加速。如果宿主机没有 /dev/kvm、BIOS 没开虚拟化或者 XML 里的 domain type 写的是 qemu虚拟机照样能起来只是性能会非常差。所以在 Rocky 10 的虚拟化排障中第一步永远不是去分析业务 SQL、也不是去调应用线程池而是先确认虚拟化层。这篇文章接下来就会给你一套完整的验证流程。2. 环境准备Rocky 10 虚拟化基础组件2.1 需要安装哪些软件在 Rocky 10 这类 RHEL 系发行版上管理 KVM 虚拟机通常需要以下软件包软件包作用qemu-kvmQEMU 的 KVM 版本提供用户态设备模拟libvirt虚拟化管理 API 与守护进程virt-install命令行创建虚拟机的工具virt-manager可选的图形化管理工具edk2-ovmf可选的 UEFI 固件用于 UEFI 启动如果你还不确定当前环境装了什么可以用下面的命令一次性查清楚rpm -qa | grep -E qemu|libvirt|virt-install|edk2正常情况下你应该能看到类似qemu-kvm-core、libvirt-daemon、virt-install等包名。如果连 qemu-kvm 都没有安装那么虚拟机项目多半是在用纯 QEMU性能慢就不是什么奇怪的事了。2.2 检查 CPU 虚拟化扩展与 /dev/kvmKVM 能不能正常工作首先取决于 CPU 是否支持硬件虚拟化。在宿主机上执行grep -E -c (vmx|svm) /proc/cpuinfo如果输出大于 0说明 CPU 支持虚拟化扩展其中vmx对应 Intelsvm对应 AMD。如果输出为 0说明 BIOS/固件中虚拟化开关可能没开或者当前进程被限制在无法使用虚拟化指令的环境中。接下来确认内核 KVM 模块是否加载ls -l /dev/kvm正常情况下会输出crw-rw-rw- 1 root kvm 10, 232 ... /dev/kvm如果提示No such file or directory说明 KVM 模块没有加载或当前环境根本不支持。可以再通过 lsmod 检查模块状态lsmod | grep kvm常见输出kvm_intel 151552 0 kvm 1089536 1 kvm_intel如果是 AMD 平台模块名对应为kvm_amd。2.3 版本说明需要提醒的是Rocky Linux 10 仍在快速迭代中不同版本对应的 qemu-kvm、libvirt 版本可能存在差异。本文示例基于常见 RHEL 系虚拟化组件习惯写法具体包名和命令参数请以当前系统的实际版本为准。排查思路和 XML 结构是通用的版本差异不会影响整体判断流程。3. 实战一步一步确认虚拟机是否真的跑在 KVM 上下面进入核心排查环节。我按照“宿主机侧确认 → XML 配置确认 → 客户机内部确认 → CPU 标志确认”的顺序来写这一套流程做完基本可以实锤一台虚拟机的运行模式。3.1 在宿主机侧确认 libvirt 域类型先查看当前宿主机上有哪些虚拟机virsh list --all假设你看到一台名为rocky10-vm的虚拟机现在导出它的完整 XML 配置virsh dumpxml rocky10-vm重点看根节点domain typekvm namerocky10-vm/name memory unitKiB4194304/memory vcpu placementstatic4/vcpu ... /domain如果根节点是domain typekvm说明 libvirt 层面的配置正确虚拟机应该会尝试使用 KVM 加速。如果写成domain typeqemu那就是强制走纯软件模拟模式了。还可以用 virsh capabilities 查看宿主机的虚拟化能力libvirt 会在这里列出它支持的 domain typevirsh capabilities | grep domain type输出示例domain typekvm domain typeqemu如果输出里只有domain typeqemu没有 kvm说明 libvirt 根本没有检测到 /dev/kvm此时即使 XML 写成 typekvm虚拟机也可能启动失败或回退到 qemu 模式。3.2 在宿主机侧查看 QEMU 进程参数libvirt 启动虚拟机后会在宿主机上产生对应的 QEMU 进程。通过 ps 可以直观看到它到底用了哪些参数ps -ef | grep qemuKVM 模式下QEMU 进程的命令行参数里会带有-machine ... accelkvm或-enable-kvm。如果看到的是类似-accel tcg或根本没有 accel 参数那就说明当前没有使用 KVM 加速。如果命令行太长不好阅读可以只看机器类型和加速参数ps -ef | grep qemu | grep -oE (accelkvm|-enable-kvm|acceltcg)输出 contiansaccelkvm时基本可以确认虚拟机正运行在 KVM 形态下如果输出为空或出现tcg就需要继续检查 libvirtd 日志和权限配置。同时可以查看 libvirtd 的日志确认是否有 KVM 初始化相关报错journalctl -u libvirtd --since today | grep -i kvm常见错误示例internal error: Failed to connect socket to /var/run/libvirt/virtqemud-sock kvm: could not open /dev/kvm: No such file or directory出现这种日志说明 QEMU 没有拿到 KVM 设备。3.3 在客户机内部确认虚拟化层上面的确认工作足以说明宿主机侧的配置情况。但有一个例外当 Rocky 10 宿主机本身也是虚拟机也就是做嵌套虚拟化时宿主机侧可能一切正常但客户机内部依然没有硬件虚拟化标志因为嵌套虚拟化没有把 CPU 虚拟化扩展透传进去。因此还需要在客户机内部做一次确认。登录到虚拟机内部执行systemd-detect-virt如果输出kvm说明客户机认为自己运行在 KVM 虚拟化环境中。如果输出qemu说明运行在纯软件模拟模式。更准确的做法是看客户机 CPU 标志lscpu | grep -E Hypervisor|Virtualization|FlagsKVM 加速且透传正常时lscpu的 Flags 中通常能看到vmx或svm。如果你在客户机里看不到这些标志说明 CPU 虚拟化扩展没有暴露给客户机此时即使宿主机侧显示 typekvm客户机内部也无法再创建更底层的 KVM 虚拟机同时某些依赖硬件虚拟化的应用也会异常。也可以直接看 /proc/cpuinfogrep -E -c (vmx|svm) /proc/cpuinfo在客户机内输出大于 0 代表硬件虚拟化标志已透传。输出为 0 不代表虚拟机一定没用 KVM但如果叠加性能慢的问题就需要重点检查嵌套虚拟化配置或 CPU 模式设置。3.4 检查 CPU 模式与拓扑是否被降级还有一种特殊情况XML 里 domain type 是 kvmCPU 标志也透传了但虚拟机性能依然很差。这时候要检查 CPU 模式是否被设置成了保守的兼容模式。在虚拟机 XML 中CPU 相关配置长这样cpu modehost-passthrough topology sockets1 dies1 cores2 threads1/ /cpuhost-passthrough会把宿主机 CPU 大部分特性直接暴露给客户机性能损耗最小host-model会选择一个与宿主机相近的 CPU 模型兼容性更好但性能略有损失custom配合cpu host或具体型号时类似 host-passthrough 的效果。如果你发现 XML 里写的是一个非常老的模型比如cpu modecustom matchexact model fallbackallowqemu64/model /cpu那么客户机 CPU 会被模拟成很基础的 qemu64 型号性能会有明显下降。这种问题在图形界面创建虚拟机时经常出现因为 virt-manager 默认会根据宿主机能力自动选择但如果安装源或模板有问题就可能退化到兼容型号。4. 如果发现跑在 qemu/TCG 模式怎么切回 KVM现在假设你已经确认了虚拟机没有跑在 KVM 上接下来就是修复环节。下面按“创建时规避”和“已有虚拟机修正”两种情况说明。4.1 创建虚拟机时指定 --virt-type kvm用 virt-install 创建虚拟机时最稳妥的方式是显式指定虚拟化类型virt-install \ --name rocky10-vm \ --memory 4096 \ --vcpus 4 \ --disk path/var/lib/libvirt/images/rocky10-vm.qcow2,size40,formatqcow2 \ --os-variant rocky10 \ --network networkdefault \ --graphics vnc \ --virt-type kvm \ --cdrom /path/to/Rocky-10.iso其中--virt-type kvm是关键参数。如果不指定virt-install 会尝试自动选择自动选择一般也是 kvm但如果宿主机没有 /dev/kvm它就会退回到 qemu。手动写清楚可以避免“创建时没注意事后性能出问题”的尴尬。创建完成后立即验证virsh dumpxml rocky10-vm | head -n 3确认第一行是domain typekvm4.2 已有虚拟机修改 domain type如果已经存在一台 typeqemu 的虚拟机可以安全地修改它的域类型。先关闭虚拟机virsh shutdown rocky10-vm virsh destroy rocky10-vmdestroy是强制关机如果虚拟机正在跑生产业务请谨慎操作最好在低峰期进行。然后编辑配置virsh edit rocky10-vm把根节点domain typeqemu改为domain typekvm保存退出。virsh edit 在保存时会对 XML 做校验如果格式不对会拒绝保存。之后重新启动虚拟机virsh start rocky10-vm再按第 3 节的流程验证一次确认当前已经运行在 KVM 加速模式下。注意如果宿主机本身没有 /dev/kvm把 type 改成 kvm 会导致虚拟机启动失败。所以在改 XML 之前一定要先确认宿主机具备 KVM 能力。4.3 确认 libvirtd 用户权限在某些最小化安装的 Rocky 10 环境中即使 /dev/kvm 存在QEMU 进程也可能因为权限不足而无法访问。默认情况下/dev/kvm 的属主是 root组是 kvm权限通常是 0666允许所有用户读写。但如果你自定义过 udev 规则或安全模块就需要检查当前用户是否在 kvm 组中groups id如果普通用户不在 kvm 组可以添加到组中然后重新登录sudo usermod -aG kvm $USER同时查看 /etc/libvirt/qemu.conf 中的用户配置。默认情况下 libvirtd 以 root 身份运行 QEMU通常不存在权限问题但如果你手动指定了 user/group就要确保该用户对 /dev/kvm、镜像目录、日志目录有足够权限。检查 /dev/kvm 权限可以用ls -l /dev/kvm如果权限不是 0666 或 0660并且当前 QEMU 用户不在 kvm 组就会出现虚拟机启动慢、启动失败甚至“无法打开 /dev/kvm”的报错。4.4 验证切换效果切换完成后重启虚拟机并按照第 3 章的顺序做一次完整验证宿主机侧virsh dumpxml看到typekvm宿主机侧ps -ef | grep qemu看到accelkvm客户机侧systemd-detect-virt输出kvm客户机侧lscpu | grep -E vmx|svm能看到硬件虚拟化标志如果以上全部符合虚拟机的性能通常会明显改善。此时可以做一个简单对比比如在修复前后分别跑一段计算密集的任务time cat /dev/zero | head -c 1000000000 /dev/null或者用更专业的工具sysbench cpu run --threads4通过对比耗时你就能直观感受到“跑在 KVM 上”和“跑在 TCG 模拟上”的差距。当然虚拟机性能还受到存储、网络、NUMA 等多种因素影响但虚拟化层恢复正常是所有优化的前提。5. 常见问题与排查清单5.1 常见问题表问题现象常见原因解决思路虚拟机很慢CPU 占用高虚拟机跑在 qemu/TCG 软件模拟模式检查 domain type改为 kvm确认 /dev/kvm 存在启动虚拟机报“没有 /dev/kvm”宿主机 CPU 虚拟化未开启或内核模块未加载检查 BIOS 开关modprobe kvm_intel / kvm_amd客户机内部看不到 vmx/svm嵌套虚拟化未开启或 CPU mode 未透传宿主机模块参数启用嵌套使用 host-passthrough修改 type 后虚拟机无法启动宿主机没有 KVM 能力但强行指定 kvm先修复宿主机虚拟化条件再改回 kvm普通用户无法创建虚拟机用户不在 kvm 组或 /dev/kvm 权限不对usermod -aG kvm调整 udev 规则客户机 CPU 型号显示 qemu64XML 中 CPU model 设置过于保守修改为 host-passthrough 或 host-model“客户机操作系统已禁用 CPU”类报错虚拟化层没有把 CPU 虚拟化扩展暴露给客户机或模拟器不支持检查虚拟机平台与 CPU 配置确认 KVM 加速可用最后一行提到的问题虽然常见的完整报错出现在部分桌面虚拟化工具中但在 KVM 环境下同样可能遇到类似现象核心都是 CPU 虚拟化能力传递链路断了按上述排查顺序处理即可。5.2 完整排查清单按照下面的顺序逐项检查基本可以定位 90% 的“虚拟机很慢但宿主机正常”问题宿主机 CPU 是否支持虚拟化grep -E -c (vmx|svm) /proc/cpuinfo内核模块是否加载lsmod | grep kvm设备节点是否存在ls -l /dev/kvmlibvirt 是否识别 KVMvirsh capabilities | grep domain type虚拟机 XML 根节点类型virsh dumpxml 虚拟机名 | headQEMU 进程是否使用加速ps -ef | grep qemu | grep -oE accelkvm|-enable-kvm客户机内部是否识别 KVMsystemd-detect-virt客户机 CPU 标志lscpu | grep -E vmx|svmCPU 模式是否过于保守检查 XML 中的cpu mode...权限与日志journalctl -u libvirtd --since today \| grep -i kvm把这个清单固化到你的运维手册中下次再遇到“虚拟机慢”的问题就不会一上来就去翻业务日志了。6. 最佳实践让 Rocky 10 虚拟机稳定跑满性能6.1 安装包选型Rocky 10 环境下建议使用发行版自带的 qemu-kvm 和 libvirt 体系而不是自己从源码编译 QEMU。发行版维护的包与内核模块、selinux 策略、systemd 服务集成更好升级也更可控。生产环境建议保持 qemu-kvm、libvirt、virt-install 三个核心组件版本一致避免某个组件单独升级后出现 ABI 不兼容。6.2 CPU 与内存配置CPU 配置方面优先使用host-passthrough模式以获得完整 CPU 特性。但如果需要在线迁移虚拟机到不同型号 CPU 的宿主机host-model是更稳妥的选择因为它会选一个折中的 CPU 模型保证迁移兼容性。内存方面需要关注 NUMA 拓扑。对于大内存、高并发虚拟机建议把虚拟机 vCPU 和内存尽量绑定在同一个 NUMA node 上。可以使用virsh vcpuinfo查看 vCPU 的物理分配情况必要时用virsh emulatorpin和numatune配置让调度更加合理。一个示例性的 XML 片段cpu modehost-passthrough checknone topology sockets1 dies1 cores4 threads2/ /cpu numatune memory modestrict nodeset0/ /numatune6.3 virtio 驱动与存储总线虚拟机内部磁盘和网卡类型对性能影响巨大。在 XML 中磁盘总线尽量使用 virtiodisk typefile devicedisk driver nameqemu typeqcow2 cachenone ionative/ source file/var/lib/libvirt/images/rocky10-vm.qcow2/ target devvda busvirtio/ /disk网卡也推荐使用 virtiointerface typenetwork source networkdefault/ model typevirtio/ /interface如果虚拟机内部没装 virtio 驱动Windows 客户机可能需要额外安装驱动包Linux 客户机一般内核自带 virtio 模块。使用 virtio 后磁盘和网络 IO 性能会得到明显提升。6.4 性能监控与回归虚拟化层修复后建议建立一套简单的性能基线。常用工具包括# 宿主机侧 virt-top # 客户机内部 top vmstat 1 iostat -x 1 pidstat -d 1在切换前后分别记录 CPU 空闲率、上下文切换、IO 等待时间、网络吞吐量等指标形成自己的基准数据。下次再有人反馈“虚拟机变慢”时直接对比基线和当前数据能省去大量排查时间。6.5 生产环境注意事项生产环境操作前一定要确认以下几点修改虚拟机 XML 前先备份virsh dumpxml 虚拟机名 vm-backup.xml优先在线迁移或维护窗口操作避免直接 destroy 生产虚拟机变更后立即验证虚拟化层而不是等用户反馈如果有 selinux保持 enforcing 模式不要为了省事直接 setenforce 0除非你确认策略冲突原因涉及 /dev/kvm 权限或用户组修改时最小化授予权限只加到 kvm 组即可7. 总结与进一步学习Rocky 10 虚拟机“慢”的问题很多时候不是调优能解决的而是虚拟化底座选错了。通过本文你可以掌握一套完整的确认流程从宿主机 CPU 标志、/dev/kvm 设备、libvirt capabilities到虚拟机 XML 的 domain type再到客户机内部的 systemd-detect-virt 和 CPU flag每一步都能帮助你判断虚拟机是否真正运行在 KVM 上。如果你发现虚拟机跑在 qemu/TCG 模式下参照第 4 章切回 KVM通常能解决绝大多数性能问题。切完之后再检查 CPU 模式和 virtio 设备可以做进一步的性能提升。接下来可以继续深入学习的方向包括libvirt 的 CPU 模型与热迁移机制NUMA 架构下的 vCPU 绑核与内存分配策略virtio-blk、virtio-net 与 vhost-user 的性能差异Rocky 10 系统上 selinux 对 libvirt 的默认策略如何用 virsh 批量管理多台 KVM 虚拟机虚拟化排障的很多问题都是相似的现象在业务层根因在底座层。先把“它到底跑在什么上面”这件事搞清楚再去做其他优化才不会白费力气。