QCOW2/RAW/qemu-img 概念浅析

目录

  • 目录
  • 扩展阅读
  • RAW
  • QCOW2 QEMU-COW 2
    • QCOW2 Header
    • QCOW2 的 COW 特性
    • QCOW2 的快照
  • qemu-img 的基本使用
  • RAW 与 QCOW2 的区别

扩展阅读

The QCOW2 Image Format
为什么用ls和du显示出来的文件大小有差别?
Qcow2镜像格式解析
ROW/COW 快照技术原理解析

RAW

KVM 虚拟化中使用的镜像格式通常为 RAW 和 QCOW2 两种格式.

RAW 的原意是「未被加工的」, 所以 RAW 格式镜像文件又被称为 原始镜像裸设备镜像, 从这些称谓可以看出, RAW 格式镜像文件能够直接当作一个块设备, 以供 GuestOS 使用. 也就是说 KVM 的 GuestOS 可以直接从 RAW 镜像中启动, 就如 HostOS 直接从硬盘中启动一般.

块设备: IO 设备中的一类, 将信息存储在固定大小的块中, 并且每个块都有自己的地址, 常用的块设备有硬盘.

因为 RAW 镜像文件赤裸裸的特性带来了下列好处:

  • 使用 dd 指令创建一个 File 就能够模拟 RAW 镜像文件
  • 性能较 QCOW2 要更高
  • 支持裸设备的原生特性, 例如: 直接挂载
  • 能够随意转换格式, 甚至作为其他两种格式转换时的中间格式
  • 能够使用 dd 指令来追加 RAW 镜像文件的空间

相对的, RAW 镜像文件也具有一个非常大的缺陷, 就是不支持快照. 所以才有了后来 QCOW 和 QCOW2 的发展.

QCOW2 (QEMU-COW 2)

(摘自官方文档)QEMU copy-on-write format with a range of special features, including the ability to take multiple snapshots, smaller images on filesystems that don’t support sparse files, optional AES encryption, and optional zlib compression
QEMU-COW 镜像文件具有一系列特性, 支持包括 多重快照(能够创建基于之前镜像的新镜像, 速度更快), 占用更小的存储空间(不支持稀疏特性, 不会预先分配指定 Size 的存储空间), 可选的 AES 加密方式, 可选的 zlib 压缩方式 等功能.

QCOW2 镜像格式是 KVM-QEMU 支持的磁盘镜像格式之一, 其表现形式为在一个系统文件中模拟一个具有一定 Size 的块设备.

QCOW2 Header

每个 QCOW2 镜像文件都会以一个格式固定的 Header 开始.

  typedef struct QCowHeader {
      uint32_t magic;
      uint32_t version;
      # Version number 版本号 (valid values are 2 and 3)

      uint64_t backing_file_offset;
      # backing_file_offset: 表示 backing file 文件绝对路径的字符串相对于 QCOW2 镜像文件起始位置的偏移量  

      uint32_t backing_file_size;
      # 因为上述的 backing file 文件绝对路径的字符串不是以'\0'结束的
      # 所以需要通过 backing_file_size 来指出该字符串的长度
      # 如果当前 Header 的镜像是一个 COW 镜像, 则存在 backing file 文件, 否则没有

      uint32_t cluster_bits;
      # cluster_bits: cluster 的位数, 表示 cluster 的大小
      # 1 << cluster_bits (1 向左移 cluster_bits 位得到的就是 cluster 的大小)
      # 一般是 512 byte <= cluster_bits <= 2 MB

      uint64_t size; /* in bytes */
      # size: 镜像文件以块设备呈现时的 Size(byte)

      uint32_t crypt_method;
      # crypt_method: 1 表示开启采用了 AES 加密;0 表示没有加密

      uint32_t l1_size;
      # L1 table(1 级索引) 可用的 8 字节项个数

      uint64_t l1_table_offset;
      # L1 table 相对于镜像文件在存储中起始位置的偏移量, 需要与 cluster 对齐

      uint64_t refcount_table_offset;
      # refcount table(引用计数表) 相对于镜像文件在存储中起始位置的偏移量, 需要与 cluster 对齐

      uint32_t refcount_table_clusters;
      # refcount table 占用多少个 cluster

      uint32_t nb_snapshots;
      # 镜像文件中所包含的快照数量

      uint64_t snapshots_offset;
      # snapshot table 相对于镜像文件在存储中起始位置的偏移量, 需要与 cluster 对齐

  } QCowHeader;

