命令与 XML 使用通用示例,需按宿主版本和实际资源调整。网络地址采用文档地址段,实际部署应选择不冲突的私网;镜像修改与设备直通的适用条件见对应章节。
从基础虚拟化到生产级虚拟机,本章涵盖 UEFI/TPM 现代固件支持、VFIO 硬件直通、virtio 半虚拟化驱动优化、virtiofs 文件共享以及磁盘镜像高级操作。
1. UEFI 固件与 TPM —— 现代 OS 支持#
1.1 为什么需要 UEFI
固件选择应按客户机与引导需求决定;SeaBIOS 仍可用于受支持的 legacy 客体,UEFI 提供现代固件接口:
| 场景 | BIOS 限制 | UEFI 解决方案 |
|---|---|---|
| Windows 11 安装 | 不支持 | OVMF + TPM 2.0 + Secure Boot |
| 磁盘 > 2TB | MBR 寻址限制与 BIOS 不应混淆;BIOS 可通过合适 bootloader 启动 GPT 磁盘 | OVMF 原生支持 GPT |
| Secure Boot | 不支持 | OVMF 支持签名验证 |
| 启动速度 | 初始化耗时依实现而变 | 不保证总启动时间更短 |
| 多 OS 引导 | 多系统可由传统 bootloader 管理,但缺少 UEFI 引导项接口 | UEFI 多条目引导管理器 |
1.2 OVMF (Open Virtual Machine Firmware)
下列文件名与目录是发行版示例,CODE/VARS 的大小、架构和 Secure Boot keys 必须匹配;优先检查 domcapabilities 和固件 metadata。新建域可使用固件自动选择;已有域的 NVRAM 含引导项与密钥,不能为路径迁移随意删除或重建。
OVMF 是 Tianocore EDK2 为 QEMU/KVM 编译的 UEFI 固件实现。
安装:
# Arch Linux
sudo pacman -S edk2-ovmf
# Ubuntu / Debian
sudo apt install ovmf
# Fedora
sudo dnf install edk2-ovmf固件文件位置:
# Arch / Fedora
ls /usr/share/edk2-ovmf/
# OVMF_CODE.fd -- 只读固件代码 (UEFI 运行时)
# OVMF_VARS.fd -- 可变存储模板 (NVRAM, 启动项, 证书)
# OVMF_CODE.secboot.fd -- 带 Secure Boot 的固件代码
# Ubuntu / Debian
ls /usr/share/OVMF/
# OVMF_CODE.fd
# OVMF_CODE_4M.fd -- 4MB 版本 (推荐用于现代 OS)
# OVMF_VARS.fdflowchart LR
A[Host: OVMF_CODE.fd] -->|readonly, shared| B[Guest NVRAM]
C[Host: OVMF_VARS.fd] -->|copy-on-write| D[Per-VM VARS file]
D --> E[Boot entries / Keys / Certificates]
B --> F[UEFI Runtime in Guest]libvirt XML 配置:
<os firmware='efi'>
<type arch='x86_64' machine='q35'>hvm</type>
<firmware>
<feature enabled='yes' name='enrolled-keys'/>
<feature enabled='yes' name='secure-boot'/>
</firmware>
<!-- 新建域让 libvirt 根据固件元数据选择兼容的 Secure Boot CODE/VARS。 -->
</os>每台虚拟机需要独立的 NVRAM 文件 OVMF_VARS.fd 是模板文件,libvirt 会在虚拟机创建时 copy 一份到
/var/lib/libvirt/qemu/nvram/。不同 VM 之间不能共享 VARS 文件,否则会互相覆盖启动项和证书。
1.3 Secure Boot
<!-- 启用 Secure Boot -->
<os firmware='efi'>
<loader readonly='yes' secure='yes' type='pflash'>
/usr/share/edk2-ovmf/OVMF_CODE.secboot.fd
</loader>
</os>Secure Boot 模式下,OVMF 会验证引导加载程序的签名。Linux 发行版通常自带签名引导程序 (shim + GRUB),Windows 也原生支持。
Secure Boot 与某些 GPU ROM 冲突 如果开启了 Secure Boot 同时做 GPU 直通,GPU 的 Video ROM 可能因签名验证失败而无法加载。先确认 firmware、ROM 类型、签名和客体日志,再决定使用经过验证的 ROM 或调整策略;关闭 Secure Boot 不是默认修复,还可能触发磁盘加密恢复。
1.4 TPM 2.0
Windows 11 官方要求 TPM 2.0。SWTPM 是常见的模拟实现,也可以采用符合要求的硬件 TPM 后端;还要核对 CPU、内存、存储、UEFI 与 Secure Boot capable 等完整要求。
安装:
# Arch Linux
sudo pacman -S swtpm
# Ubuntu / Debian
sudo apt install swtpm swtpm-tools
# Fedora
sudo dnf install swtpm swtpm-toolslibvirt XML 配置:
<tpm model='tpm-crb'>
<backend type='emulator' version='2.0'>
<encryption secret='...'/>
</backend>
</tpm>virt-manager 操作:
- Add Hardware -> TPM
- Model:
CRB(推荐,性能优于 TIS) - Backend:
Emulated - Version:
2.0
TPM 状态信息持久化 TPM 模拟器的状态存储在
/var/lib/libvirt/swtpm/<vm-uuid>/下。如果 BitLocker 等依赖 TPM 的全盘加密开启,备份该目录至关重要——丢失 TPM 状态意味着无法解密磁盘。
1.5 完整 Windows 11 兼容配置
<!-- 演示 UEFI/TPM 相关片段;并非全部 Windows 11 硬件要求 -->
<os firmware='efi'>
<type arch='x86_64' machine='q35'>hvm</type>
<firmware>
<feature enabled='yes' name='secure-boot'/>
</firmware>
</os>
<tpm model='tpm-crb'>
<backend type='emulator' version='2.0'/>
</tpm>2. VFIO / PCI Passthrough —— 硬件直通#
VFIO/IOMMU group 是隔离单位;直通前检查组内所有设备、宿主依赖与恢复控制路径。ID 绑定可能匹配多块同型号设备,黑名单可能禁用宿主全部显卡。ACS override 是部分补丁内核提供的危险软件拆组手段,不会制造硬件 DMA 隔离,也不是默认操作。
VFIO (Virtual Function I/O) 将物理 PCIe 设备直接分配给虚拟机,实现接近裸机的 I/O 性能。典型应用场景:GPU 直通(游戏/渲染/AI 训练)、NVMe 直通(数据库)、USB 控制器直通(外设延迟敏感场景)。
2.1 IOMMU 基础
IOMMU (Input-Output Memory Management Unit) 是 VFIO 的硬件基础,负责将 DMA 地址映射到虚拟机地址空间。
启用 IOMMU:
# /etc/default/grub (GRUB 用户)
GRUB_CMDLINE_LINUX_DEFAULT="... intel_iommu=on iommu=pt"
# Intel: 按内核/固件需要检查 intel_iommu=on;AMD 通常自动初始化,iommu.strict=1 不是启用开关
# iommu=pt: 直通模式下不对 host 设备做 DMA 重映射,减少性能开销
# systemd-boot 用户
# /boot/loader/entries/xxx.conf
options ... intel_iommu=on iommu=pt
# 更新引导配置
sudo grub-mkconfig -o /boot/grub/grub.cfg # GRUB验证 IOMMU 启用:
# 检查内核日志
dmesg | grep -i iommu
# Intel 输出示例: DMAR-IR: Enabled IRQ remapping in x2apic mode
# AMD 输出示例: AMD-Vi: Enabling IOMMU
# 检查 DMAR / AMD-Vi 表
dmesg | grep -i -e DMAR -e IOMMU
# 验证 IOMMU 分组
find /sys/kernel/iommu_groups/ -type l | sort -V2.2 IOMMU 分组与隔离
IOMMU 分组决定了哪些设备可以独立直通。VFIO 需要组内所有相关设备满足安全绑定条件(绑定 VFIO 或从宿主 driver 解绑定等);不等于每个功能都必须暴露给同一客体。不可让仍由宿主使用的同组设备破坏隔离。
# 查看每个分组的设备
#!/bin/bash
for g in $(find /sys/kernel/iommu_groups/ -maxdepth 1 -type d | sort -V); do
echo "IOMMU Group ${g##*/}:"
for d in $(find $g/devices/ -type l); do
echo " $(basename $d) ($(lspci -nns $(basename $d) | cut -d' ' -f2-))"
done
doneACS 补丁的安全风险 如果 GPU 与其他设备(如 USB 控制器、NVMe、网卡)共享 IOMMU 分组,可以使用
pcie_acs_override=downstream,multifunction内核参数强制拆分组。但这破坏了硬件隔离——同一组内的设备可以通过 DMA 互相访问。不能作为换槽失败后的自动修复;无法获得可靠隔离时应放弃该分配或更换硬件。
flowchart TD
A[物理 PCIe 设备] --> B{IOMMU 组内仅有目标设备?}
B -->|是| C[跳过 ACS]
B -->|否| D{可以更换 PCIe 插槽?}
D -->|是| E[换插槽后重试]
D -->|否| F[停止分配并评估硬件隔离]
F --> G["ACS override 不提供真实硬件隔离"]
G --> H[⚠️ 安全隔离被破坏,注意风险]
C --> I[绑定到 vfio-pci]2.3 GPU 直通完整流程
GPU 直通是 VFIO 最常见的用例。以下以 NVIDIA 显卡为例。
Step 1: 获取 GPU PCI ID
lspci -nn | grep -i nvidia
# 输出示例:
# <PCI_BDF> VGA compatible controller [...] [<VENDOR_DEVICE_ID>]
# <PCI_BDF> Audio device [...] [<VENDOR_DEVICE_ID>]
#
# <VENDOR_DEVICE_ID> = GPU 本体
# <VENDOR_DEVICE_ID> = HDMI Audio 功能
# 检查同组与关联功能、宿主依赖和VFIO绑定条件;需要分配的功能明确列出Step 2: 配置 vfio-pci 早绑定
阻止宿主机驱动在启动时抢占 GPU:
# /etc/modprobe.d/vfio.conf
# 用你的 GPU PCI ID 替换
options vfio-pci ids=<VENDOR_DEVICE_ID>,<VENDOR_DEVICE_ID>
# 同时黑名单宿主机显卡驱动
# /etc/modprobe.d/blacklist.conf
blacklist nouveau
blacklist nvidia
blacklist nvidiafb# /etc/mkinitcpio.conf (Arch Linux)
MODULES=(... vfio_pci vfio vfio_iommu_type1 ...)
# 旧内核可能有 vfio_virqfd;Linux 6.2 起功能并入 VFIO,勿盲目加载不存在的模块。
# 然后 sudo mkinitcpio -P
# /etc/initramfs-tools/modules (Debian/Ubuntu)
vfio
vfio_iommu_type1
vfio_pci
# 然后 sudo update-initramfs -u -k all内核命令行添加:
vfio-pci.ids=<VENDOR_DEVICE_ID>,<VENDOR_DEVICE_ID>验证绑定:
lspci -k -s "<PCI_BDF>"
# Kernel driver in use: vfio-pci <-- 成功Step 3: libvirt XML 配置
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='<PCI_DOMAIN>' bus='<GPU_BUS>' slot='<GPU_SLOT>' function='<GPU_FUNCTION>'/>
</source>
<rom bar='on'/>
<address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>
</hostdev>
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='<PCI_DOMAIN>' bus='<GPU_BUS>' slot='<GPU_SLOT>' function='<GPU_AUDIO_FUNCTION>'/>
</source>
<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>
</hostdev>NVIDIA Error 43 问题 历史部分 NVIDIA 驱动存在虚拟化检测限制,现代驱动不能一概如此判断;Error 43 也可能由 ROM、reset、固件或驱动不匹配引起。下面隐藏 KVM/vendor_id 是历史兼容性片段,不是所有 GPU 默认需要的设置,先诊断实际版本与日志:
<features> <hyperv> <vendor_id state='on' value='KVM Hv'/> </hyperv> <kvm> <hidden state='on'/> </kvm> </features>同时在
<cpu>块中添加:<feature policy='disable' name='hypervisor'/>
2.4 单 GPU 直通(无第二块显卡)
如果你只有一张显卡,直通后宿主机将失去图形输出。需要以下额外配置:
- 宿主机改为 headless:SSH 远程管理
- 引导阶段不要抢占 GPU:
video=efifb:off内核参数 - GPU ROM 提取:某些 GPU 需要提供 ROM file
echo 1 > /sys/bus/pci/devices/<PCI_BDF>/rom cat /sys/bus/pci/devices/<PCI_BDF>/rom > gpu.rom echo 0 > /sys/bus/pci/devices/<PCI_BDF>/rom - 关闭时归还 GPU:libvirt hook 脚本在 VM 停止时解绑 vfio-pci
2.5 USB 控制器直通
相比逐个透传 USB 设备,直通整个 USB 控制器的优势:
| 透传方式 | 热插拔 | 延迟 | 兼容性 |
|---|---|---|---|
| USB 重定向 (Spice) | 需手动选择 | 较高 | 依赖 guest 工具 |
| 单个 USB 设备 | 不支持 | 低 | 仅透传已选设备 |
| 整个 USB 控制器 | 原生支持 | 原生延迟 | 所有 USB 设备均可用 |
# 找到独立的 USB 控制器
lspci | grep USB
# 示例: <USB_CONTROLLER_BDF> USB controller: Intel Corp. ...
# 在 virt-manager 中: Add Hardware → PCI Host Device → 选择 USB 控制器游戏虚拟机最佳实践 对于游戏虚拟机,建议直通一个独立的 USB 3.0 PCIe 扩展卡。这样可以物理切换键盘/鼠标/耳机等外设。
3. virtio 驱动与性能优化#
3.1 virtio 架构原理
virtio 是一套半虚拟化 (paravirtualized) I/O 框架。Guest 知道自己运行在虚拟机中,通过 virtio 驱动直接与 QEMU 的 virtio 后端通信,绕过完整设备模拟的中间层。
flowchart LR
subgraph Guest
A[Guest Application]
B[virtio Frontend Driver]
end
subgraph Hypervisor
C[QEMU virtio Backend]
D["vhost (kernel)"]
E["vhost-user (userspace)"]
end
subgraph Host Hardware
F[Physical I/O Device]
end
A --> B
B -->|virtqueue / shared memory| C
C --> D
C --> E
D --> F
E --> F3.2 virtio 设备类型对比
| 设备类型 | 存储/网络设备 | 性能特点 | 推荐场景 |
|---|---|---|---|
| virtio-blk | 块设备 | 支持多队列,实际 IOPS 依后端与配置 | 一般存储 |
| virtio-scsi | SCSI 控制器 | 多 LUN,支持 SCSI 命令 | 需要 SCSI 功能的场景 |
| virtio-net | 网卡 | 多队列,vhost 加速 | 所有网络场景 |
| virtio-gpu | 显卡 | virgl 3D 加速(Linux guest) | 需要 3D 的 Linux VM |
| virtio-serial | 串口 | VM-guest 通信通道 | guest-agent 通信 |
| virtio-rng | 随机数 | 从 host 获取熵 | 加密密集型应用 |
| virtio-balloon | 内存 | 动态调整 guest 内存 | 内存超分配 |
| virtio-fs | 文件系统 | host-guest 目录共享 | 共享文件目录 |
| virtio-input | 输入设备 | 低延迟鼠标/键盘 | 替代 USB 重定向 |
| virtio-mem | 内存热插拔 | 运行时增减内存 | 灵活内存管理 |
3.3 Windows Guest virtio 驱动安装
Windows 不内置 virtio 驱动,需要从 Fedora 项目下载:
# 下载 virtio-win ISO
wget https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso
# 挂载到虚拟机,然后在 Windows 中浏览安装安装顺序:
- 安装阶段:Windows 安装程序选择磁盘时,"加载驱动程序" -> 浏览 virtio ISO -> 选择对应 Windows 版本的
viostor目录 - 安装后:运行
virtio-win-guest-tools.exe或逐个安装:NetKVM— 网络驱动viostor— 磁盘驱动vioinput— 鼠标/键盘输入qxldod— QXL 显示驱动vioserial— 串口驱动(用于 guest-agent)
- guest-agent:安装
qemu-ga-x64.msi
Linux Guest:
# virtio 驱动内置于内核主线,只需安装 guest-agent
sudo apt install qemu-guest-agent # Debian/Ubuntu
sudo pacman -S qemu-guest-agent # Arch
sudo dnf install qemu-guest-agent # Fedora
# 启用并启动服务
sudo systemctl enable --now qemu-guest-agent3.4 CPU 与内存性能调优
CPU Pinning(CPU 绑定):
将 vCPU 绑定到固定的物理 CPU 核心,避免调度抖动,对延迟敏感的工作负载至关重要。
<cputune>
<vcpupin vcpu='0' cpuset='2'/>
<vcpupin vcpu='1' cpuset='8'/>
<vcpupin vcpu='2' cpuset='3'/>
<vcpupin vcpu='3' cpuset='9'/>
<emulatorpin cpuset='0-1'/>
<iothreadpin iothread='1' cpuset='10-11'/>
</cputune>SMT / Hyper-Threading 注意事项 cpuset 数字是示意逻辑 CPU ID,不保证 2 与 8 为 SMT 兄弟。先用
lscpu -e和thread_siblings_list查实际拓扑,留出 housekeeping CPU,再按共享缓存/延迟目标测量绑定效果。iothreadpin还要求域实际定义相应 iothread。
CPU 隔离 (isolcpus):
# 内核命令行添加,防止宿主机使用指定核心
isolcpus=2-9,10-17
# isolcpus 的 domain 隔离标志被标为 deprecated,其他标志语义不同;优先评估可动态管理的 cpuset,并保留 housekeeping CPUvCPU 拓扑:
<cpu mode='host-passthrough' check='none'>
<topology sockets='1' dies='1' cores='4' threads='2'/>
<cache mode='passthrough'/>
<feature policy='require' name='topoext'/>
</cpu>host-passthrough:将宿主机 CPU 特性完整暴露给 guest,最大性能check='none':跳过 QEMU 的 CPU 模型验证sockets='1' cores='4' threads='2':模拟 1 socket x 4 核 x 2 线程 = 8 vCPU
HugePages(大页内存):
# 宿主机配置 2MB 大页
# /etc/default/grub 或内核命令行
hugepagesz=2M hugepages=4096
# 4096 × 2MB = 8GB 大页池
# 运行时配置
sudo sysctl vm.nr_hugepages=4096
# 查看大页状态
cat /proc/meminfo | grep Huge<!-- libvirt XML -->
<memoryBacking>
<hugepages/>
<locked/>
</memoryBacking>什么时候用 HugePages? 对于内存 > 8GB 且需要稳定性能的虚拟机(游戏、数据库、AI 推理),大页可以显著减少 TLB miss。但对于轻量级 VM,THP (Transparent Huge Pages) 已足够。
性能优化速查表:
| 技术 | 效果 | 应用场景 | 复杂度 |
|---|---|---|---|
| CPU Pinning | 消除 vCPU 调度抖动 | 延迟敏感(游戏/实时) | 中 |
| isolcpus / cgroup | 防止宿主机抢占核心 | 与 CPU Pinning 配合 | 中 |
| HugePages | 减少 TLB miss | 大内存 VM | 中 |
| host-passthrough | 最大化 CPU 特性暴露 | 适用于不需要异构迁移的场景;仍需测量 | 低 |
| IOThreads | 独立磁盘 I/O 线程 | 高 IOPS 场景 | 低 |
| Multi-queue NIC | 网络并行处理 | 多 vCPU + 高吞吐 | 低 |
3.5 网络优化
Multi-queue virtio-net:
<interface type='network'>
<model type='virtio'/>
<driver name='vhost' queues='8'/>
</interface>queues 数量建议等于 vCPU 数量。
# Guest 内设置队列数
sudo ethtool -L eth0 combined 8
# 验证
ethtool -l eth0vhost-net vs vhost-user:
| 后端 | 位置 | 延迟 | 功能 |
|---|---|---|---|
| QEMU 用户态 | QEMU 进程 | 高 | 兼容性最好 |
| vhost-net | 内核 | 低 | 标准选择 |
| vhost-user | DPDK/SPDK 用户态进程 | 极低 | 需要额外配置 |
3.6 磁盘 I/O 优化
<!-- iothreads 在 domain 顶层,disk driver 引用对应 ID;本片段须放入正确位置。 -->
<iothreads>1</iothreads>
<!-- devices 内: -->
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' cache='none' io='native' discard='unmap' iothread='1'/>
<source file='/var/lib/libvirt/images/vm.qcow2'/>
<target dev='vda' bus='virtio'/>
</disk>| 参数 | 选项 | 含义 |
|---|---|---|
cache |
none |
绕过宿主机页缓存,直接 O_DIRECT |
cache |
writeback |
使用宿主机页缓存;正确性取决于 flush 和存储,性能需实测 |
cache |
writethrough |
同步确认;不保证所有设备故障下的安全,延迟需实测 |
cache |
directsync |
O_DIRECT + 同步确认;仍需底层存储持久性保证 |
io |
native |
使用 Linux AIO;通常配合 cache=none/directsync,性能需测量;io_uring 支持依版本 |
discard |
unmap |
支持 TRIM/DISCARD,释放磁盘空间 |
4. virtiofs —— 主机与虚拟机文件共享#
virtiofs 是 QEMU 5.0+ 引入的半虚拟化文件系统,替代老旧的 virtio-9p,提供 host-guest 间的高性能文件共享。
4.1 与替代方案对比
| 方案 | 吞吐量 | POSIX 语义 | 配置复杂度 | 推荐度 |
|---|---|---|---|---|
| virtiofs | 极高 | 完整 | 中 | 首选 |
| virtio-9p | 低 | 不完整 | 低 | 遗留兼容 |
| NFS | 中-高 | 较完整 | 中 | 多 VM 共享 |
| Samba/CIFS | 低-中 | 不完整 | 低 | Windows guest |
| VirtFS (9p) | 低 | 部分 | 低 | 废弃 |
4.2 环境要求
- Linux Guest kernel >= 5.4(virtiofs 驱动;Host 还需对应软件支持)
- QEMU >= 5.0(推荐 >= 8.0)
- libvirt >= 6.2
- virtiofsd 守护进程(现代常为独立 Rust 包;路径与选项按版本核对)
# 确认 virtiofsd 可用
which virtiofsd
# 通常位于 /usr/lib/qemu/virtiofsd 或 /usr/libexec/virtiofsd4.3 完整配置
Step 1: 宿主机创建共享目录
mkdir -p ~/vm-shared
chmod 755 ~/vm-sharedStep 2: libvirt 内存后备配置
virtiofs 需要用共享内存 (memfd) 作为通信通道:
<domain type='kvm'>
<!-- ... -->
<memoryBacking>
<source type='memfd'/>
<access mode='shared'/>
</memoryBacking>
<!-- ... -->
</domain>Step 3: 添加 filesystem 设备
<filesystem type='mount' accessmode='passthrough'>
<driver type='virtiofs'/>
<source dir='/home/user/vm-shared'/>
<target dir='share_tag'/>
<binary path='/usr/libexec/virtiofsd' xattr='on'>
<cache mode='always'/>
<sandbox mode='chroot'/>
</binary>
</filesystem>| 参数 | 说明 |
|---|---|
accessmode='passthrough' |
按 passthrough 语义处理权限/所有者;实际 UID/GID 映射与 daemon 权限需检查 |
source dir |
Host 端目录路径 |
target dir |
Guest 端挂载标签(非实际路径,是标识名) |
cache mode='always' |
更积极缓存;与宿主并发修改时需核对一致性语义 |
cache mode='auto' |
默认,根据访问模式自动选择 |
xattr='on' |
启用扩展属性支持 (SELinux) |
Step 4: Guest 内挂载
# 手动挂载
sudo mount -t virtiofs share_tag /mnt/shared
# 验证挂载
mount | grep virtiofs
df -h /mnt/shared
# 自动挂载 (/etc/fstab)
share_tag /mnt/shared virtiofs defaults 0 0fstab 挂载顺序 virtiofs 是本地虚拟设备,不必视为网络文件系统。可按客体 systemd/启动依赖选择
nofail,x-systemd.automount,并验证设备就绪与挂载结果;_netdev只改变挂载顺序语义:share_tag /mnt/shared virtiofs defaults,nofail,x-systemd.automount 0 0
virt-manager 操作路径:
- Add Hardware -> Filesystem
- Type:
mount, Driver:virtiofs - Source path:
/home/user/vm-shared - Target path:
share_tag(自定义标签)
4.4 DAX (Direct Access) 窗口配置
本节是 DAX 设计示意,不代表下面 memfd/cache 片段就启用了 DAX window。DAX 必须有匹配的 QEMU、virtiofsd、客体内核及实际窗口配置;当前实现是否支持需查对应版本,不能仅加 mount -o dax 保证生效。
DAX 的设计允许 guest 映射 host 文件页,减少部分缓存路径;收益和支持条件需要按完整软件栈验证:
<memoryBacking>
<source type='memfd'/>
<access mode='shared'/>
</memoryBacking>
<!-- ... -->
<filesystem type='mount' accessmode='passthrough'>
<driver type='virtiofs'/>
<source dir='/home/user/vm-shared'/>
<target dir='share_tag'/>
<binary path='/usr/libexec/virtiofsd'>
<cache mode='always'/>
</binary>
</filesystem>使用 DAX 挂载:
sudo mount -t virtiofs -o dax share_tag /mnt/shared5. 磁盘镜像高级操作#
qemu-img 面向离线磁盘。任何修改、转换、修复、快照、resize、commit 或 rebase 前都必须停止所有使用者并备份;在线查询也可能看到不一致的元数据。check -r all 可能丢失数据,先复制原件。qemu-img 的磁盘内部快照不保存 guest RAM、UEFI NVRAM 或 TPM 状态。
5.1 qemu-img 命令大全
# ========== 创建镜像 ==========
# 创建 qcow2 格式(精简配置,按需增长)
qemu-img create -f qcow2 disk.qcow2 40G
# 创建预分配 qcow2(避免碎片)
qemu-img create -f qcow2 -o preallocation=full disk.qcow2 40G
# 创建 raw 格式(通常是稀疏文件;完整预分配可显式选择 preallocation=full)
qemu-img create -f raw disk.raw 40G
# 创建 qcow2 带集群大小(默认 64K)
qemu-img create -f qcow2 -o cluster_size=2M disk.qcow2 100G
# ========== 转换镜像 ==========
# raw -> qcow2(最常用:回收空间)
qemu-img convert -f raw -O qcow2 old.img new.qcow2
# qcow2 -> raw(性能优化)
qemu-img convert -f qcow2 -O raw old.qcow2 new.raw
# 压缩转换(-c 压缩目标镜像)
qemu-img convert -c -f raw -O qcow2 old.img compressed.qcow2
# 离线转换:-W 允许目标乱序写,不提供在线一致性;仅在合适的预分配目标上考虑
qemu-img convert -f raw -O qcow2 source.img target.qcow2
# 进阶示意:预分配 raw 目标;仍要求源离线
qemu-img convert -W -f raw -O raw -o preallocation=full source.img target.raw
# ========== 查看信息 ==========
# 查看镜像元数据
qemu-img info disk.qcow2
# virtual size: 40 GiB
# disk size: 2.3 GiB
# cluster_size: 65536
# backing file: base.qcow2
# 查看详细 JSON 输出
qemu-img info --output=json disk.qcow2
# 一致性检查
qemu-img check disk.qcow2
# 修复发现的错误(慎用)
qemu-img check -r all disk.qcow2
# ========== 快照操作 ==========
# 创建快照
qemu-img snapshot -c snap1_before_update disk.qcow2
# 列出所有快照
qemu-img snapshot -l disk.qcow2
# 应用/回滚到某快照
qemu-img snapshot -a snap1_before_update disk.qcow2
# 删除快照
qemu-img snapshot -d snap1_before_update disk.qcow2
# ========== 调整大小 ==========
# 扩容(仅扩大虚拟磁盘,分区/文件系统需在 guest 内扩展)
qemu-img resize disk.qcow2 +20G
# 缩容(先在客体/离线工具中安全缩文件系统与分区;新边界必须容纳全部结构与数据,XFS 等不支持常规缩容)
qemu-img resize disk.qcow2 -10G --shrink
# 显式截短该镜像的虚拟大小(不是重新计算链;满足全部缩容前提才可操作)
qemu-img resize --shrink disk.qcow2 20G5.2 Backing Chain(增量镜像链)
qcow2 支持基于 backing file 的增量叠加,类似 overlay 文件系统:
# 创建基础镜像
qemu-img create -f qcow2 base.qcow2 40G
# 基于基础镜像创建 overlay(记录差异)
qemu-img create -f qcow2 -b base.qcow2 -F qcow2 overlay.qcow2
# 查看 backing chain
qemu-img info --backing-chain overlay.qcow2flowchart TD
A["base.qcow2 / OS 安装 + 基础软件 / 40GB virtual, 15GB actual"]
B["overlay1.qcow2 / backing: base.qcow2 / Application 1 改变 / diff: 2GB"]
C["overlay2.qcow2 / backing: overlay1.qcow2 / Application 2 改变 / diff: 500MB"]
A -->|backing file| B
B -->|backing file| CBacking Chain 操作:
# 合并 overlay 到 base(commit)
qemu-img commit overlay.qcow2
# 重构 backing chain(rebase)
qemu-img rebase -b new_base.qcow2 -F qcow2 overlay.qcow2
# 拍平 backing chain(合并所有 overlay 生成独立镜像)
qemu-img convert -f qcow2 -O qcow2 overlay2.qcow2 standalone.qcow2Backing chain 的危险操作 base 中未被 overlay 覆盖的扇区仍会被读取,因此改写共享 base 会改变所有依赖它的客体数据视图;不应把这解释成“扇区偏移必然失效”。正常运行中 base 应保持不可变。
- 修改前列出所有依赖链并停止写入者,备份完整链。
commit会写入 backing file,可能影响其他 overlay;不能作为修改共享 base 前的通用安全步骤。- 安全模式
rebase会读取旧/新 base 并保留客体视图;-u只改元数据,错误使用会破坏视图。格式、路径与底层数据均需核对。- 需要独立副本时优先将离线链 convert 拍平,并验证副本;不对在线镜像运行这些工具。
5.3 存储池管理
定义 LVM/disk 池前核对设备稳定 ID、容量、现有分区及使用者;定义与 build/格式化是不同操作,后者可能毁掉现有数据。物理块设备不是“空白镜像”,不能凭 /dev/sdX 名称操作。后端是否支持该功能依当前 libvirt 编译与版本。
libvirt 存储池类型:
| 类型 | 适用场景 | 特点 |
|---|---|---|
| Directory | 通用 | 最简单,宿主机文件系统 |
| LVM | 高性能块存储 | 快照、精简分配 |
| ZFS | 高级存储 | 快照、克隆、send/recv、压缩、去重 |
| NFS | 集中存储/迁移 | 远程访问、多宿主机共享 |
| iSCSI | SAN | 高可用、企业级 |
| GlusterFS | 分布式 | 横向扩展 |
| RBD (Ceph) | 云规模 | 极大规模、副本、自动修复 |
创建存储池:
# Directory 类型 (最常用)
virsh pool-define-as --name images --type dir --target /var/lib/libvirt/images
virsh pool-start images
virsh pool-autostart images
# LVM 类型
virsh pool-define-as --name lvm_pool --type logical \
--source-device "/dev/disk/by-id/<LVM_SOURCE_DISK_ID>" --target /dev/vg_kvm存储池管理命令:
virsh pool-list --all # 列出所有存储池
virsh pool-info images # 存储池详情
virsh pool-refresh images # 刷新(重新扫描卷)
virsh vol-list images # 列出池中所有卷
virsh vol-info disk.qcow2 --pool images # 卷信息
virsh vol-create-as images new_disk.qcow2 40G --format qcow2
virsh vol-delete disk.qcow2 --pool images5.4 磁盘性能对比
| 格式 | 精简分配 | 快照 | 压缩 | 性能 | 推荐场景 |
|---|---|---|---|---|---|
| raw | 文件可稀疏/后端可精简 | 无 qcow2 内部快照,后端可快照 | 无原生压缩 | 依后端与负载 | 简单文件或块设备镜像 |
| qcow2 | 是 | 是 | 是 | 高(约 95% raw) | 通用推荐 |
| vmdk | 是 | 是 | 部分 | 中 | VMware 兼容 |
| vdi | 是 | 是 | 部分 | 中 | VirtualBox 兼容 |
5.5 Guest 内分区扩展
qemu-img resize 只扩大了虚拟磁盘,还需要在 guest 内扩展分区和文件系统:
# === Guest 内操作 ===
# 1. 查看当前分区表
lsblk
sudo fdisk -l /dev/vda
# 2. 扩展分区(以 GPT + systemd-growfs 为例)
sudo growpart /dev/vda 1 # 扩展第 1 个分区
# 3. 扩展文件系统
# ext4
sudo resize2fs /dev/vda1
# XFS
sudo xfs_growfs /
# Btrfs
sudo btrfs filesystem resize max /
# 4. 验证
df -h /virt-resize 离线扩容 如果 guest 分区布局复杂,可以在 guest 关机后使用 libguestfs 工具:
先离线备份并检查客体分区;预先创建足够大的目标文件(如 `qemu-img create -f qcow2 new.qcow2 <LARGER_SIZE>`),再执行: `virt-resize --expand /dev/sda1 old.qcow2 new.qcow2`。这里 /dev/sda1 指镜像内的客体分区,不是宿主磁盘;支持的文件系统与扩展结果需核对。
6. 高级网络配置#
NAT、isolated、bridge 和 macvtap 的安全与性能由规则、拓扑和负载决定,表中的高低仅表示原笔记概览,不是测量结果。NAT/isolated 不阻断客体对宿主桥与同网段客体;bridge/macvtap 需外部网络授权,macvtap 不是 PCI 直通。普通 Wi-Fi client 常不能透明桥接多个 MAC。变更宿主 IP/路由前准备本地或带外恢复。
6.1 网络模式对比
| 模式 | NAT | 隔离性 | 外部可访问 | 性能 | 使用场景 |
|---|---|---|---|---|---|
| NAT (default) | 是 | 高 | 否(需端口转发) | 中 | 桌面虚拟化 |
| Bridged | 否 | 低 | 是(同网段 IP) | 高 | 服务器虚拟化 |
| macvtap (VEPA) | 否 | 中 | 是 | 极高 | 高性能场景 |
| macvtap (Bridge) | 否 | 低 | 是 | 极高 | 单机高性能 |
| PCI Passthrough (SR-IOV) | 否 | 无 | 是 | 接近裸机 | 极致性能 |
6.2 桥接网络配置
# /etc/network/interfaces (Debian/Ubuntu) 或使用 NetworkManager / systemd-networkd
# 使用 nmcli (NetworkManager)
nmcli connection add type bridge ifname br0
nmcli connection add type ethernet slave-type bridge con-name bridge-br0 ifname eth0 master br0
nmcli connection up br0<!-- libvirt XML -->
<interface type='bridge'>
<!-- 未指定 MAC,由 libvirt 生成;迁移现有 VM 应保留其地址。 -->
<source bridge='br0'/>
<model type='virtio'/>
</interface>6.3 macvtap 高性能直通
macvtap 将客体虚拟网卡关联到宿主物理接口,无需传统 bridge;它仍经过宿主网络路径,并非 PCI/VFIO 网卡直通:
<interface type='direct'>
<source dev='eth0' mode='bridge'/>
<model type='virtio'/>
</interface>macvtap 模式:
| 模式 | 行为 | 适用场景 |
|---|---|---|
| VEPA | VM 间流量经外部交换机转发 | 企业环境 |
| Bridge | 宿主机上的 VM 间可直接通信 | 单机多 VM |
| Private | VM 间完全隔离 | 安全隔离 |
| Passthrough | 一个 VM 独占网卡 | 单 VM 高性能 |
macvtap 的局限 macvtap bridge 模式下,宿主机自身无法与 VM 通信(即使是同一物理网卡)。这是 Linux macvlan 的设计限制。如需宿主机与 VM 通信,在宿主机的 macvtap 接口上额外配置一个 macvlan 或者改用传统 bridge。
参考与延伸
根据技术笔记重新整理,示例使用通用名称。