KVM虚拟机磁盘IO性能差,virtio‑blk
KVM 虚拟机磁盘 IO 性能差,绝大多数情况不是硬件不行,而是虚拟磁盘的驱动类型、缓存模式和底层调度没有对齐。
只要把磁盘总线切换为 virtio-blk,选对 cache 模式,再调整宿主机 IO 调度器,就能在不动硬件的情况下获得明显提升。
以下步骤适用于 libvirt 管理的 KVM 虚拟机,操作前请先备份虚拟机配置文件。
先判断瓶颈:跑一轮性能基线测试
在改任何参数之前,先确认虚拟机当前磁盘接口和缓存模式。
在宿主机执行:
virsh dumpxml 虚拟机名 | grep -E ""
重点看三处:vda 表示 virtio-blk,sda 表示 SATA 或 IDE;qemu 和 type=raw/qcow2;cache= 当前是什么值。
同时用 iotop 或 iostat 观察虚拟机内高 IO 负载时宿主机磁盘的等待时间,把调优前后的数据留作对比。
使用 virtio-blk 半虚拟化驱动
virtio-blk 是 KVM 默认推荐的高性能磁盘驱动,绕过传统设备模拟,直接通过共享内存收发 IO 请求。
如果虚拟机当前用的是 sda 或 hda,需要修改虚拟机的 .xml 配置文件。
先关闭虚拟机,然后编辑配置:
virsh edit 虚拟机名
找到 标签,把总线类型改成 virtio,例如:
改完后启动虚拟机,在虚拟机内执行 lsblk 或 lspci | grep -i virtio,看到 vda 以及 Virtio block device 即表示驱动生效。
需要留意:从 IDE/SATA 改成 virtio 后,Linux 内的磁盘名会从 /dev/sda 变为 /dev/vda,如果虚拟机用着旧盘符挂载,可能需要修改 /etc/fstab 和引导配置,否则开机可能失败。
建议先拍快照再操作。
缓存模式怎么选:none、writeback、writethrough
cache 模式直接决定数据写入宿主机缓存层的方式,对 IO 性能影响最大。
| 模式 | 行为 | 适用场景 |
| --- | --- | --- |
| none | 关闭宿主机页缓存写入,数据直写磁盘,但保留读缓存 | 数据库、日志型应用,最稳最快 |
| writeback | 数据先写宿主机页缓存,异步刷盘 | 对掉电不敏感、可承受少量数据丢失的测试机 |
| writethrough | 每次写入都同步落盘,最安全但最慢 | 需要强一致性的关键业务 |
对于大部分生产环境,推荐 cache='none'。
虽然名字叫 none,但它仍然使用宿主机页面缓存做读加速,同时避免 writeback 模式下虚拟机以为数据落盘、实际还在宿主机缓存中的安全隐患。
修改方式同样通过 virsh edit,修改 标签中的 cache 值,重启虚拟机生效。
宿主机 IO 调度器与队列深度调整
磁盘 IO 性能差有时候不是虚拟机的问题,而是宿主机底层排队太长。
查看当前调度器:
cat /sys/block/sda/queue/scheduler
常见结果有 noop、deadline、mq-deadline、kyber、bfq。
物理 HDD 建议用 deadline 或 mq-deadline,SSD 和 NVMe 建议用 none(即 noop)。
临时修改:
echo none > /sys/block/sda/queue/scheduler
永久生效需要配合 udev 规则或内核引导参数。
另外,如果宿主机 CPU 核心较多,可以给 virtio-blk 开启多队列。
在虚拟机 XML 的 或 中使用 ,队列数建议与 vCPU 数量一致或等于宿主机物理核心数,然后查看虚拟机内 /sys/block/vda/queue/ 下是否有多个 mq 队列。
性能验证:用 fio 看真实提升
调优后不要只看“感觉变快了”,用 fio 做一次前后对比。
在虚拟机内安装 fio(CentOS:yum install fio,Ubuntu:apt install fio),然后跑随机读写:
fio --name=randwrite --rw=randwrite --bs=4k --size=1G --iodepth=16 --runtime=30 --time_based --filename=/tmp/testfile --direct=1
fio --name=randread --rw=randread --bs=4k --size=1G --iodepth=16 --runtime=30 --time_based --filename=/tmp/testfile --direct=1
重点看 IOPS(每秒读写次数)和 latency(延迟)。
如果 cache=none 搭配 virtio-blk 后数据依然很差,再检查宿主机磁盘健康状态(smartctl -a)、RAID 卡写缓存策略是否开启,以及是否用了共享存储与网络瓶颈。
避坑说明与常见误区
不要以为 cache=writeback 一定更快。
在大量随机写场景下,writeback 的优势会被刷盘线程吃掉,反而造成延迟抖动。
不要只改 XML 忽略虚拟机内驱动。
Windows 虚拟机需要提前安装 virtio-win 驱动,否则切换 virtio 后直接蓝屏。
Windows 的 VirtIO 驱动可以从官方 virtio-win 镜像获取,镜像挂载后右键安装即可。
不要拿 qcow2 的默认参数跑生产。
qcow2 格式本身比 raw 多一层元数据开销,如果追求极限性能,可以使用 raw 格式或预分配 qcow2(virt-sparsify 或创建时用 preallocated=yes)。
关于缓存模式的一致性提醒:none 模式遇到宿主机断电时,虚拟机内已经确认写入的数据是否完整,取决于物理磁盘本身的写缓存策略;
真正的硬保证需要带电池的 RAID 卡或支持掉电保护的 SSD。
建议生产环境配合冗余存储层使用。
按上面的步骤把 virtio-blk、缓存模式和调度器都检查一遍,多数 KVM 虚拟机磁盘 IO 性能差的问题都能解决。
改完配置记得先对比 fio 数据再决定是否收工,遇到启动异常时可以回到本文的避坑部分逐项排查。
如果你正在处理类似的磁盘性能问题,建议先基于当前版本测试验证,再根据实际负载微调参数。