rbd块设备的id修改

背景

看到有这个需求,具体碰到什么场景了不太清楚,之前做过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
[root@lab104 ~]# rbd create testrbd --size 1T
[root@lab104 ~]# rbd info testrbd
rbd image 'testrbd':
size 1 TiB in 262144 objects
order 22 (4 MiB objects)
snapshot_count: 0
id: 5f0c22d39dda
block_name_prefix: rbd_data.5f0c22d39dda
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
op_features:
flags:
create_timestamp: Thu Apr 10 11:01:08 2025
access_timestamp: Thu Apr 10 11:01:08 2025
modify_timestamp: Thu Apr 10 11:01:08 2025
[root@lab104 ~]# rbd rm testrbd
Removing image: 100% complete...done.
[root@lab104 ~]# rbd create testrbd --size 1T
[root@lab104 ~]# rbd info testrbd
rbd image 'testrbd':
size 1 TiB in 262144 objects
order 22 (4 MiB objects)
snapshot_count: 0
id: 5f57bde3f24c
block_name_prefix: rbd_data.5f57bde3f24c
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
op_features:
flags:
create_timestamp: Thu Apr 10 11:07:17 2025
access_timestamp: Thu Apr 10 11:07:17 2025
modify_timestamp: Thu Apr 10 11:07:17 2025

这个id信息就是那个block_name_prefix里面的,可以看到,同样的名称同样的大小,重建一次,这个信息就发生了改变了,说明这个信息是随机性的,并没有固定算法,这些信息是在几个地方有记录的我们把这几个地方找出来

rbd相关的对象

1
2
3
4
rbd_id.testrbd
rbd_directory
rbd_header.5f57bde3f24c
rbd_object_map.5f57bde3f24c

这几个是元数据的对象,其它就是数据的信息,我们假如要改id名称,需要先处理元数据

1
rbd_data.5f57bde3f24c.xxxxxxxx

数据存储是这样的

1
2
3
4
5
6
7
8
9
10
[root@lab104 ~]# rados -p rbd listomapvals rbd_directory
id_5f57bde3f24c
value (11 bytes) :
00000000 07 00 00 00 74 65 73 74 72 62 64 |....testrbd|
0000000b

name_testrbd
value (16 bytes) :
00000000 0c 00 00 00 35 66 35 37 62 64 65 33 66 32 34 63 |....5f57bde3f24c|
00000010

rbd_directory通过omap老存储id和名称的对应关系

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
[root@lab104 ~]# rados -p rbd listomapvals rbd_header.5f57bde3f24c
access_timestamp
value (8 bytes) :
00000000 e5 35 f7 67 95 6f 07 08 |.5.g.o..|
00000008

create_timestamp
value (8 bytes) :
00000000 e5 35 f7 67 95 6f 07 08 |.5.g.o..|
00000008

features
value (8 bytes) :
00000000 3d 00 00 00 00 00 00 00 |=.......|
00000008

modify_timestamp
value (8 bytes) :
00000000 e5 35 f7 67 95 6f 07 08 |.5.g.o..|
00000008

object_prefix
value (25 bytes) :
00000000 15 00 00 00 72 62 64 5f 64 61 74 61 2e 35 66 35 |....rbd_data.5f5|
00000010 37 62 64 65 33 66 32 34 63 |7bde3f24c|
00000019

order
value (1 bytes) :
00000000 16 |.|
00000001

size
value (8 bytes) :
00000000 00 00 00 00 00 01 00 00 |........|
00000008

snap_seq
value (8 bytes) :
00000000 00 00 00 00 00 00 00 00 |........|
00000008

rbd_header.5f57bde3f24c 这个存储的是这个对象的rbd info看到的一些信息

1
2
3
[root@lab104 ~]# rados -p  rbd get  rbd_id.testrbd rbd_id.testrbd
[root@lab104 ~]# cat rbd_id.testrbd
5f57bde3f24c[root@lab104 ~]

rbd_id.testrbd是用实体数据存储的rbd的id信息