NOTE 1: 上述所有的偏移量数值, 都是为了帮助 QCOW2 镜像文件定位相应的 metadata table.
NOTE 2: QCOW2 镜像文件格式的块设备数据都被储存在一个个 cluster 中, 而 QCOW2 Header 也是保存在一个 cluster 中
NOTE 3: L1 和 L2 tables 结合使用能够实现将磁盘镜像地址映射到镜像文件偏移
NOTE 4: 每一个 cluster 都有一个引用计数值, 当引用计数值为 0 时, 该 cluster 能够被删除

QCOW2 的 COW 特性

一个 QCOW2 镜像能够用于保存其它 QCOW2 镜像(模板镜像)的变化, 这样是为了能够保证原有镜像的内容不被修改, 这就是所谓的增量镜像. 增量镜像看着就像是一个独立的镜像文件, 其所有数据都是从模板镜像获取的. 仅当增量镜像中 clusters 的内容与模板镜像对应的 clusters 不一样时, 这些 clusters 才会被保存到增量镜像中.

当要从增量镜像中读取一个 cluster 时, QEMU 会先检查这个 cluster 在增量镜像中有没有被分配新的数据(被改变了). 如果没有, 则会去读模板镜像中的对应位置.

QCOW2 的快照

从原理的层面上来说, 一个增量镜像可以近似的当作一个快照, 因为增量镜像相对于模板镜像而言, 就是模板镜像的一个快照. 可以通过创建多个增量镜像来实现创建多个模板镜像的快照, 每一个快照(增量镜像)都引用同一个模板镜像. 需要注意的是, 因为模板镜像不能够修改, 所以必须保持为 read only, 而增量镜像则为可读写. 但需要注意的是增量镜像并不是真正的 QCOW2 镜像快照, 因为「真快照」是存在于一个镜像文件里的.

qemu-img 的基本使用

列举一些常用的 qemu-img 指令.

  • 创建 QCOW2 镜像文件: qemu-img create
# 指定容量为 4G
fanguiju@fanguiju:~$ qemu-img create -f qcow2 test.qcow2 4G
Formatting 'test.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=65536 lazy_refcounts=off
  • 查看 QCOW2 镜像文件信息: qemu-img info
fanguiju@fanguiju:~$ qemu-img info test.qcow2
image: test.qcow2
file format: qcow2
virtual size: 4.0G (4294967296 bytes)
disk size: 196K
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false
  • 创建 QCOW2 的快照: qemu-img snapshot
fanguiju@fanguiju:~$ qemu-img snapshot -c snap1 test.qcow2

# 再次查看 QCOW2 镜像文件信息, 可以看见 Snapshot list
fanguiju@fanguiju:~$ qemu-img info test.qcow2
image: test.qcow2
file format: qcow2
virtual size: 4.0G (4294967296 bytes)
disk size: 204K
cluster_size: 65536
Snapshot list:
ID        TAG                 VM SIZE                DATE       VM CLOCK
1         snap1                     0 2017-04-07 17:14:24   00:00:00.000
Format specific information:
    compat: 1.1
    lazy refcounts: false
  • 再次创建 QCOW2 的快照2:
fanguiju@fanguiju:~$ qemu-img snapshot -c snap2 test.qcow2

fanguiju@fanguiju:~$ qemu-img info test.qcow2
image: test.qcow2
file format: qcow2
virtual size: 4.0G (4294967296 bytes)
disk size: 212K
cluster_size: 65536
Snapshot list:
ID        TAG                 VM SIZE                DATE       VM CLOCK
1         snap1                     0 2017-04-07 17:14:24   00:00:00.000
2         snap2                     0 2017-04-07 17:17:54   00:00:00.000
Format specific information:
    compat: 1.1
    lazy refcounts: false
  • 删除 QCOW2 镜像文件的快照:
