rbd对象探究

rbd对象探究

1. rbd镜像的创建与使用

为了更直观的感受rbd对象,本文从创建rbd池开始,构建了一个模拟的rbd使用环境,并以此探究rbd的对象。

首先是rbd池的创建与使用:

服务端:

1.创建rbd池

[root@node-1 ~]# ceph osd pool create rbd-pool 64 64 && rbd pool init rbd-pool

2.创建块设备镜像

[root@node-1 ~]# rbd create --size 1024 rbd-pool/rbd-pool-image-1

3.拷贝密钥文件,或者创建新用户,这里直接拷贝admin密钥及配置

[root@node-1 ~]# scp –r /etc/ceph 192.168.159.132:/etc/

客户端:

1.注意更新ceph yum源

2.安装ceph-common

[[email protected] ~]# yum install ceph-common –y

3.挂载块设备镜像

[[email protected] ~]# rbd map rbd-pool/rbd-pool-image-1

4.格式化,仅第一次挂载需要,块设备名称注意更改

[[email protected] ~]# mkfs.xfs /rbd /dev/rbd0

5.挂载到目录

[[email protected] ~]# mkdir /mnt/rbd0 && mount /dev/rbd0 /mnt/rbd0

6.卸载

[[email protected] ~]# umount /mnt/rbd0 && rbd unmap rbd-pool/rbd-pool-image-1

注意:在rbd map时可能会报错,因为内核特性不支持。

rbd: sysfs write failed

RBD image feature set mismatch. You can disable features unsupported by the kernel with "rbd feature disable rbd-pool/rbd-pool-image-1 object-map fast-diff deep-flatten".

In some cases useful info is found in syslog - try "dmesg | tail".

rbd: map failed: (6) No such device or address

这里根据提示关闭某些特性即可。

2. 当我们创建镜像时,创建了什么?

[root@node-1 ~]# rados -p rbd-pool ls

rbd_object_map.20cc292949764 # rbd特性信息

rbd_header.20cc292949764 #image元数据

rbd_directory # 记录该rbd池中含有的image_nameid

rbd_info # rbd信息

rbd_id.rbd-pool-image-1 #此镜像的id

通过以上命令及其结果可以看出,相关含义在《Ceph设计原理与实现》一书中有详细介绍,当我们创建完镜像后,rbd-pool中多了几个对象。其含义可在src/include/rbd_types.h文档中查看。

/* New-style rbd image 'foo' consists of objects

  • rbd_id.foo - id of image

  • rbd_header. - image metadata

  • rbd_object_map. - optional image object map

  • rbd_data..00000000

  • rbd_data..00000001

  • ... - data

*/

目前rbd镜像中还没有文件,因此大部分对象是空的。通过“rados -p rbd-pool get ”命令可以导出对象。

经过查看,发现rbd_id.rbd-pool-image-1保存了镜像的id:20cc292949764。

rbd_info中保存了:overwrite validated。

rbd_object_map.20cc292949764中保存了:

