Ceph-05 Ceph 块存储之 RBD
本文讲述 Ceph 块设备存储的相关介绍以及 RBD 相关操作。
# 什么是块设备?
首先,块是一个字节序列(例如,一个 512 字节的数据块)。
块设备是 I/O
设备中的一类,是将信息存储在固定大小的块中,每个块都有自己的地址,
还可以在设备的任意位置读取一定长度的数据。最常见的块设备例如硬盘,U盘,SD卡等。
做一个不是很准确的但是方便你理解的概括:块设备就是以块
作为存储单位的设备。
顺便提一下,与块设备相对应的 I/O
设备是 字符设备
,它是在 IO 传输过程中以字符为单位进行传输的设备。例如键盘,打印机等。
Linux 系统下一般块设备都在 /dev/
目录下,通常块设备(硬盘)连接到计算机之后,系统检测到有新的块设备,
就会自动在 /dev/
目录下创建一个块设备文件,用户就可以通过这个文件去访问块设备。
通常会有 sda, sdb, hda, loop 等这样的块设备文件,其中以 sd 开头的块设备文件对应的是SATA接口的硬盘, 而以hd开头的块设备文件对应的是IDE接口的硬盘。以 loop 开头是循环设备,一般链接到某个文件。
# RBD 是什么?
接下来回到我们的正题,那 rbd 是什么呢? rbd 就是由 Ceph 集群提供出来的块设备。 可以这样理解,sda 和 hda 都是通过数据线连接到了真实的硬盘,而 rbd 是通过网络连接到了 Ceph 集群中的一块存储区域, 往 rbd 设备文件写入数据,最终会被存储到 Ceph 集群的这块区域中。
接下来我们看看官网对 RBD 的介绍:
RBD : Ceph’s RADOS Block Devices , Ceph block devices are thin-provisioned, resizable and store data striped over multiple OSDs in a Ceph cluster.
Ceph 块设备是精简配置的、大小可调且将数据条带化存储到集群内的多个 OSD 。从这句介绍中我们可以得到 RBD 下面的特性。
- RBD 就是 Ceph 里的块设备,挂载以后可以当普通的硬盘使用。
- resizable: 这个块可大可小。
- data striped: 数据条带化,这个块在 Ceph 里面是被切割成若干小块来保存的。
- thin-provisioned: 精简配置的,这个特性有点像虚拟机里面的
VDI
磁盘,块的大小和在 ceph 中实际占用的大小是没有关系的, 并不是你创建 1 个 1GB 的块,它就得占 1GB 的空间。刚开始创建的块设备,甚至不占空间的,今后用多大空间,才会在 Ceph 中占用多大空间。
Ceph 块设备利用 RADOS 的多种能力,如快照、复制和一致性。 Ceph 的 RADOS 块设备( RBD )使用内核模块或 librbd 库与 OSD 交互。下图是 RBD 的基本架构:
Note: 内核模块可使用 Linux 页缓存。对基于 librbd 的应用程序, Ceph 可提供 RBD 缓存。
# 环境说明
- 操作系统: Ubuntu 18.04 LTS
- Ceph 版本: 12.2.12 Luminous (stable)
如果你还没有安装好 Ceph 环境,请参考 Ceph-03 搭建 Ceph 存储集群
# RBD 操作
RBD 的操作有很多,这里只列举几个常用的操作。
Note: 为了方便起见,下文我们统一用 rbd 来指代 Ceph 的块设备。
# 创建块设备
root@ceph1:~# rbd create foo --size=1024
# 查看当前集群所有 rbd
root@ceph1:~# rbd ls
foo
test
--size
是必须传入的参数,单位默认是 MB,你也可以指定成 GB,例如:
rbd create foo --size=100G
查看 rbd 的详细信息:
root@ceph1:~# rbd info foo
rbd image 'foo':
size 1GiB in 256 objects
order 22 (4MiB objects)
block_name_prefix: rbd_data.d36b6b8b4567
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
flags:
create_timestamp: Sun Feb 16 01:36:36 2020
我们可以看到 Ceph 默认创建的 rbd 的默认格式是 format2 (Hammer 以及Hammer 之前默认的格式是 format1)。 我们再创建一个 format1 格式的 rbd:
root@ceph1:~# rbd create foo-1 --size=1024 --image-format=1
rbd: image format 1 is deprecated
root@ceph1:~# rbd ls
foo-1
foo
test
我们可以看到虽然创建成功了,但是 Ceph 发出一个警告:"image format 1 is deprecated",
可见在 Luminous 版本中 format1 格式的 rbd 已经被废弃了。我们再看下 foo-1
的信息:
rbd image 'foo-1':
size 1GiB in 256 objects
order 22 (4MiB objects)
block_name_prefix: rb.0.d372.327b23c6
format: 1
我们可以看到 format1 和 format2 最明显的区别就是 block_name_prefix
的结构不一样。
接下来我们再看看文件结构:
root@ceph1:~# rados -p rbd ls |grep foo
foo-1.rbd
rbd_id.foo
format2 采用rbd_id.{rbd_name}
的形式保存了这个块的 prefix
,而 format1 采用的是 {rbd_name}.rbd
的形式。
下面对这两种格式进行简要的对比总结:
格式 | rbd_diretory | ID | prefix | data |
---|---|---|---|---|
format1 | 保存了所有 RBD 的名称 | foo.rbd | 在 ID 中 | 形如:rb.0.d372.327b23c6 |
format2 | 空 | rbd_id.foo | 在 ID 中并在 rbd_header.prefix 显示输出 | 形如 rbd_data.d36b6b8b4567 |
除了上面意外 format1 和 format2 还有一个很重要的功能区别,那就是只有 format2 的 rbd 的才支持克隆。 这个后面在下文讲 rbd 克隆操作的时候还会提到。
默认创建的 rbd 的 object 大小是 4MiB(2 的 order 次方),我们也可以自己指定大小,例如:
root@ceph1:~# rbd create foo-2 --size=1024 --object-size=8M
root@ceph1:~# rbd info foo-2
rbd image 'foo-2':
size 1GiB in 128 objects
order 23 (8MiB objects)
block_name_prefix: rbd_data.d37c6b8b4567
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
flags:
create_timestamp: Sun Feb 16 03:33:53 2020
如果没有指定,那么默认创建的 rbd 都会在 rbd 这个默认的存储池,如果你需要在其他存储池创建 rbd,可以通过下面的 2 种方式:
root@ceph1:~# rbd create foo-3 --size=1024 --pool rbd2
root@ceph1:~# rbd create rbd2/foo-4 --size=1024
root@ceph1:~# rbd ls rbd2
foo-3
foo-4
# 映射块设备
命令形式:
rbd map {rbd_name}
例如:
root@ceph1:~# rbd map test
/dev/rbd1
root@ceph1:~# rbd showmapped
id pool image snap device
0 rbd test - /dev/rbd0
如果你的 rbd 格式是 format2,那么映射的时候可能会遇到如下错误:
root@ceph1:~# rbd map foo
rbd: sysfs write failed
RBD image feature set mismatch. You can disable features unsupported by the kernel with "rbd feature disable foo 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
出现这种错误的原因是 OS kernel 不支持块设备镜像的一些特性,所以映射失败。这种情况有是那种解决方案
# 方法一
直接diable这个rbd镜像的不支持的特性,首先查看该镜像支持了哪些特性:
rbd image 'foo':
size 1GiB in 256 objects
order 22 (4MiB objects)
block_name_prefix: rbd_data.d36b6b8b4567
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
flags:
create_timestamp: Sun Feb 16 01:36:36 2020
可以看到特性 features 一栏,由于我 OS 的kernel只支持 layering,其他都不支持,所以需要把部分不支持的特性 disable 掉。
root@ceph1:~# rbd feature disable foo exclusive-lock object-map fast-diff deep-flatten
root@ceph1:~# rbd info foo
rbd image 'foo':
size 1GiB in 256 objects
order 22 (4MiB objects)
block_name_prefix: rbd_data.d36b6b8b4567
format: 2
features: layering
flags:
create_timestamp: Sun Feb 16 01:36:36 2020
root@ceph1:~# rbd map foo
/dev/rbd2
# 方法二
创建rbd镜像时就指明需要的特性,如:
root@ceph1:~# rbd create foo2 --size 1024 --image-feature layering
root@ceph1:~# rbd info foo2
rbd image 'foo2':
size 1GiB in 256 objects
order 22 (4MiB objects)
block_name_prefix: rbd_data.d39d6b8b4567
format: 2
features: layering
flags:
create_timestamp: Sun Feb 16 04:09:23 2020
# 方法三
如果还想一劳永逸,那么就在执行创建rbd镜像命令的主机中,修改Ceph配置文件/etc/ceph/ceph.conf,在global section下,增加:
rbd_default_features = 1
这里顺便提一下,这里 features 的配置是通过位运算开关来打开或者关闭某个 feature 的。所以如果你想开启 layering, exclusive-lock
支持,这里的 rbd_default_features
值就应该设置成 0x00011
也就是 3
,依次类推,全部都打开就是 31
(0x11111)。
重启 MON 服务之后生效 systemctl restart ceph-mon.target
# 挂载块设备
挂载之前,跟普通磁盘一样,你先得格式化:
root@ceph1:~# mkfs.ext4 /dev/rbd2
mke2fs 1.44.1 (24-Mar-2018)
Discarding device blocks: done
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: 20f1bdbf-3ecc-4764-a4b9-f351ce168eb3
Superblock backups stored on blocks:
32768, 98304, 163840, 229376
Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done
然后挂载块设备
root@ceph1:~# mkdir /mnt/rbd-foo
root@ceph1:~# mount /dev/rbd2 /mnt/rbd-foo
root@ceph1:~# df -h | grep rbd
/dev/rbd2 976M 2.6M 907M 1% /mnt/rbd-foo
Ceph RBD 支持 POSIX 标准,所以你可以像使用本地存储目录一样使用它。
# 开机自动挂载
有两种方法可以实现 Ceph rbd 的开机自动挂载。
# 方法一
我们知道 rbd 最所以不能像普通的硬盘设备一样开机自动挂载,是因为 Ceph 的 rbd 必须先经过映射(map)操作。
所以我们只需要把 rbd map foo
写入到开机启动脚本就好了。
不知道如何设置的同学请参考 ubuntu-18.04 设置开机启动脚本。
这里就不做赘述了。
# 方法二
Ceph 本身为我们提供了一种更高级的自动映射 rbd 的方法。
首先我们需要在部署节点上把客户端验证的 key 推送到客户端。
ceph-deploy admin ceph-client
# 如果部署节点没有 ceph-client 的验证信息,可以直接用 scp 拷贝
scp /etc/ceph/ceph.client.admin.keyring root@{client.ip}:/etc/ceph/
然后我们编辑客户端的 rbdmap 文件 vim /etc/ceph/rbdmap
,添加一行自动 map 的配置:
rbd/{rbd_name} id=admin,keyring=/etc/ceph/ceph.client.admin.keyring
{rbd_name}
是你需要自动 map 的 rbd 名称,比如你改成 foo
,这样 Ceph 就会在开机的时候自动映射 foo
块设备。
接下来就简单了,我们可以像普通硬盘一样开机挂载了。编辑 /etc/fstab
,添加一行自动挂载的配置
/dev/rbd/rbd/{rbd_name} /mnt/rbd ext4 defaults,noatime,_netdev 0 2
这里的 {rbd_name}
同样需要改成对应的 rbd 实际名称,同时需要注意加上 _netdev
选项,表示是网络设备。
# RBD 删除
这个非常简单,命令形式如下:
rbd rm {pool_name}/{rbd_name}
例如:
rbd rm rbd/foo
# RBD 快照
创建快照:
rbd snap create {rbd_name}@{snap_name}
例如:
rbd snap create foo@foo-snap-01
root@client:~# rbd snap ls foo
SNAPID NAME SIZE TIMESTAMP
10 foo-snap-01 4GiB Fri Feb 7 04:13:05 2020
删除快照:
rbd snap rm {rbd_name}@{snap_name}
例如:
rbd snap rm foo@foo-snap-01
快照回滚,如果不小心删除数据了,并且之前有创建快照的话,可以使用快照回滚:
rbd snap rollback {rbd_name}@{snap_name}
例如:
root@client:# rbd snap rollback foo@foo-snap-01
Rolling back to snapshot: 100% complete...done.
Note: 回滚之前要先 umout 块设备,回滚之后再重新 mount。
# 通过快照克隆 RBD
首选,被克隆的 rbd 格式必须是 format2
(1)克隆之前,先保护快照,以免被修改。
rbd snap protect foo@s_foo_1
(2)克隆
rbd clone foo@s_foo_1 clone_foo
rbd image 'clone_foo':
size 1GiB in 256 objects
order 22 (4MiB objects)
block_name_prefix: rbd_data.148a76b8b4567
format: 2
features: layering
flags:
create_timestamp: Sun Feb 16 10:02:24 2020
parent: rbd/foo@s_foo_1
overlap: 1GiB
此时我们可以看到 clone_foo
的 parent
属性为 rbd/foo@s_foo_1
,表示引用的是 rbd/foo@s_foo_1
快照
(3)脱离
现在 clone_foo
还是跟 rbd/foo@s_foo_1
关联在一起的。还不是一个独立的 rbd
,所以我们需要把他们脱离:
root@client:# rbd flatten clone_foo
Image flatten: 100% complete...done.
root@client:# rbd info clone_foo
rbd image 'clone_foo':
size 1GiB in 256 objects
order 22 (4MiB objects)
block_name_prefix: rbd_data.148a76b8b4567
format: 2
features: layering
flags:
create_timestamp: Sun Feb 16 10:02:24 2020
脱离之后 clone_foo
就是一个独立的 rbd
了。
# RBD 扩容
RBD 的扩容分 2 步:
- 扩展块大小
- 扩展 fs(文件系统)
Ceph 块设备映像是精简配置,只有在你开始写入数据时它们才会占用物理空间。然而,它们都有最大容量,就是你设置的 --size 选项。 如果你想增加(或减小) Ceph 块设备映像的最大尺寸,执行下列命令:
rbd resize --size 2048 foo #增加块设备容量
rbd resize --size 2048 foo --allow-shrink # 减少块设备容量
如果 rbd 已经被挂载了,扩容/缩容之后还需要扩展挂载 rbd 的文件系统,否则不会生效。
ext4 文件系统扩容:
resize2fs /dev/rbdxxx
xfs 文件系统扩容:
xfs_growfs /dev/rbdxxx
# RBD 缩容
Note: xfs 文件系统不支持文件系统缩小,只能增大,ext4 文件系统支持扩大和缩小
RBD 缩容比较麻烦,分为 4 步:
- 先卸载文件系统 umout /dev/rbd0
- 检测文件系统 e2fsck -f /dev/rbd0
- 缩小文件系统 resize2fs /devrbd0 400M
- 缩小块大小 rbd resize --image rbd1 --size 400 --allow-shrink
注意,上面的步骤不能乱,要严格按照顺序执行。操作完之后,要记得检查块设备里面的文件是否可以正常访问,是否有损坏。
# 参考文献
本站博文如非注明转载则均属作者原创文章,引用或转载无需申请版权或者注明出处,如需联系作者请加微信: geekmaster01