「Ceph」- 客户端

客户端类型

Ceph 支持多种客户端类型,所有的用户数据都是通过客户端进行交互的。每种客户端底层都依赖 Ceph 不同标准的客户端接口:S3/Swift、RBD、CephFS;

Ceph RDB 提供了块存储,其安装方式类似于物理存储驱动器。Ceph RGW 通过其自己的用户管理器提供具有 S3 兼容和 Swift 兼容的 RESTful 接口的对象存储服务。但是,所有 Ceph Client 底层都使用 RADOS 协议和存储集群进行交互;

Ceph 支持当前主流的数据访问方式,比如 NFS、iSCSI、RBD、Filesystem、S3 等等;

librados

librados(分布式对象存储系统 RADOS 库),是对 RADOS 的抽象和封装,并向上层提供 API,用于与 RADOS 系统交互。Client 调用本机上的 librados,再由后者通过 socket 与 RADOS 的节点通信并完成各种操作;

基于 LIBRADOS 实现的兼容 Swift 和 S3 的存储网关系统 RADOSGW;
基于 LIBRADOS 实现的块设备驱动 RBD;
基于 LIBRADOS 实现的 POSIX 分布式文件系统 CephFS;

我们也能够借助 librados 来编写自己的应用,实现与 RADOS 的直接交互;

对象存储接口

现代应用程序需要具有异步通信功能的简单对象存储接口。Ceph Cluster 提供了具有异步通信功能的简单对象存储接口。该接口支持对整个集群中对象的直接、并行访问;

通过对象接口,能够执行以下操作:
1)池操作
2)快照
3)读 / 写对象
4)创建 / 设置 / 获取 / 删除 XATTR
5)创建 / 设置 / 获取 / 删除键 / 值对

访问集群的必要参数

不论哪种存储客户端访问方式,它们都要有以下几个必备要素:
1)Ceph 配置文件和 Ceph Monitor 地址
2)存储池名称
3)用户名和密钥的路径

客户端的 Watch/Notify 机制

在 Ceph Cluster 中,Watch/Notify 机制用于在不同客户端之间进行通信,使各客户端的状态保持一致;

Watch/Notify 机制需关联到特定对象。当多个客户端接收到同一个对象后,任一客户端发送通知消息对该对象所在的 OSD 消息进行复制,进而转发给所有的客户端;

当某客户端不是以只读方式打开对象时会接收消息,并主动发送通知消息到其他客户端,同时接收来自其他客户端的消息。而且该客户端也会收到自己发出去的通知消息,并判断此通知是不是自己发出的消息对应的回应消息;

客户端的独占锁

如果一个 RBD 映射到多个客户端,独占锁能保证在同一时刻 RBD 锁定单个客户端。多个客户端尝试写入同一对象,有助于解决写入冲突问题。此功能建立在 object-watch-notify 机制的基础上。因此,在写入时,如果一个客户端首先在对象上创建了独占锁,另一个客户端在写对象之前会检查该对象上是否设置了独占锁;

启用此功能后,一次只有一个客户端可以修改 RBD 设备。尤其是在创建 / 删除快照等操作期间更改内部 RBD 结构时,独占锁极为重要。它还为操作失败的客户端提供一些保护。例如,如果虚拟机不响应,并且用同一磁盘启动了另一个虚拟机,则无响应的虚拟机将在 Ceph 中被列入黑名单,并且无法破坏新启动的虚拟机;

默认情况下不启用独占锁,创建 RBD 时,必须使用–image-feature 参数显式启用此功能;

rbd create --size 102400 mypool/myimage --image-feature 5

# 数字 5(二进制 101)是 1(二进制 001)和 4(二进制 100)的总和,其中 1 启用 layering,而 4 启用独占锁。因此,
# 以上命令将创建一个 100GB 的 RBD 映像,启用 layering 和独占锁;

客户端的对象映射

当客户端对 RBD 映像执行写操作时,对象映射可跟踪写入链路后端对象。发生写操作时,该写操作将转换为后端 RADOS 对象内的偏移量。启用对象映射功能后,Ceph 将跟踪这些 RADOS 对象。因此,你可以知道对象是否实际存在。对象映射保存在客户端的内存中,这样可以避免在 OSD 中查询不存在的对象。换句话说,对象映射是实际存在的对象的索引;

对象映射对于放大 / 缩小、导出、复制、展平、删除、读操作是有好处的,避免了不必要的对象查找,节省了时间,提高了性能;

