《重识云原生系列》专题索引:
Ceph统一存储知识地图:
Ceph最早起源于Sage就读博士期间的工作、成果于2004年发表,并随后贡献给开源社区。经过多年的发展之后,已得到众多云计算和存储厂商的支持,成为应用最广泛的开源分布式存储平台。
Ceph根据场景可分为对象存储、块设备存储和文件存储。Ceph相比其它分布式存储技术,其优势点在于:它不单是存储,同时还充分利用了存储节点上的计算能力,在存储每一个数据时,都会通过计算得出该数据存储的位置,尽量将数据分布均衡。同时,由于采用了CRUSH、HASH等算法,使得它不存在传统的单点故障,且随着规模的扩大,性能并不会受到影响。
高性能
高可用性
高可扩展性
特性丰富
Ceph本质上是一个分布式对象存储系统,通过它的对象网关(object gateway),也就是RADOS网关(radosgw)提供对象存储接口。RADOS网关利用librgw(RADOS网关库)和librados这些库,允许应用程序跟Ceph对象存储建立连接。Ceph通过RESTful API提供可访问且最稳定的多租户对象存储解决方案之一。
RADOS网关提供RESTful接口让用户的应用程序将数据存储到Ceph集群中。RADOS网关接口满足一下特点:
要访问Ceph的对象存储系统,也可以绕开RADOS网关层,librados软件库允许用户的应用程序通过C、C++、Java、Python和PHP直接访问Ceph对象存储。
在这种类型中,数据以块的形式存储在卷里,卷会挂接到节点上。这些块形成的卷会映射到操作系统中,并被文件系统层控制。
Ceph引入了一个新的RBD协议,也就是Ceph块设备。RBD为客户端提供了可靠、分布式、高性能的块存储。RBD已经被Linux内核支持,几乎所有的Linux操作系统发行版都支持RBD。除了可靠性和性能之外,RBD也支持其他的企业级特性,如完整和增量式快照,精简的配置,写时复制式克隆以及全内存是缓存。
Ceph RBD支持的最大镜像为16EB。这些镜像可以作为磁盘映射到物理机裸机、虚拟机或者其他主机用。业界领先的开源hypervisor,例如KVM和Xen完全支持RBD。
Ceph文件系统(也就是CephFS)是一个兼容POSIX的文件系统,利用Ceph存储集群来保存用户数据。Linux内核驱动程序支持CephFS,这也使得CephFS高度适用于各大Linux操作系统发行版。CephFS将数据和元数据分开存储,为上层的应用程序提供较高的性能以及可靠性。
在Ceph集群内部,Ceph文件系统库(libcephfs)运行在RADOS库(librados)之上,后者是Ceph存储集群协议,由文件、块和对象存储共用。要使用CephFS,集群节点上最少要配置一个Ceph元数据服务器(MDS),客户端可以采用多种方式使用CephFS。
如果要把Ceph挂在成文件系统,客户端可以使用本地Linux内核的功能或者使用Ceph社区提供的ceph-fuse驱动。
除此之外,客户端可以使用第三方开源程序,例如NFS的ganesha和SMB/CIFS的Samba。这些程序通过libcephfs将用户数据存入可靠的分布式Ceph存储集群。CephFS可以用来替代HDFS。也是通过libcephfs组件将数据存入Ceph集群。为了无缝实现这个功能,Ceph社区为Hadoop和Hadoop插件提供了必要的CephFS Java接口。
Ceph的核心组件包括Client客户端、MON监控服务、MDS元数据服务、OSD存储服务,各组件功能如下:
Ceph采用crush算法,在大规模集群下,实现数据的快速、准确存放,同时能够在硬件故障或扩展硬件设备时,做到尽可能小的数据迁移,其原理如下:
步骤:
说明:
如果新加入的OSD1取代了原有的 OSD4成为 Primary OSD, 由于 OSD1 上未创建 PG , 不存在数据,那么 PG 上的 I/O 无法进行,怎样工作的呢?
步骤:
File用户需要读写的文件。File->Object映射:
a. ino (File的元数据,File的唯一id)。
b. ono(File切分产生的某个object的序号,默认以4M切分一个块大小)。
c. oid(object id: ino + ono)。
Object是RADOS需要的对象。Ceph指定一个静态hash函数计算oid的值,将oid映射成一个近似均匀分布的伪随机值,然后和mask按位相与,得到pgid。Object->PG映射:
a. hash(oid) & mask -> pgid 。
b. mask = PG总数m(m为2的整数幂)-1 。
PG(Placement Group),用途是对object的存储进行组织和位置映射, (类似于redis cluster里面的slot的概念) 一个PG里面会有很多object。采用CRUSH算法,将pgid代入其中,然后得到一组OSD。PG->OSD映射:
a. CRUSH(pgid)->(osd1,osd2,osd3) 。
步骤:
客户端写数据osd过程:
说明:
场景数据迁移流程:
说明:
每个OSD上分布很多PG, 并且每个PG会自动散落在不同的OSD上。如果扩容那么相应的PG会进行迁移到新的OSD上,保证PG数量的均衡。
网络通信框架三种不同的实现方式:
特点:每一个网络链接,都会创建两个线程,一个用于接收,一个用于发送。
缺点:大量的链接会产生大量的线程,会消耗CPU资源,影响性能。
特点:这种是目前网络通信中广泛采用的方式。k版默认已经使用Asnyc了。
特点:这种方式需要依赖第三方的库accelio稳定性,目前处于试验阶段。
设计模式(Subscribe/Publish):
步骤:
通信协议格式需要双方约定数据格式。消息的内容主要分为三部分:
class Message : public RefCountedObject {
protected:
ceph_msg_header header; // 消息头
ceph_msg_footer footer; // 消息尾
bufferlist payload; // "front" unaligned blob
bufferlist middle; // "middle" unaligned blob
bufferlist data; // data payload (page-alignment will be preserved where possible)
/* recv_stamp is set when the Messenger starts reading the Message off the wire */
utime_t recv_stamp; //开始接收数据的时间戳
/* dispatch_stamp is set when the Messenger starts calling dispatch() on its endpoints */
utime_t dispatch_stamp; //dispatch 的时间戳
/* throttle_stamp is the point at which we got throttle */
utime_t throttle_stamp; //获取throttle 的slot的时间戳
/* time at which message was fully read */
utime_t recv_complete_stamp; //接收完成的时间戳
ConnectionRef connection; //网络连接
uint32_t magic = 0; //消息的魔术字
bi::list_member_hook<> dispatch_q; //boost::intrusive 成员字段
};
struct ceph_msg_header {
__le64 seq; // 当前session内 消息的唯一 序号
__le64 tid; // 消息的全局唯一的 id
__le16 type; // 消息类型
__le16 priority; // 优先级
__le16 version; // 版本号
__le32 front_len; // payload 的长度
__le32 middle_len;// middle 的长度
__le32 data_len; // data 的 长度
__le16 data_off; // 对象的数据偏移量
struct ceph_entity_name src; //消息源
/* oldest code we think can decode this. unknown if zero. */
__le16 compat_version;
__le16 reserved;
__le32 crc; /* header crc32c */
} __attribute__ ((packed));
struct ceph_msg_footer {
__le32 front_crc, middle_crc, data_crc; //crc校验码
__le64 sig; //消息的64位signature
__u8 flags; //结束标志
} __attribute__ ((packed));
数据分布和负载均衡:
a. 数据分布均衡,使数据能均匀的分布到各个节点上。
b. 负载均衡,使数据访问读写操作的负载在各个节点和磁盘的负载均衡。
灵活应对集群伸缩:
a. 系统可以方便的增加或者删除节点设备,并且对节点失效进行处理。
b. 增加或者删除节点设备后,能自动实现数据的均衡,并且尽可能少的迁移数据。
支持大规模集群:
a. 要求数据分布算法维护的元数据相对较小,并且计算量不能太大。随着集群规模的增 加,数据分布算法开销相对比较小。
CRUSH算法的全称为:Controlled Scalable Decentralized Placement of Replicated Data,可控的、可扩展的、分布式的副本数据放置算法。
Ceph 分布数据的过程:首先计算数据 x 的 Hash 值并将结果和 PG 数目取余,以得到数据 x 对应的 PG 编号。然后,通过 CRUSH 算法将 PG 映射到一组 OSD 中。最后把数据 x 存放到 PG 对应的 OSD 中。注明:PG 全称是 Placement Group (放置组)。
这个过程中包含了两次映射,第一次是数据 x 到 PG 的映射。如果把 PG 当作存储节点,那么传统 Hash 算法一样。不同的是, PG 是抽象的存储节点,它不会随着物理节点的加入或则离开而增加或减少,因此数据到 PG 的映射是稳定的。
以 Dynamo 为例,在这个过程中, PG 起到了两个作用:第一个作用是划分数据分区。每个 PG 管理的数据区间相同,因而数据能够均匀地分布到 PG 上;第二个作用是充当 Dynamo 中 Token 的角色,即决定分区位置。实际上,这和 Dynamo 中固定分区数目,以及维持分区数目和虚拟节点数目相等的原则是同一回事。
以 Ceph 为例, CRUSH 算法通过两次映射计算数据存储位置来确定如何存储和检索数据。CRUSH 使 Ceph 客户机能够直接与 OSDs 通信,而不是通过集中的服务器或代理。
通过算法确定的数据存储和检索方法, Ceph 避免了单点故障、性能瓶颈和对其可伸缩性的物理限制。CRUSH 需要集群的映射,并使用 CRUSH 映射在 OSDs 中伪随机存储和检索数据,数据在集群中均匀分布。
CRUSH算法因子:
反映了存储系统层级的物理拓扑结构。定义了OSD集群具有层级关系的静态拓扑结构。OSD层级使得CRUSH算法在选择OSD时实现了机架感知能力,也就是通过规则定义,使得副本可以分布在不同的机架、不同的机房中、提供数据的安全性。
决定了一个PG的对象副本如何选择的规则,通过这些可以自己设定规则,用户可以自定义设置副本在集群中的分布。
CRUSH Map是一个树形结构,OSDMap更多记录的是OSDMap的属性(epoch/fsid/pool信息以及osd的ip等等)。
叶子节点是device(也就是osd),其他的节点称为bucket节点,这些bucket都是虚构的节点,可以根据物理结构进行抽象,当然树形结构只有一个最终的根节点称之为root节点,中间虚拟的bucket节点可以是数据中心抽象、机房抽象、机架抽象、主机抽象等。
数据分布策略Placement Rules主要有特点:
rule replicated_ruleset #规则集的命名,创建pool时可以指定rule集
{
ruleset 0 #rules集的编号,顺序编即可
type replicated #定义pool类型为replicated(还有erasure模式)
min_size 1 #pool中最小指定的副本数量不能小1
max_size 10 #pool中最大指定的副本数量不能大于10
step take default #查找bucket入口点,一般是root类型的bucket
step chooseleaf firstn 0 type host #选择一个host,并递归选择叶子节点osd
step emit #结束
}
说明:
集群中有部分sas和ssd磁盘,现在有个业务线性能及可用性优先级高于其他业务线,能否让这个高优业务线的数据都存放在ssd磁盘上。
QoS (Quality of Service,服务质量)起源于网络技术,它用来解决网络延迟和阻塞等问题,能够为指定的网络通信提供更好的服务能力。
问题:
我们总的Ceph集群的iO能力是有限的,比如带宽、IOPS。如何避免用户争取资源,如果保证集群所有用户资源的高可用性,以及如何保证高优用户资源的可用性。所以我们需要把有限的IO能力合理分配。
mClock是一种基于时间标签的I/O调度算法,最先被Vmware提出来的用于集中式管理的存储系统。(目前官方QOS模块属于半成品)。
基本思想:
基于令牌桶算法(TokenBucket)实现了一套简单有效的qos功能,满足了云平台用户的核心需求。
基本思想:
步骤:
令牌图算法框架图:
Ceph的整体架构介绍,这篇文章带入Ceph的大门
Ceph介绍及原理架构分享 - 简书
分布式存储架构_百度百科
Ceph介绍(一):基本原理_Yannick_J的博客-CSDN博客_ceph
我所了解的各公司使用的 Ceph 存储集群 (携程、乐视、有云、宝德云、联通等) - SammyLiu - 博客园