rbd_object_map.5f57bde3f24c这个可以忽略先,这个是支持重建的

操作实践

修改 rbd_directory 的omap信息

我们先修改 rbd_directory 的信息

存在两组关系

  • id_5f57bde3f24c 对应 |….testrbd|
  • name_testrbd 对应|….5f57bde3f24c|

这里我们任意指定一个名称,这个应该是16进制的,所以注意字母不要超过f

我们改掉中间的一部分

id_5f57bde3f24c 改成id_5f57abc3f24c

那么新的对应关系是

  • id_5f57abc3f24c 对应 |….testrbd|
  • name_testrbd 对应 |….5f57bde3f24c|

那么就是一个改val 一个改key了 ,rados没有rename key val的接口。那么只能set操作

1
echo -en \\x07\\x00\\x00\\x00\\x74\\x65\\x73\\x74\\x72\\x62\\x64 |rados -p rbd setomapval rbd_directory id_5f57abc3f24c

这个val直接取上面查询到的val即可了,这个是没变的

我们检查效果

1
2
3
4
5
6
7
8
9
10
[root@lab104 ~]# rados -p rbd listomapvals rbd_directory
id_5f57abc3f24c
value (11 bytes) :
00000000 07 00 00 00 74 65 73 74 72 62 64 |....testrbd|
0000000b

id_5f57bde3f24c
value (11 bytes) :
00000000 07 00 00 00 74 65 73 74 72 62 64 |....testrbd|
0000000b

可以看到完整的复刻了,那么我们可以删除老的key了

1
rados -p rbd rmomapkey rbd_directory id_5f57bde3f24

再修改name里面的val的信息

1
2
3
4
5
6
7
[root@lab104 ~]# rados -p rbd listomapvals rbd_directory


name_testrbd
value (16 bytes) :
00000000 0c 00 00 00 35 66 35 37 62 64 65 33 66 32 34 63 |....5f57bde3f24c|
00000010

这个里面左边的就是表示右边的内容的,这个是