{

"size": 256,

"bit_table": [

"0x00",

"0x00",

}//用于支持 object-map特性,具体作用在实践中遇到再来补充。

这里给出查看rbd_object_map命令: ceph-dencoder import ./rbd_object_map.20cc292949764 type BitVector<2> decode dump_json。

3. 向rbd写入一个文件后,实际写入的是什么?

在mkfs块设备后,我们查看下rbd-pool中的对象。

[root@node-1 data]# rados -p rbd-pool ls

rbd_data.20e5ff0224ec0.00000000000000e0 #image对象信息

rbd_directory #rbd管理image对象信息

rbd_header.20e5ff0224ec0 #image元数据

rbd_data.20e5ff0224ec0.0000000000000060 #

rbd_info #rbd信息

rbd_data.20e5ff0224ec0.0000000000000001

rbd_data.20e5ff0224ec0.00000000000000ff

rbd_data.20e5ff0224ec0.0000000000000080

rbd_id.rbd-pool-image-1 #记录image_nameimage_id的映射关系

rbd_data.20e5ff0224ec0.00000000000000c0

rbd_data.20e5ff0224ec0.0000000000000082

rbd_data.20e5ff0224ec0.0000000000000020

rbd_data.20e5ff0224ec0.0000000000000040

rbd_data.20e5ff0224ec0.0000000000000081

rbd_data.20e5ff0224ec0.0000000000000000

rbd_data.20e5ff0224ec0.00000000000000a0

发现增加了12个rbd_data对象。rbd被xfs格式化以后会产生一些对象,这些对象是以16进制名称的方式存储在后台的,也就是rbd大小一定的情况下对象数目是一定的,也就是名称也是一定的。在后续的向文件中写入操作的过程中,还会发现,对象依然是从rbd_data.*****00的对象开始写入。这个实际和客户端格式化的文件系统有关。在《从ceph对象中提取rbd中的指定文件》一文中可以得知:rbd存储对象和文件系统的sectors是一一对应的。

客户端查看分区设备信息:

[root@localhost ~]# parted -s /dev/rbd0 unit s print

Model: 未知 (unknown)

Disk /dev/rbd0: 2097152s

Sector size (logical/physical): 512B/512B

Partition Table: loop

Disk Flags:

Number Start End Size File system 标志

  • 1 0s 2097151s 2097152s xfs*

上面结果中“Start”对应的“0s”表示该分区设备从第0块sector开始写入,每块sector大小512B,共有2097152s 块。

服务端查看镜像信息:

[root@node-1 ~]# rbd info rbd-pool/rbd-pool-image-1

rbd image 'rbd-pool-image-1':

size 1 GiB in 256 objects #大小1GB,平均分配给256个对象

order 22 (4 MiB objects) # 每个对象大小4MB

snapshot_count: 0

id: 20e5ff0224ec0

block_name_prefix: rbd_data.20e5ff0224ec0

format: 2 # image 1 基本上不用

features: layering, exclusive-lock

op_features: # image支持的特性

flags:

create_timestamp: Wed May 26 16:42:36 2021

access_timestamp: Wed May 26 16:42:36 2021

modify_timestamp: Wed May 26 16:42:36 2021

上述结果可知镜像对应的块设备大小1GB,平均分配到256个对象,每个4MB。

简单计算可以得出:sector数量 * 单个sector大小 = 镜像大小

2097152 * 512 / 1024 / 1024 = 1024 MB = 1GB。

因此2097152个sector和image中的256个对象存在对应关系。已知sector从0块开始写入,那么obj应该也从0开始增长,写满4MB后,换到新的obj。

我在这里使用dd命令在客户端写入一个4MB对象,然后再去查看pool中对象信息。

这里我们在客户端上挂载镜像后,向该目录中写入一个无意义对象。

[root@localhost mnt]# dd if=/dev/zero of=/mnt/rbd0/file1 count=1 bs=4MB

然后,观察rbd-pool对象情况。

[root@node-1 ~]# rados -p rbd-pool ls

rbd_data.20e5ff0224ec0.00000000000000e0

rbd_directory

rbd_header.20e5ff0224ec0

rbd_data.20e5ff0224ec0.0000000000000060

rbd_info

rbd_data.20e5ff0224ec0.0000000000000001

rbd_data.20e5ff0224ec0.00000000000000ff

rbd_data.20e5ff0224ec0.0000000000000080

rbd_id.rbd-pool-image-1

rbd_data.20e5ff0224ec0.00000000000000c0

rbd_data.20e5ff0224ec0.0000000000000082

rbd_data.20e5ff0224ec0.0000000000000020

rbd_data.20e5ff0224ec0.0000000000000040

rbd_data.20e5ff0224ec0.0000000000000081

rbd_data.20e5ff0224ec0.0000000000000000

rbd_data.20e5ff0224ec0.00000000000000a0

似乎没有变化,但其实rbd_data.******00对象的大小增加了,先按下不表,我们看下此时rbd_data.******00对象的大小。

[root@node-1 ~]# rados -p rbd-pool stat rbd_data.20e5ff0224ec0.0000000000000000

rbd-pool/rbd_data.20e5ff0224ec0.0000000000000000 mtime 2021-05-26 18:22:26.000000, size 4034560

经查询,rbd_data.******00对象大小为4034560B。

我们再向客户端挂载的文件目录中写入一个有意义的小对象。

[root@localhost rbd0]# vi hellorbd

hello rbd

然后,查看hellorbd文件在块设备中的位置,顺便也可以看下file1的位置。

[root@localhost rbd0]# xfs_bmap -lvp /mnt/rbd0/hellorbd

/mnt/rbd0/hellorbd:

  • EXT: FILE-OFFSET BLOCK-RANGE AG AG-OFFSET TOTAL FLAGS*

0: [0..7]: 7880..7887 0 (7880..7887) 8 01111

[root@localhost rbd0]# xfs_bmap -lvp /mnt/rbd0/file1

/mnt/rbd0/file1:

  • EXT: FILE-OFFSET BLOCK-RANGE AG AG-OFFSET TOTAL FLAGS*

0: [0..7815]: 64..7879 0 (64..7879) 7816 01111

可以看出hellorbd在sector中分布在[7880~7887],file1为[64~7879]。hellorbd紧跟着file1,并且file1并非从0开始,而是从64开始,说明前面的sector已经被使用,这段64个sector(即 64 * 512 B)长度空间在格式化文件系统的时候已经被占用了。还有一点值得吐槽的是:dd命令中的4MB,实际写入大小只有4000000B。

根据hellorbd的位置信息,可以计算出它存储在在rbd-pool/rbd-pool-image-1中的对象的具体位置。

计算方法:

1.计算出hellorbd到rbd-pool对象的映射

sectors数量 / 对象数量 = 单个对象的sectors范围

2097152/256 = 8192

根据 hellorbd:[7880~7887],可以得出hellorbd在第0个对象中:rbd_data.******00。

2.计算出hellorbd在rbd_data对象中偏移量

(7880 - (0 * 8192))* 512B = 4030560

4034560!还记得我们上文中在写入file1之后,查看过rbd_data.******00对象的大小吗?就是4034560。

接下来使用rados命令和dd命令在服务端还原出rbdhello。

[root@node-1 ~]# rados -p rbd-pool get rbd_data.20e5ff0224ec0.0000000000000000 ./rbd_data.20e5ff0224ec0.0000000000000000

[root@node-1 ~]# dd if=rbd_data.20e5ff0224ec0.0000000000000000 of=hellorbd bs=512 count=8 skip=7880

  • [root@node-1 ~]# cat hellorbd*

hello rbd

或者,

[root@node-1 ~]# dd if=rbd_data.20e5ff0224ec0.0000000000000000 of=hellorbd-1 bs=1 count=4096 skip=4034560

[root@node-1 ~]# cat hellorbd-1

hello rbd

可以得出,块设备在rbd中被切割成一个个对象,保存在rbd_data对象中,这样使得rbd管理起块设备的数据极为方便,而且也达到到了瘦分配的特性。rbd_data中还保存着客户端中这个设备的信息(文件系统,大小等),这个客户端在挂载时,可以直接把image映射为一个块设备,其所有读写操作的本质都是rbd_data。

你可能感兴趣的:(rbd对象探究)