将 raw 格式转换为 qcow2 格式是 KVM 虚拟化环境中常见的操作,本文主要介绍如何使用qemu工具将虚拟机的镜像文件从raw格式转换为qcow2格式。

KVM 虚拟机硬盘文件格式

KVM 虚拟机可以使用多种格式的硬盘文件,其中 raw 和 qcow2 是两种最常用的格式。

raw 格式

工作原理:

raw 格式文件是原始磁盘镜像,它直接复制了物理硬盘的扇区数据,没有经过任何压缩或转换。因此,raw 文件的大小与它所代表的虚拟磁盘大小完全相同。

特点:

  • 优点:

    • 高性能: 由于没有额外的转换层,raw 格式文件读写速度最快。
    • 简单直接: 结构简单,易于理解和管理。
    • 兼容性好: 可以被大多数虚拟化软件和工具识别。
  • 缺点:

    • 空间占用大: 即使虚拟磁盘内部有很多空闲空间,raw 文件也会占用全部空间。
    • 不支持快照: 无法创建磁盘快照,备份和恢复操作效率低。
    • 安全性较低: raw 文件包含了所有数据,包括已删除的文件,存在数据泄露风险。

适用场景:

  • 对性能要求极高的虚拟机,例如数据库服务器。
  • 需要将虚拟磁盘镜像直接复制到物理硬盘的场景。
  • 需要与其他不支持 qcow2 格式的虚拟化软件或工具兼容的场景。

qcow2 格式

工作原理:

qcow2 格式文件是 QEMU 镜像文件格式,它是一种精简配置的磁盘镜像,采用了多种技术来提高存储效率和性能。

  • 写时复制 (Copy-on-Write): qcow2 文件初始大小很小,只有在写入数据时才会分配实际空间。
  • 压缩: qcow2 文件支持多种压缩算法,可以有效减小文件大小。
  • 快照: qcow2 文件支持创建多个磁盘快照,方便进行备份、恢复和测试。

特点:

  • 优点:

    • 节省存储空间: 只占用实际使用的磁盘空间,支持压缩。
    • 支持快照: 方便备份、恢复和测试。
    • 安全性更高: 可以加密镜像文件,保护数据安全。
    • 高级功能: 支持 AES 加密、zlib 压缩等高级功能。
  • 缺点:

    • 性能略低: 由于引入了额外的转换层,性能略低于 raw 格式。
    • 兼容性稍差: 主要用于 KVM 和 QEMU 等虚拟化软件。

适用场景:

  • 大多数 KVM 虚拟机场景。
  • 需要节省存储空间的场景。
  • 需要频繁创建快照进行备份和测试的场景。
  • 对安全性要求较高的场景。

总结:

特性raw 格式qcow2 格式
文件大小与虚拟磁盘大小相同远小于虚拟磁盘大小,按需分配
性能最快略慢于 raw 格式
快照不支持支持
压缩不支持支持
安全性较低较高
适用场景对性能要求极高、需要直接复制到物理硬盘大多数场景,节省空间、支持快照、安全性更高

总的来说,qcow2 格式在功能、效率和安全性方面都优于 raw 格式,除非对性能有较高的要求,不然一般推荐使用qcow2作为 KVM 虚拟机使用的硬盘文件格式。

转换格式

检查硬盘

改造前我们先进入虚拟机中检查一下硬盘的相关信息:

[root@infra-centos7 ~]# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda    253:0    0  150G  0 disk 
├─vda1 253:1    0    1G  0 part /boot
└─vda2 253:2    0  149G  0 part /
[root@infra-centos7 ~]# blkid
/dev/vda1: UUID="763539f9-fc49-443a-a246-4cedb357dc92" TYPE="xfs" 
/dev/vda2: UUID="4110a890-d483-4d07-af95-dda95c600e96" TYPE="xfs" 
[root@infra-centos7 ~]# df -Th | grep vda
/dev/vda2      xfs       149G   70G   80G  47% /
/dev/vda1      xfs      1014M  279M  736M  28% /boot

然后在宿主机上面查看文件信息

root@tiny-unraid:/mnt/user/domains/infra-centos7# qemu-img info vdisk1.img 
image: vdisk1.img
file format: raw
virtual size: 150 GiB (161061273600 bytes)
disk size: 150 GiB

转换命令

接着使用这个命令进行转换

root@tiny-unraid:/mnt/user/domains/infra-centos7# qemu-img convert -f raw -O qcow2 -c vdisk1.img vdisk1.qcow2

让我们逐个分析命令中的参数:

  • qemu-img convert: 这是 qemu-img 工具的子命令,用于转换磁盘镜像文件的格式。
  • -f raw: 指定源磁盘镜像文件的格式为 raw
  • -O qcow2: 指定目标磁盘镜像文件的格式为 qcow2
  • -c: 可选参数,表示在转换过程中对 qcow2 镜像进行压缩。
  • vdisk1.img: 源磁盘镜像文件的名称。
  • vdisk1.qcow2: 转换后的目标磁盘镜像文件的名称。

命令执行过程:

  1. qemu-img 读取源文件 vdisk1.img,该文件为 raw 格式。
  2. qemu-img 将 raw 格式的数据转换为 qcow2 格式。
  3. 如果使用了 -c 参数,qemu-img 会在转换过程中对 qcow2 镜像进行压缩。
  4. qemu-img 将转换后的 qcow2 格式数据写入目标文件 vdisk1.qcow2

转换完成之后我们查看qcow2文件的信息,可以看到转换前后的文件大小有非常明显的差别

