QEMU / KVM / libvirt 分层关系
一条虚机的完整链路是四层:libvirt 守护进程接收管理请求并维护域 XML,调用 QEMU 进程去执行,QEMU 通过 /dev/kvm 拿到 CPU 与内存的硬件加速,最底层才是 CPU 虚拟化扩展与 IOMMU。四层职责分明,排障时先判断问题落在哪一层,能避免在同一层反复折腾。
基本信息
| 管理面 | libvirt 守护进程、virsh 与 virt-manager,期望状态保存在域 XML |
|---|---|
| 执行面 | QEMU 进程,负责设备模型与虚拟机生命周期 |
| 加速面 | KVM 内核模块与 /dev/kvm,提供 CPU 与内存虚拟化 |
| 硬件面 | VT-x / AMD-V、EPT / NPT、IOMMU |
| 配置落点 | 所有持久变更最终都要经过 virsh define 写入域 XML |
分层职责
| 层 | 组件 | 职责 | 常见问题 |
|---|---|---|---|
| 管理 | libvirt / virsh | 域 XML、生命周期、网络与存储池 | XML 定义与实际进程不一致 |
| 执行 | QEMU | 设备模型、进程生命周期 | 设备参数错误、启动失败 |
| 加速 | KVM 内核模块 | CPU 与内存虚拟化、/dev/kvm | 模块未加载、嵌套未开 |
| 硬件 | VT-x/AMD-V、IOMMU | 指令与地址转换支持 | 固件未开、平台限制 |
典型使用场景
- 创建虚机:virt-install 或 virt-manager 生成域定义并启动
- 调整配置:dumpxml 导出、修改后 define 回去并重启生效
- 性能优化:按层确认瓶颈在 QEMU 设备模型还是宿主资源
- 迁移与备份:libvirt 层面导出定义加磁盘文件
- 排障定位:先看 virsh 状态,再看 QEMU 进程,再看内核模块
按层排查常用命令
按层排查常用命令
virsh -c qemu:///system list --all
virsh dumpxml vm1 --inactive | grep -E 'cpu|memory|source'
ps -ef | grep qemu-system | grep -v grep
lsmod | grep kvm && ls -l /dev/kvm
virsh net-list --all && virsh pool-list --allvirsh 按连接区分作用范围:系统级 qemu:///system 与用户级 qemu:///session 的域列表并不相同,排查时先确认连的是哪个。
libvirt 日志在 /var/log/libvirt/ 下按模块分文件(qemu、libvirtd),启动失败的信息通常先出现在这里而不是 guest 控制台。
排障顺序建议自上而下:先看 virsh 里域的状态与 XML 是否符合预期,再看 QEMU 进程是否在跑、启动参数是什么,最后才查内核模块与硬件开关。越往上越容易改,越往下改动影响越大。
域定义与磁盘文件是两码事:define 只注册配置,磁盘文件在存储上独立存在;删掉域定义磁盘仍在,反过来删了磁盘,域定义还在但一启动就报找不到文件。