QCOW2/RAW/qemu-img 概念浅析
目录
扩展阅读
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 格式.
QCOW2/RAW/qemu-img 概念浅析的更多相关文章
- iOS 并发概念浅析
在进行iOS开发过程中,我们常会遇到网络请求.复杂计算.数据存取等比较耗时的操作,如果处理不合理,将对APP的流畅度产生较大影响.除了优化APP架构,并发(concurrency)是一个常用且较好的解 ...
- KVM+QEMU虚拟化概念
概念: KVM,即Kernel-basedvirtual machine,由redhat开发,是一种开源.免费的虚拟化技术.对企业来说,是一种可选的虚拟化解决方案. 定义:基于Linux内核的虚拟机 ...
- 虚拟机镜像压缩(qcow2,raw)
●qcow2 格式的压缩首先,需要对虚拟机系统的剩余空间写零操作: $ dd if=/dev/zero of=/zero.dat 删除 zero.dat$ rm /zero.dat关闭虚拟机,进入虚拟 ...
- 僵尸网络(botnet)概念浅析
僵尸程序 僵尸程序是用于构建僵尸网络以形成大规模攻击平台的恶意代码.僵尸网络是被黑客集中控制的计算机群,其核心特点是黑客能够通过一对多的命令与控制信道操纵感染僵尸程序的主机执行相同的恶意行为,如可同时 ...
- 网络地址转换NAT的两种模式(概念浅析)& IP溯源
由于全球IPv4地址越来越少.越来越贵,因此大到一个组织,小到一个家庭一个人都很难获得公网IP地址,所以只能使用内网地址,从而和别人共享一个公网IP地址.在这种情况下,NAT技术诞生. 翻译 NAT( ...
- qcow2 raw vhd 虚拟磁盘转换
Centos-6.4-x86_64_Ruiy.vhd: Microsoft Disk Image, Virtual Server or Virtual PC
- 【网络安全】IOC概念浅析
OpenIOC(Open Indicator of Compromise,开放威胁指标) MANDIANT 公司发布的情报共享规范,是开源.灵活的框架.OpenIOC是一个记录.定义以及共享威胁情报的 ...
- QEMU 使用的镜像文件:qcow2 与 raw
qcow2 的基本原理 qcow2 镜像格式是 QEMU 模拟器支持的一种磁盘镜像.它也是可以用一个文件的形式来表示一块固定大小的块设备磁盘.与普通的 raw 格式的镜像相比,有以下特性: 更小的空间 ...
- (转)QEMU 使用的镜像文件:qcow2 与 raw
原文:https://www.ibm.com/developerworks/cn/linux/1409_qiaoly_qemuimgages/ qcow2 的基本原理 qcow2 镜像格式是 QEMU ...
随机推荐
- Prometheus 2.14.0 新特性
Prometheus 2.14.0 现在(2019.11.11)已经发布,在上个月的 2.13.0 之后又进行了一些修正和改进. 这次最大的新功能是基于 React 的新 UI,与现有 UI 大体相同 ...
- ln -在文件之间建立连接
总览 ln [options] source [dest] ln [options] source...directory POSIX 选项: [-f] GNU 选项(缩写): [-bdfinsvF] ...
- 常用技术blog
淘宝核心系统团队 http://csrd.aliapp.com/ 淘宝搜索技术博客 http://www.searchtb.com 淘宝量子恒道官方博客 http://blog.linezing.co ...
- c/c++基础篇之数据类型转换
C/C++常见的数据类型转换 1. 常见的单类基本类型转换 (1)强制类型转换 如: int a=(int)(9.87) 结果a=9 char c=(char)(97) 结果为c=’a’ ...
- 一、.net Core bundleconfig.json
一.bundleconfig.json [ { "outputFileName": "wwwroot/css/site.min.css", "inpu ...
- Myabtis中批量更新update多字段
在mybatis中批量更新多个字段 推荐使用如下操作: 方式1:在Dao层接口中: void updateBatch(@Param("list")List<Student&g ...
- PAT Advanced 1042 Shuffling Machine (20 分)(知识点:利用sstream进行转换int和string)
Shuffling is a procedure used to randomize a deck of playing cards. Because standard shuffling techn ...
- L3-015. 球队“食物链”
某国的足球联赛中有N支参赛球队,编号从1至N.联赛采用主客场双循环赛制,参赛球队两两之间在双方主场各赛一场. 联赛战罢,结果已经尘埃落定.此时,联赛主席突发奇想,希望从中找出一条包含所有球队的“食物链 ...
- php内置函数分析之array_sum()
PHP_FUNCTION(array_sum) { zval *input, *entry, entry_n; if (zend_parse_parameters(ZEND_NUM_ARGS(), & ...
- 简单后台登录逻辑实现Controller
package com.fei.controller.admin; import javax.servlet.http.HttpSession; import org.springframework. ...