1
35 66 35 37:分别是 ASCII 字符 `'5' 'f' '5' '7'

那么我们反向计算
5f57bde3f24c这个我们改成的是5f57abc3f24c
那么对应左边的值就是

1
0c 00 00 00 35 66 35 37 61 62 63 33 66 32 34 63

先删除之前的

1
rados -p rbd rmomapkey rbd_directory name_testrbd

然后设置

1
echo -en \\x0c\\x00\\x00\\x00\\x35\\x66\\x35\\x37\\x61\\x62\\x63\\x33\\x66\\x32\\x34\\x63|rados -p rbd setomapval rbd_directory name_testrbd

检查

1
2
3
4
5
6
7
8
9
10
[root@lab104 ~]# rados -p rbd listomapvals rbd_directory
id_5f57abc3f24c
value (11 bytes) :
00000000 07 00 00 00 74 65 73 74 72 62 64 |....testrbd|
0000000b

name_testrbd
value (16 bytes) :
00000000 0c 00 00 00 35 66 35 37 61 62 63 33 66 32 34 63 |....5f57abc3f24c|
00000010

可以看到已经修改好了

修改rbd_id.testrbd二进制

再改动rbd_id.testrbd信息

1
2
3
[root@lab104 ~]# hexdump -C rbd_id.testrbd
00000000 0c 00 00 00 35 66 35 37 62 64 65 33 66 32 34 63 |....5f57bde3f24c|
00000010

可以看到这是一个二进制的文件,那么我们手动编辑了

1
2
3
vim -b rbd_id.testrbd
文本转16进制编辑
:%!xxd

内容

1
0000000: 0c00 0000 3566 3537 6264 6533 6632 3463  ....5f57bde3f24c

我们改成

1
0000000: 0c00 0000 3566 3537 6162 6333 6632 3463  ....5f57abc3f24c

上面已经计算过了,直接套用即可

16进制编辑还原成文本

1
:%!xxd -r

检查

1
2
3
[root@lab104 ~]# hexdump -C rbd_id.testrbd
00000000 0c 00 00 00 35 66 35 37 61 62 63 33 66 32 34 63 |....5f57abc3f24c|
00000010

没有问题,可以把对象覆盖回去了

1
rados -p rbd put rbd_id.testrbd rbd_id.testrbd

修改rbd_header的omap信息

还剩最后一个了rbd_header.5f57bde3f24c

1
rados -p rbd cp rbd_header.5f57bde3f24c rbd_header.5f57abc3f24c

复制下对象后,检查下相关的信息是否复制过来了

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
[root@lab104 ~]# rados -p rbd listomapvals rbd_header.5f57abc3f24c
access_timestamp
value (8 bytes) :
00000000 e5 35 f7 67 95 6f 07 08 |.5.g.o..|
00000008

create_timestamp
value (8 bytes) :
00000000 e5 35 f7 67 95 6f 07 08 |.5.g.o..|
00000008

features
value (8 bytes) :
00000000 3d 00 00 00 00 00 00 00 |=.......|
00000008

modify_timestamp
value (8 bytes) :
00000000 e5 35 f7 67 95 6f 07 08 |.5.g.o..|
00000008

object_prefix
value (25 bytes) :
00000000 15 00 00 00 72 62 64 5f 64 61 74 61 2e 35 66 35 |....rbd_data.5f5|
00000010 37 62 64 65 33 66 32 34 63 |7bde3f24c|
00000019

order
value (1 bytes) :
00000000 16 |.|
00000001

size
value (8 bytes) :
00000000 00 00 00 00 00 01 00 00 |........|
00000008

snap_seq
value (8 bytes) :
00000000 00 00 00 00 00 00 00 00 |........|
00000008

这个里面只有一条信息需要修改object_prefix

1
2
3
4
5
object_prefix
value (25 bytes) :
00000000 15 00 00 00 72 62 64 5f 64 61 74 61 2e 35 66 35 |....rbd_data.5f5|
00000010 37 62 64 65 33 66 32 34 63 |7bde3f24c|
00000019

可以看到这个地方的对应关系是这样转换的,我们还是反向转换一下即可

1
rbd_data.5f57abc3f24c 对应为72 62 64 5f 64 61 74 61 2e 35 66 35 37 61 62 63 33 66 32 34 63

我们设置下

1
2
rados -p rbd rmomapkey rbd_header.5f57abc3f24c  object_prefix
echo -en \\x15\\x00\\x00\\x00\\x72\\x62\\x64\\x5f\\x64\\x61\\x74\\x61\\x2e\\x35\\x66\\x35\\x37\\x61\\x62\\x63\\x33\\x66\\x32\\x34\\x63|rados -p rbd setomapval rbd_header.5f57abc3f24c object_prefix

注意前面的\\x15\\x00\\x00\\x00前缀不要漏了

查看信息

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
[root@lab104 ~]# rados -p rbd listomapvals rbd_header.5f57abc3f24c
access_timestamp
value (8 bytes) :
00000000 e5 35 f7 67 95 6f 07 08 |.5.g.o..|
00000008

create_timestamp
value (8 bytes) :
00000000 e5 35 f7 67 95 6f 07 08 |.5.g.o..|
00000008

features
value (8 bytes) :
00000000 3d 00 00 00 00 00 00 00 |=.......|
00000008

modify_timestamp
value (8 bytes) :
00000000 e5 35 f7 67 95 6f 07 08 |.5.g.o..|
00000008

object_prefix
value (25 bytes) :
00000000 15 00 00 00 72 62 64 5f 64 61 74 61 2e 35 66 35 |....rbd_data.5f5|
00000010 37 61 62 63 33 66 32 34 63 |7abc3f24c|
00000019

可以看到已经改好了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@lab104 ~]# rbd info testrbd
rbd image 'testrbd':
size 1 TiB in 262144 objects
order 22 (4 MiB objects)
snapshot_count: 0
id: 5f57abc3f24c
block_name_prefix: rbd_data.5f57abc3f24c
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
op_features:
flags:
create_timestamp: Thu Apr 10 11:07:17 2025
access_timestamp: Thu Apr 10 11:07:17 2025
modify_timestamp: Thu Apr 10 11:07:17 2025

可以看到已经可以查询到信息了,并且prefix已经改好了,我们还需要处理数据

1
rados -p rbd ls|grep rbd_data.5f57bde3f24c > obj.list

我们需要把这些对象全部复制一份

1
for obj in `cat obj.list`;do target=`echo $obj|sed 's/\(rbd_data\.\)[^.]*\(\..*\)/\15f57abc3f24c\2/'`;echo $obj;echo $target;rados  -p rbd cp $obj $target   ;done

这个就是把数据改掉prefix后全部复制了一遍

1
[root@lab104 ~]# for obj in `cat obj.list`;do rados  -p rbd rm  $obj ;done

确认没问题就可以删掉了

1
2
[root@lab104 ~]# rados -p rbd ls|grep rbd_objec
rbd_object_map.5f57bde3f24c

重建object-map

1
2
3
4
5
6
7
8
9
10
11
[root@lab104 ~]# rbd  object-map rebuild testrbd
2025-04-10T12:11:16.762+0800 7f601b7fe700 -1 librbd::object_map::RefreshRequest: failed to load object map: rbd_object_map.5f57abc3f24c
2025-04-10T12:11:16.773+0800 7f601b7fe700 -1 librbd::object_map::InvalidateRequest: 0x7f600c00c560 invalidating object map in-memory
2025-04-10T12:11:16.773+0800 7f601b7fe700 -1 librbd::object_map::InvalidateRequest: 0x7f600c00c560 invalidating object map on-disk
2025-04-10T12:11:16.774+0800 7f601b7fe700 -1 librbd::object_map::InvalidateRequest: 0x7f600c00c560 should_complete: r=0
Object Map Rebuild: 100% complete...done.
[root@lab104 ~]# rados -p rbd ls|grep rbd_objec
rbd_object_map.5f57abc3f24c
rbd_object_map.5f57bde3f24c

[root@lab104 ~]# rados -p rbd rm rbd_object_map.5f57bde3f24c

老的可以清理了

数据访问确认

到这里工作就都完成了,我们需要去确认下我们的数据是不是完整的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@lab103 ~]# rbd ls
testrbd
zp
[root@lab103 ~]# rbd map testrbd
/dev/rbd0
[root@lab103 ~]# mount /dev/rbd0 /mnt
[root@lab103 ~]# rbd info testrbd
rbd image 'testrbd':
size 1 TiB in 262144 objects
order 22 (4 MiB objects)
snapshot_count: 0
id: 5f57abc3f24c
block_name_prefix: rbd_data.5f57abc3f24c
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
op_features:
flags:
create_timestamp: Thu Apr 10 11:07:17 2025
access_timestamp: Thu Apr 10 11:07:17 2025
modify_timestamp: Thu Apr 10 11:07:17 2025
[root@lab103 ~]# df -h /mnt
Filesystem Size Used Avail Use% Mounted on
/dev/rbd0 1.0T 7.2G 1017G 1% /mnt

可以看到可以挂载,文件系统还在

总结

通过上面的一系列的操作,我们可以看到这个id是可以更改的,这个地方对元数据的控制能够让我们在面对极端故障的时候能够更好的挽回数据,比如元数据对象丢失,就需要我们去重构下这个数据了,以上操作是操作的一个比较原始使用场景的rbd,没有做快照,没有克隆,如果有用到,需要对更多信息进行修改
大致上说就是该两部分数据:

  • 通过echo修改omap的数据
  • 通过vim编辑二进制对象的数据

rbd块设备的id修改
https://zphj1987.com/2025/04/10/rbd块设备的id修改/
作者
zphj1987
发布于
2025年4月10日
许可协议