KVM虚拟机的模版导出,通常都是直接用qemu-img
命令可以将默认的raw
格式或者qcow2
格式的磁盘文件压缩后导出,指令如下:
//将默认raw格式的磁盘,简单压缩转换成qcow2格式
#qemu-img convert -c -f raw -O qcow2 vm500G.raw /path/new-vm500G.qcow2
//将默认qcow2格式的磁盘,导出为简单压缩后的qcow2格式
#qemu-img convert -c -O qcow2 vm500G.qcow2 new.img.qcow2
以上两种方法都能在一定程度上压缩减小导出后的镜像文件体积;但仅限于在虚拟机刚安装部署好,还没有进行过大量数据读写处理的情况下;
假如虚拟机磁盘大小分配40G,刚装好的操作系统加入占用了5G,那么通过以上的方式压缩导出的镜像文件可能也就只占4~5G左右;这是因为该磁盘镜像的大量的剩余空间都还没有被虚拟机的操作系统使用到(大量剩余block
块都是空白的,未写入过数据)所以在导出的过程中,这些空白的block
就会被压缩甚至忽略掉;所以这样压缩出来的缩效果还是很不错的;
但是,假如该虚拟机在装好后之后,有在磁盘上产生并存储过一个2G的大文件,尽管当前已经从虚拟机中彻底删除了这个大文件,虚拟机内的磁盘空间也显示剩余空间已经释放出来了,系统占用空间会变成跟系统刚装完时一样只有5GB;但此时再使用上面的指令对磁盘镜像文件进行压缩导出,你就会发现导出的文件体积比之前至少会多出2GB的体积;
这是因为虚拟机内删除文件,实际只是在分区表中把文件的索引给删除了,其2G文件的物理数据还是依然占用着磁盘上对应的block块的;此时在kvm下用qemu-img info
指令就可以清楚看到该虚拟磁盘镜像的物理占用空间(disk size)比之前也变大了2GB;
精简导出
那么有没有办法只导出当前虚拟机内实际占用的有效数据呢?将所有已经删除了的文件和其对应的磁盘block
块都忽略掉,不要导出到我们的镜像文件中,以最大程度缩减导出来的文件体积!
方法就是在导出镜像之前,先在虚拟机系统的内部,对所有未使用,以及所有剩余可使用的磁盘空间进行全面置零填充操作,可以简单理解为将当前所有未存储有效数据的block(含已删除的文件block)全都进行写0覆盖,然后再进行镜像压缩导出,就可以忽略所有这些无用的数据空间了;
虚拟机内部写零操作
#dd if=/dev/zero of=/null.dat //创建一个全0的大文件,占满所有的剩余磁盘空间,需要很久时间
#rm -f /null.dat //删除这个文件
KVM下的导出操作
针对
raw
格式虚拟磁盘文件精简导出#cp --sparse=always vm500G.raw vm500G-new.raw //--sparse=always稀疏拷贝,忽略全0数据
#qemu-img convert -c -f raw -O qcow2 vm500G.raw vm500G.qcow2
针对原本就是qcow2
格式的虚拟磁盘文件精简导出
#qemu-img convert -c -O qcow2 vm500G.qcow2 vm500G-mini.qcow2
实测导出数据大小对比
raw文件实际大小disk size: 5.8GB
直接导出qcow2镜像大小: 4.5GB
全置零后导出qcow2镜像大小: 2.2GB