执行缩小、导出、复制和删除之类的操作时,客户端将向所有可能受影响的 RADOS 对象(无论它们是否存在)发出操作请求。启用对象映射后,如果对象不存在,则无须执行以上几种操作就能加速放大 / 缩小过程;

对于删除操作,如果你有一个 1TB 的 RBD 块,其中包含成百上千的 RADOS 对象,但没有启用对象映射,则需要为每个对象发出删除操作请求。但是,如果启用了对象映射,则只需对存在的对象发出删除操作请求;

默认情况下不启用对象映射,创建 RBD 时必须使用–image-features 参数显式启用该特性。另外,独占锁是开启对象映射的必要条件。启用对象映射,需要执行如下命令:

rbd -p mypool create myimage --size 102400 --image-features 13

# 此处,数字 13 是 1(二进制 0001)、4(二进制 0100)和 8(二进制 1000)的总和,其中 1 启用 layering,4 启用独占锁,8 启用对象映射;
# 因此,以上命令将创建一个 100GB 的 RBD 映像,启用 layering、独占锁和对象映射;

客户端的数据条带化

问题描述

存储设备具有吞吐量限制,这会影响性能和可伸缩性;

解决方案

存储系统通常使用 Stripe(条带化)技术解决这个问题。Stripe 就是将存储内容进行顺序分片,然后在多个存储设备之间分布式存储每一个分片,以提高吞吐量和性能。数据条带化最常见的形式为 RAID 技术;

原理简述

与 Ceph 条带化最相似的 RAID 类型是 RAID 0,即条带化卷。Ceph 条带化提供类似 RAID 0 的吞吐量、n 路 RAID 镜像的可靠性和更快的恢复速度;

但是 Ceph Stripe 与 RAID 0 相比,还是有很大差异的:

Ceph 提供 3 种类型的客户端(Ceph RBD、CephFS、Ceph Object Storage),Ceph Client 将输入数据(例如 RBD 镜像、RESTful 对象、CephFS 文件系统目录)转换为要存储在 Ceph Cluster 中的对象。Ceph Client 负责存储在集群中的数据进行条带化,然后每个条带分布在不同的对象中,每个对象中含有多个条带单元。也就是说,Ceph 对象并不会被条带化;

所以,每个 Object 相当于 Stripe

该图展示了一种简单的条带化格式:

最简单的 Ceph 条带化格式就是,1 个对象中只有 1 个条带。Ceph Client 将条带单元写入 Ceph 存储对象,直到达到该对象最大容量,然后为其他条带创建对象,以此类推。对于小的 RBD Image 或 S3/Swift 对象,可使用最简单的条带化格式(一个对象中只有一个条带)。但是,这种最简单的形式并没有充分利用 Ceph 在多个放置组中分布数据的优势,因此并不能有效提升性能;

在图中,客户端数据在由 4 个对象组成的对象集(图中的对象集 1)上进行条带化,其中第 1 个条带单元是对象 0 中的条带单元 0,对象 3 写入第 4 个条带后,客户端确定对象集是否已满。如果对象集未满,客户端将再次将条带写入第一个对象集。如果对象集已满,客户端将创建一个新的对象集,参见图中的对象集 2,并开始在新对象集的第一个对象中写入条带单元为 16 的第一个条带,参见图中的对象 4;

数据复制

条带化与对象副本无关。因为 CRUSH 会跨 OSD 实现对象的副本复制,所以条带会跟着对象复制而自动复制;

影响数据条带化的因素

决定 Ceph 如何做数据条带化的因素如下:

1)对象大小:Ceph Cluster 中的对象有最大可配置大小,例如 2 MB 或 4 MB。对象大小应足够大,以容纳多个条带单元,并且是条带单元的倍数。建议最大对象可配置大小安全值为 16 MB;

2)条带大小:条带单元具有可配置的大小,例如 64 KB。Ceph Client 将要写入对象的数据划分为大小相等的条带单元,最后一个条带单元除外。一个对象可以包含多个条带单元;

3)条带数量:Ceph Client 根据条带大小和对象大小判断一份数据需要多少个条带单元,然后将这些条带单元写入一系列(一组)对象,这组对象称为对象集;

性能测试

在将集群投入生产之前,请测试条带化配置的性能。因为将条带化数据写入对象后,你将无法修改条带单元的相关配置参数;