pve 之上的虚拟机,需要依托硬盘使用。
虚拟机的硬盘实际上是分配在宿主机的一个块文件,然后由 pve 核心转换使用。
其中,pve 常用的有两种格式,qcow2 跟 raw。vmware 有自己的格式 vmdk。这三种格式的虚拟硬盘文件都有工具相对应转换。
RAW格式
raw 的本意是 “未加工的”,像数码相机的照片也有raw格式。
对于存储而言,raw 格式就是一块纯纯的块文件,用 dd 指令生成出来的文件,差不多就是这种格式的样子了。
优点
raw 的性能很强,而且由于是直接的块文件,除了能随时挂载、卸载设备,甚至在扩容的时候,可以直接合并、追加。
# 用0初始化一个4G的块,if = input file, of = output file, bs = block size, count = block count dd if=/dev/zero of=zeros.raw bs=1024k count=4096 # 合并输出到新的文件,new 就是 old 扩容4G的样子 cat old.img zeros.raw > new.img
把 new.img 重新挂到虚拟机之后,就相当于 pve 内置工具 qume-img 以下操作。
qemu-img resize old.img +4G
缺点
首先,原始格式往往意味着没有优化,类似数码相机的 raw 往往是最大的,raw 格式的存储也很大。raw 格式需要预分配且不能伸缩,在新建虚拟机的使用场景下,需要提前准备好容量(即使虚拟机还没占用这么大的容量空间)。
不过由于 Linux 对空洞文件的支持很好,所以实际上用 du 指令去查看大小的时候,显示会比 ls 查看的更小。
root@pve:~# ls -lh /mnt/mnme0n1p1/images/104/vm-104-disk-0.raw -rw-r----- 1 root root 107G Mar 17 16:49 /mnt/mnme0n1p1/images/104/vm-104-disk-0.raw
root@pve:~# du -lh /mnt/mnme0n1p1/images/104/vm-104-disk-0.raw 56G /mnt/mnme0n1p1/images/104/vm-104-disk-0.raw
这种情况下对空洞文件的支持,会让系统出现一些不容易理解的现象,比如通过 df -lh 查看容量的时候,发现 Avail 已经是 0,结果还是能往里面写东西。
此外,对于 raw 格式的逻辑也是按照设定大小来的。比如 rsync 上面的 raw 文件就要传输 107G 的数据。
再就是快照的问题。raw 格式的原始,使得快照没有什么捷径(比如qcow2格式快照差异即可)。所以 pve 并不提供 raw 格式的快照能力。当然有黑科技做二进制的差异版本管理来实现快照也有可行性,但终究还是黑科技了点。
QCOW2格式
QCOW2 = QEMU copy-on-write format 2。
亦即 QEMU (一款模拟处理器软件,PVE 支持的虚拟方式之一)的写时拷贝格式。
听到写时拷贝就有既视感了,没错,其实跟 docker 的 overlay 有点相似的意思。
优点
这种格式优点就很明显了,首先就是简单的快照化。只要做差异分层即可回滚到指定的快照去。而且快照速度很快。
再就是能动态伸缩大小,虚拟出来的虚拟机用多少,再在宿主机中申请出来多少。这种特性下不支持空洞文件的操作系统也无所谓优化了,du 跟 ls 命令下看到的容量是一致的。
root@pve:~# ls -lh /mnt/mnme0n1p1/images/103/vm-103-disk-0.qcow2 -rw-r----- 1 root root 289G Mar 17 17:11 /mnt/mnme0n1p1/images/103/vm-103-disk-0.qcow2
root@pve:~# du -lh /mnt/mnme0n1p1/images/103/vm-103-disk-0.qcow2 286G /mnt/mnme0n1p1/images/103/vm-103-disk-0.qcow2
速度方面,跟 raw 比有差距,但差距已经很小了。这里有 redhat 官方的测试:KVM qcow2 Performance。
缺点
这里提的缺点是个人在生产中遇到的,不知道是不是非必现 bug。
qcow2 格式在频繁的使用下,会出现宿主占用比实际内部占用更大,而且大很多的问题。如图,在发版机经历过 30TB/W 15TB/R(读写量)后,虚拟机内部:
宿主机PVE看到的:
硬盘读写情况:
猜测是大量的小文件操作之后,qcow2 产生了大量的碎片无法合并,进而越来越膨胀。
出现这种情况后,qcow2 并没有直接的 gc 指令,但理论上可以通过转换格式,来去掉中间的碎片。
qemu-img convert -f qcow2 -O raw vm-104-disk-0.qcow2 vm-104-disk-0.raw qemu-img convert -f raw -O raw vm-104-disk-0.raw vm-104-disk-0.qcow2
甚至有人提出了更黑科技的原地自转 qrow2 方法,而不用通过 raw 格式中转。这种方法就没有尝试过了。
qcow2 出现问题后的解决方法是有的,但由于它能膨胀超过原定的指定大小直至占满硬盘,这就是“计划外”的运维问题了,这一点很坑。
一旦出现这种情况,就需要立马给 qcow2 瘦身。否则虚拟机连交互都做不了。
VMDK格式
VMDK = vmware disk。
VMWare 是一个很老牌的虚拟机厂家(windows的同学很熟悉),他定的这种格式性能、稳定性应该是相当好的。不过 linux 很多虚拟化方式并不支持。
但 qemu-img 工具是支持对它的转换的,以此可以进行两边不同虚拟机的迁移。
qemu-img convert -f vmdk -O qcow2 image-from-vmware.vmdk image-for-kvm-qcow2.img