fanguiju@fanguiju:~$ qemu-img snapshot -d snap1 test.qcow2
fanguiju@fanguiju:~$ qemu-img info test.qcow2
image: test.qcow2
file format: qcow2
virtual size: 4.0G (4294967296 bytes)
disk size: 208K
cluster_size: 65536
Snapshot list:
ID        TAG                 VM SIZE                DATE       VM CLOCK
2         snap2                     0 2017-04-07 17:17:54   00:00:00.000
Format specific information:
    compat: 1.1
    lazy refcounts: false
  • 恢复 QCOW2 镜像文件的快照:
fanguiju@fanguiju:~$ qemu-img snapshot -a snap2 test.qcow2
  • 创建基于 QCOW2 镜像文件的镜像
    创建一个基于镜像 1(test.qcow2) 的镜像 2(test_1.qcow2), test.qcow2 成为了 test_1.qcow2 的 backing file. 对 test_1.qcow2 所作的 I/O 操作都不会影响到 test.qcow2. test.qcow2 仍能够作为其他镜像的 backing file. 前提是 test.qcow2 不被修改.
    NOTE: 如果作为 backing file 的镜像文件被修改了, 那么会影响到所有基于它的镜像文件.
fanguiju@fanguiju:~$ qemu-img create -b test.qcow2 -f qcow2 test_1.qcow2
Formatting 'test_1.qcow2', fmt=qcow2 size=4294967296 backing_file='test.qcow2' encryption=off cluster_size=65536 lazy_refcounts=off

# 可以看出镜像 test_1.qcow2 的 backing file 是 test.qcow2
fanguiju@fanguiju:~$ qemu-img info test_1.qcow2
image: test_1.qcow2
file format: qcow2
virtual size: 4.0G (4294967296 bytes)
disk size: 196K
cluster_size: 65536
backing file: test.qcow2
Format specific information:
    compat: 1.1
    lazy refcounts: false
  • * 让 QCOW2 镜像文件脱离 backing file*: qemu-img convert
    convert 用于转换镜像文件的格式, 当源镜像和目的镜像的格式均为 qcow2 时, 就相当于将源镜像的当前状态复制到目标镜像.
    同时也因为被转换出来的目的镜像不会包含任何源镜像的快照, 所以目的镜像能够摆脱 backing file.
# 将 test_1.qcow2 的状态复制到 test_1-merge.qcow2
fanguiju@fanguiju:~$ qemu-img convert -p -f qcow2 test_1.qcow2 -O qcow2 test_1-merge.qcow2
    (100.00/100%)

fanguiju@fanguiju:~$ qemu-img info test_1.qcow2
image: test_1.qcow2
file format: qcow2
virtual size: 4.0G (4294967296 bytes)
disk size: 196K
cluster_size: 65536
backing file: test.qcow2
Format specific information:
    compat: 1.1

fanguiju@fanguiju:~$ qemu-img info test_1-merge.qcow2
image: test_1-merge.qcow2
file format: qcow2
virtual size: 4.0G (4294967296 bytes)
disk size: 196K
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false
  • 更改 QCOW2 镜像文件的 backing file
fanguiju@fanguiju:~$ qemu-img create -f qcow2 base.qcow2 1G
Formatting 'base.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off

fanguiju@fanguiju:~$ qemu-img info test_1.qcow2
image: test_1.qcow2
file format: qcow2
virtual size: 4.0G (4294967296 bytes)
disk size: 196K
cluster_size: 65536
backing file: test.qcow2
Format specific information:
    compat: 1.1
    lazy refcounts: false

fanguiju@fanguiju:~$ qemu-img rebase test_1.qcow2 -b base.qcow2

fanguiju@fanguiju:~$ qemu-img info test_1.qcow2
image: test_1.qcow2
file format: qcow2
virtual size: 4.0G (4294967296 bytes)
disk size: 196K
cluster_size: 65536
backing file: base.qcow2
Format specific information:
    compat: 1.1
    lazy refcounts: false
  • QCOW2 镜像文件转换成 RAW 格式:
fanguiju@fanguiju:~$ qemu-img convert test.qcow2 -O raw test.img

RAW 与 QCOW2 的区别

两者的区别之一就是是否具有稀疏(Sparse File)特性. (关于 Sparse File 和 holes 的详细介绍, 请查阅扩展阅读.)

