Akemi

RBD镜像快照与克隆--COW/COR

2025/07/08

RBD镜像格式2的镜像可以支持几个可选的特性

其中layering特性是RBD镜像的核心特性

1
2
rbd feature enable <pool-name>/<rbd-name> layering
rbd feature disable <pool-name>/<rbd-name> layering

镜像快照snap

先说如果没有快照的情况下,数据对RBD的读写会直接写入磁盘

首先快照是什么

与虚拟机不同,RBD的快照在初始状态下是一个和原镜像同样结构的空镜像

COW写时复制/COR读时复制

写入数据

首先snap是只读的,写入是对RBD进行写入

snap在初始状态下,如果有数据进行写入,就会触发COW写时复制

1.原始数据被放到新存储块下的block_new
2.新数据替换掉原始数据的位置block_old
3.snap将已修改的数据块位置,关联到block_new
4.RDB将修改过的block_old位置标记为不受snap保护的位置

此时这个snap其实增长了新数据占用的那一点点空间

非初始状态下

如果有数据进行写入,且写入位置为block_old,那么不受snap保护,不会触发COW,新数据就会直接写入到RBD中

读取数据

snap初始状态下,读取到的是RBD的内容,因为全部都受snap保护

非初始状态下,会读取所有受保护数据块对应位置的RBD的内容,同时读取所有不受保护的数据块的snap的数据

根据上面说的写入数据的机制,可以知道snap将这些数据块元数据已经做了修改,将其指向block_new的位置

镜像克隆

RBD 克隆扁平化(Flattening) 是指将基于快照创建的克隆镜像与其父快照之间的依赖关系断开,使克隆镜像成为一个完全独立的镜像的过程。当执行扁平化操作时,系统会将所有从父快照继承的数据块复制到克隆镜像中,从而消除对原始快照的依赖。

根据上面说的COW的读取数据,镜像克隆其实就是读数据最后读成一个完整镜像的过程,最后克隆出来的结果就是一个RBD镜像

RBD快照操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
在创建快照前,需要先冻结文件系统
MOUNT_POINT="/mnt/rbd"
fsfreeze --freeze ${MOUNT_POINT}

解冻文件系统
fsfreeze --unfreeze ${MOUNT_POINT}

# 1. 创建快照
# 语法:rbd snap create <pool-name>/<image-name>@<snap-name>
rbd snap create mypool/myimage@mysnap_20230901 # 为镜像 myimage 创建名为 mysnap_20230901 的快照

# 2. 列出快照
# 语法:rbd snap ls <pool-name>/<image-name>
rbd snap ls mypool/myimage # 查看 myimage 的所有快照

# 3. 回滚到快照(覆盖当前数据)
# 语法:rbd snap rollback <pool-name>/<image-name>@<snap-name>
rbd snap rollback mypool/myimage@mysnap_20230901 # 将镜像回滚到指定快照状态
# 注意:回滚需要先卸载设备,且会覆盖当前数据!

# 4. 克隆快照(基于快照创建新镜像)
# 语法:rbd clone <pool>/<parent-image>@<snap> <pool>/<child-image>
rbd clone mypool/myimage@mysnap_20230901 mypool/cloned_image # 基于快照创建克隆镜像
# 需先启用克隆功能:rbd feature disable mypool/myimage object-map,fast-diff,deep-flatten

# 5. 扁平化克隆(断开与父快照的依赖)
# 语法:rbd flatten <pool-name>/<child-image-name>
rbd flatten mypool/cloned_image # 将克隆镜像转为独立镜像(释放父快照依赖)

# 6. 保护快照(防止被删除)
# 语法:rbd snap protect <pool-name>/<image-name>@<snap-name>
rbd snap protect mypool/myimage@mysnap_20230901 # 保护快照(克隆操作必需)

# 7. 解除快照保护
# 语法:rbd snap unprotect <pool-name>/<image-name>@<snap-name>
rbd snap unprotect mypool/myimage@mysnap_20230901 # 解除保护(删除前必需)

# 8. 删除快照
# 语法:rbd snap rm <pool-name>/<image-name>@<snap-name>
rbd snap rm mypool/myimage@mysnap_20230901 # 删除未保护的快照
# 强制删除(危险!):rbd snap purge mypool/myimage # 删除该镜像所有快照

# 9. 查看快照信息
# 语法:rbd info <pool-name>/<image-name>@<snap-name>
rbd info mypool/myimage@mysnap_20230901 # 显示快照详细信息

# 10. 差异对比
# 语法:rbd diff <pool-name>/<image-name>[@<snap-name>]
rbd diff mypool/myimage@mysnap_20230901 # 计算快照与当前镜像的差异块
rbd diff mypool/myimage --from-snap mysnap_20230901 # 对比两个快照间的差异

# ================================
# 操作流程示例:
# 创建镜像 → 创建快照 → 克隆 → 扁平化 → 清理
# ================================
# rbd create mypool/newimage --size 1024
# rbd snap create mypool/newimage@base_snap
# rbd snap protect mypool/newimage@base_snap
# rbd clone mypool/newimage@base_snap mypool/cloned_image
# rbd flatten mypool/cloned_image
# rbd snap unprotect mypool/newimage@base_snap
# rbd snap rm mypool/newimage@base_snap

CATALOG
  1. 1. 镜像快照snap
  2. 2. COW写时复制/COR读时复制
    1. 2.1. 写入数据
    2. 2.2. 读取数据
  3. 3. 镜像克隆
  4. 4. RBD快照操作