root@tiny-unraid:/mnt/user/domains/infra-centos7# ls -lh
total 182G
-rwxrwxr-x 1 root users 150G Jun 24 14:07 vdisk1.img*
-rw-r--r-- 1 root root   32G Jun 24 15:07 vdisk1.qcow2

root@tiny-unraid:/mnt/user/domains/infra-centos7# qemu-img info vdisk1.qcow2 
image: vdisk1.qcow2
file format: qcow2
virtual size: 150 GiB (161061273600 bytes)
disk size: 31.5 GiB
cluster_size: 65536
Format specific information:
    compat: 1.1
    compression type: zlib
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
    extended l2: false

这里还需要注意,如果担心ls命令看到的文件大小并不是文件真实占用硬盘空间的大小,可以考虑使用du命令来检查

默认情况下使用dd命令来生成一个raw文件,并不会马上占用对应的硬盘大小。(例如dd一个100G大小的raw文件,实际并不会马上占用100G的硬盘,只会随着实际使用而不断增长)

但是还有一种特殊的情况就是使用rsync命令备份这些文件的时候,因为raw文件的特性,如果一个100G的raw硬盘文件,只使用了30G,实际只占用了30G硬盘,因为rsync过程中对文件的复制操作,会导致复制过后的新文件大小变为100G。

修改xml配置

修改前xml文件

qemu转换完成之后我们需要修改kvm虚拟机的xml配置文件

    <disk type='file' device='disk'>
      <driver name='qemu' type='raw' cache='writeback'/>
      <source file='/mnt/user/domains/infra-centos7/vdisk1.img'/>
      <target dev='hdc' bus='virtio'/>
      <boot order='1'/>
      <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
    </disk>
    

解析一下上面的这段配置

1. 硬盘缓存模式 cache='writeback'

  • writeback 模式下,数据写入磁盘镜像文件时会先缓存到主机内存,稍后再写入磁盘。
  • 优点:提升写入性能。
  • 缺点:存在数据丢失风险,如果主机崩溃,缓存中的数据将丢失。

建议:

  • 除非对性能要求极高,否则建议使用更安全的缓存模式,例如:

    • cache='none':禁用缓存,每次写入都直接写入磁盘,最安全但性能较低。
    • cache='writethrough':写入数据时同时写入缓存和磁盘,兼顾性能和安全性。

2. 硬盘总线类型 bus='virtio'

  • virtio 是半虚拟化驱动,性能优于模拟设备。
  • 但需要客户机操作系统安装 virtio 驱动才能识别。

建议:

  • 确认客户机操作系统已安装 virtio 驱动,例如 Ubuntu 通常默认安装。
  • 如果客户机操作系统不支持 virtio,则需要使用模拟设备,例如 bus='ide'bus='scsi'

3. PCI 地址分配 address type='pci' ...

  • 这段配置为虚拟硬盘分配了固定的 PCI 地址。
  • 一般情况下,KVM 会自动分配 PCI 地址,无需手动指定。
  • 如果对这个配置进行了修改导致报错却又不知道如何还原,可以尝试将这段配置直接删除,删除后再次启动虚拟机一般会自动生成对应的新配置。

4. disk type

在 KVM 虚拟机配置文件中,<disk> 元素的 <driver> 子元素中的 type='raw' 指的是虚拟磁盘镜像文件的格式。

type='raw' 表示使用原始磁盘镜像格式。

  • 特点:
    • 直接映射: 虚拟磁盘文件直接映射到主机文件系统上的一个文件,没有额外的格式转换,读写性能最好。
    • 简单: 结构简单,创建和使用方便。
    • 空间占用大: 即使虚拟磁盘内部文件系统有空闲空间,镜像文件大小也不会自动缩减。

其他可用的 type 参数:

除了 raw 之外,qemu 驱动还支持其他几种虚拟磁盘镜像文件格式:

  • qcow2 (推荐):
    • QEMU 默认格式,支持许多高级功能,例如:
      • 稀疏分配: 镜像文件大小可以动态增长,只占用实际使用的空间。
      • 快照: 可以创建虚拟磁盘的时间点副本。
      • 压缩: 可以压缩镜像文件,节省存储空间。
  • qed:
    • KVM/QEMU 早期版本使用的格式,功能较少,现在已经很少使用。
  • vmdk:
    • VMware 使用的虚拟磁盘格式,KVM 可以读取和使用,但不建议创建新的 vmdk 格式镜像。

修改后xml文件

这里主要修改的是source file和type字段

    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2' cache='writeback'/>
      <source file='/mnt/user/domains/infra-centos7/vdisk1.qcow2' index='1'/>
      <backingStore/>
      <target dev='hdc' bus='virtio'/>
      <boot order='1'/>
      <alias name='virtio-disk2'/>
      <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
    </disk>

重新登录机器之后我们检查硬盘的情况

[root@infra-centos7 ~]# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda    253:0    0  150G  0 disk 
├─vda1 253:1    0    1G  0 part /boot
└─vda2 253:2    0  149G  0 part /
[root@infra-centos7 ~]# blkid
/dev/vda1: UUID="763539f9-fc49-443a-a246-4cedb357dc92" TYPE="xfs" 
/dev/vda2: UUID="4110a890-d483-4d07-af95-dda95c600e96" TYPE="xfs" 
[root@infra-centos7 ~]# df -Th | grep vda
/dev/vda2      xfs       149G   70G   80G  47% /
/dev/vda1      xfs      1014M  279M  736M  28% /boot

到这里整个转换就完成了。