RAW 支持 Sparse File, 其内部块中含有若干的 holes. 这些 holes 会被 HostOS Filesystems 管理. 如果我们创建了一个 RAW(20G) 镜像文件, 使用 ls 指令查看该文件大小为 20G, 但如果使用 du 指令来查看其大小时就会变得很小, 这是因为 RAW(20G) 文件中存在若干的 holes.
EXAMPLE:

$> qemu-img info rhel6_0.img
image: rhel6_0.img
file format: raw
virtual size: 20G (21474836480 bytes)
disk size: 1.0G

$> ls -lh rhel6_0.img
-rw-r--r-- 1 root root 20G Apr  7 23:15 rhel6_0.img

$> du -h rhel6_0.img
1.1G    rhel6_0.img

相对的, 如果创建一个同为 20G 的 QCOW2 镜像文件, 无论是使用 ls 还是 du 指令查看到的文件 Size 都应该是一致的. 这说明 QCOW2 镜像文件除了含有作为一个块设备所需要的数据信息之外, 其自身还包含了内部块分配信息的记录.
EXAMPLE:

$> qemu-img info rhel6_0
image: rhel6_0
file format: qcow2
virtual size: 20G (21474836480 bytes)
disk size: 1.0G
cluster_size: 262144
Format specific information:
    compat: 1.1
    lazy refcounts: false

$> ls -lh rhel6_0
-rw-r--r-- 1 root root 1.1G Apr  6 19:26 rhel6_0

$> du -h rhel6_0
1.1G    rhel6_0

需要注意的是: 虽然 Sparse File 特性会导致镜像文件的内部块中存在 holes, 但实际上 holes 是不会占用存储空间的, 无论是 RAW(Support Sparse File) 还是 QCOW2(Don’t Support Sparse Files), 两者的磁盘利用率相等, 因为物理硬盘的块数量是固定的, 不会受到 holes 的影响. 虽说 holes 不会影响最终的磁盘使用率, 不过 holes 能够引起某些应用进程的「误解」. 例如: 上面已经举例的 ls 指令, 除此之外, 在 scp RAW 镜像文件时, 会消耗更大的网络 I/O. 同样的, tar RAW 镜像文件时也会消耗更长的时间和 CPU. 这也算是 RAW 的一大缺点了, 一般的解决方法就是将 RAW 转换为 QCOW2 之后再进行压缩或传输.

当然, Sparse File 也是具有其优势的:
The advantage of sparse files is that storage is only allocated when actually needed: disk space is saved, and large files can be created even if there is insufficient free space on the file system.
Sparse FIle 的优势在于: 存储只有在实际需要时, 空间才会被分配. 存储的实际空间被保留了起来, 所以即使在文件系统上显示以及没有足够的可用空间时, 仍然可以创建大文件.

除了 Sparse File 特性的区别之外, 使用 RAW 启动的虚拟机会比 QCOW2 启动的虚拟机 I/O 效率更高一些(25%), 所以如果追求性能的话建议选用 RAW 格式.

时间: 2024-10-27 18:38:00

QCOW2/RAW/qemu-img 概念浅析的相关文章

浅析linux中snapshots, blockcommit,blockpull

基础知识 一个虚拟机快照可被看作是虚拟机的在某个指定时间的视图(包括他的操作系统和所有的程序). 据此,某可以还原到一个之前的完整的状态,或者在guest运行的时候做个备份.所以,在我们 继续深入之前我们必须搞懂两个名词:backing files和overlays . QCOW2 backing files 与 overlays qcow2(qemu copy-on-write)具有创建一个base-image,以及在base-image(即backing file) 的基础上创建多个copy

KVM学习及应用的七个阶段

本文转载自 "xiaoli110的博客" 博客 http://xiaoli110.blog.51cto.com/1724/1561107 KVM虚拟化的学习,也可以分为七个阶段,经过七个阶段的学习,就在生产环境中完成虚拟化任务. 第一阶段 虚拟机管理学习 1 了解虚拟化的历史及概念,Xen VMWare HyperV KVM特性了解: 2 分别通过virt-manager及virt-install创建一台虚拟机: 3 了解libvirt xml文件,尤其是CPU 内存 网络 磁盘 VN

OpenStack一款由许多行业领袖共同开源的技术项目

本文将概述 OpenStack.您还不熟悉 OpenStack?OpenStack 是由许多行业领袖共同发起的一系列开源技术项目(参阅 参考资料).它提供了一个操作平台,可以大规模地协调云.它的技术与虚拟机管理程序无关,并且提供了可以在标准硬件上配置虚拟机 (VM) 的软件.此外,它还提供了一个分布式对象存储和广泛的可选功能,包括网络控制器.身份验证管理器.管理仪表板和块存储. 由 Rackspace Cloud 和 National Aeronautics and Space Administ

KVM/QEMU/qemu-kvm/libvirt 概念全解

目录 目录 前言 KVM QEMU KVM 与 QEMU qemu-kvm Libvirt Libvirt 在 OpenStack 中的应用 前言 如果是刚开始接触虚拟机技术的话, 对上述的概念肯定会有所混淆, 傻傻的分不清. 尤其在看虚拟化技术文档时导致理解能力下降, 所以在开始学习虚拟化技术之前对这些概念有一个整体的认识和清晰的理解, 就显得很有必要了. KVM KVM(Kernel-basedVirtual Machine 基于内核的虚拟机), 狭义 KVM 指的是一个嵌入到 Linux

浅析ERP项目监理的基本概念及实施要点

浅析ERP项目监理(上) 一. 监理的必要性 (一 )监理是信息产业价值链进一步分工的产物 在信息产业价值链上有三层,第一层是软件商,他们主要的任务是开发软件;第二层是实施队伍,他们以实施顾问的身份出现,;第三层是咨询公司,提供信息化战略咨询,他们针对企业信息化过程中的http://www.aliyun.com/zixun/aggregation/6377.html">流程再造.组织变革.管理变革为企业提供信息咨询.但目前,国内并没有形成明显的三层结构:即做软件的做软件,做实施的做实施,做

浅析Ruby中的类对象的概念

  这篇文章主要介绍了Ruby中的类对象的概念,是Ruby学习当中的基础知识,需要的朋友可以参考下 面向对象的程序涉及类和对象. 一个类是蓝本,从个别对象被创建.在面向对象的术语,我们说小明的自行车是被称为自行车类的对象实例. 任何车辆的例子.它包括轮子,马力,燃油或燃气罐容量.这些特点形成的类车辆的数据成员.可以从其他车辆区分这些特征. 车辆也有一定的功能,如停止,驾驶,超速驾驶.即使这些功能形成的类车辆的数据成员.因此,可以定义一个类作为一个组合的特点和功能. 车辆类可以被定义为: ? 1

领域驱动设计系列(2)浅析VO、DTO、DO、PO的概念、区别和用处

转自:http://kb.cnblogs.com/page/522348/ 上一篇文章作为一个引子,说明了领域驱动设计的优势,从本篇文章开始,笔者将会结合自己的实际经验,谈及领域驱动设计的应用.本篇文章主要讨论一下我们经常会用到的一些对象:VO.DTO.DO和PO. 由于不同的项目和开发人员有不同的命名习惯,这里我首先对上述的概念进行一个简单描述,名字只是个标识,我们重点关注其概念: 概念: VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起

Java编码浅析(注意区分三个概念)(转)

编码: (1)外部资源的字符集-----没有读入jvm中的数据都是外部资源 (2)jvm中数据的字符集-----都是unicode (1)和(2)之间发生交互时,如果不指定编码,则使用JVM平台默认字符集     Java与Unicode:   Java的class文件采用utf8的编码方式,JVM运行时采用utf16.   Java的字符串是unicode编码的.   总之,Java采用了unicode字符集,使之易于国际化.   Java支持哪些字符集:   即Java能识别哪些字符集并对它

java入门概念个人理解之package与import浅析_java

由于近来学习java,遇到了一些在c++上没有的概念,将它记录下,以自己复习使用,如有不理解妥之处,望大家批评指导.资料均由网上经过自己整合理解而来,如有侵权请通知我将起删除即可. 我就以package与import开始吧. package的作用其实就是c++的namespace的作用,防止名字相同的类产生冲突,只是实现的机制不一样,java编译器在编译时,直接根据package 指定的信息直接将生成的class文件生成到对应目录下.如package aaa.bbb.ccc 编译器就将该.jav