Ceph知识分享
- Ceph架构简介及使用场景介绍
1.1 Ceph简介
Ceph是一个统一的分布式存储系统,设计初衷是提供较好的性能、可靠性和可扩展性。Ceph项目最早起源于Sage就读博士期间的工作(最早的成果于2004年发表),并随后贡献给开源社区。在经过了数年的发展之后,目前已得到众多云计算厂商的支持并被广泛应用。RedHat及OpenStack都可与Ceph整合以支持虚拟机镜像的后端存储。
1.2 Ceph特点
- Ceph支持对象存储、块存储和文件存储服务,故称为统一存储。
- 采用CRUSH算法,数据分布均衡,并行度高,不需要维护固定的元数据结构。
- 数据具有强一致,确保所有副本写入完成才返回确认,适合读多写少场景。
- 去中心化,MDS之间地位相同,无固定的中心节点。
1.2.1 Ceph相比于其他存储方案的优点
- 高性能
- 摒弃了传统的集中式存储元数据寻址的方案,采用CRUSH算法,数据分布均衡,并行度高,Ceph客户端读写数据可以直接与存储设备(osd) 交互。
- 考虑了容灾域的隔离,能够实现各类负载的副本放置规则,例如跨机房、机架感知等。
- 能够支持上千个存储节点的规模,支持TB到PB级的数据。
- 高可用性
- 副本数可以灵活控制。
- 支持故障域分隔,数据强一致性。
- 多种故障场景自动进行修复自愈。
- 没有单点故障,自动管理。
- 高可扩展性
- 去中心化(Ceph不同于Swift,客户端所有的读写操作都要经过代理节点。一旦集群并发量增大时,代理节点很容易成为单点瓶颈。Ceph本身并没有主控节点)。
- 扩展灵活。
- 随着节点增加而线性增长。
- 特性丰富
- 支持三种存储接口:块存储、文件存储、对象存储(关于这三种类型存储的特性见本文第2章节),三种方式可以一同使用。
- 支持自定义接口,支持多种语言驱动。
1.2.2 Ceph存在一些缺点
- 去中心化的分布式解决方案,需要提前做好规划设计,对技术团队的要求能力比较高。
- Ceph扩容时,由于其数据分布均衡的特性,会导致整个存储系统性能的下降。
1.3 Ceph架构
1.3.1 Ceph的逻辑组织架构
支持三种接口:
- 对象存储:有原生的API,而且也兼容Swift和S3的API。
- 块存储:支持精简配置、快照、克隆。
- 文件存储:Posix接口,支持快照。
- RADOS
全称Reliable Autonomic Distributed Object Store,是Ceph集群的精华, Ceph存储集群的基础,负责保存存储对象,确保数据始终保持一致。
- Librados
Librados库,支持从应用程序直接访问RADOS(没有HTTP开销),同时为块存储(通过RBD)、对象存储(通过RGW)、文件系统(通过CephFS)提供原生接口。
- RADOSGW
网关接口,提供对象存储服务,使用librgw和librados来实现,允许应用程序与Ceph对象存储建立连接,提供与S3和Swift 兼容的RESTful API接口。
- RBD
块存储,提供自动精简配置并可调整大小,将数据分散存储在多个OSD上。
- CephFS
与POSIX兼容的文件系统,基于librados封装原生接口。
1.3.2 Ceph的数据组织架构
- File
用户需要存储或者访问的文件。
- Object
Ceph最底层的存储单元是Object对象,每个Object包含元数据和原始数据。无论使用哪种存储方式(对象、块、文件),存储的数据都会被切分成对象(Objects)。Objects size大小可以由管理员调整,通常为2M或4M。每个对象都会有一个唯一的OID,由ino与ono生成,一个Object只能映射到一个PG中,和PG是多对一的关系。
- Pool
存储池分区,存储池的大小取决于底层的存储空间,是ceph存储数据时的逻辑分区,它起到namespace的作用,每个pool包含一定数量(可配置)的PG。
- PG
PG全称Placement Grouops,是一个逻辑的概念,在linux系统中可以直接看到对象,但是无法直接看到PG。因为对象的size很小,在一个大规模的集群中可能有几百到几千万个对象。这么多对象光是遍历寻址,速度都是很缓慢的;并且如果将对象直接通过某种固定映射的哈希算法映射到osd上,当这个osd损坏时,对象无法自动迁移至其他osd上面(因为映射函数不允许)。为了解决这些问题,ceph引入了归置组的概念,即PG,它在数据寻址时类似于数据库中的索引:每个对象都会固定映射进一个PG中,所以当我们要寻找一个对象时,只需要先找到对象所属的PG,然后遍历这个PG就可以了,无需遍历所有对象。而且在数据迁移时,也是以PG作为基本单位进行迁移,ceph不会直接操作对象。一个PG包含多个OSD,和OSD是多对多的关系。
1.4 Ceph核心组件及功能
- OSD
OSD全称Object Storage Device,也就是负责响应客户端请求返回具体数据的进程,用于Ceph集群中所有数据与对象的存储,一个Ceph集群一般都有很多个OSD。主要功能包括:
-
- 处理集群数据的复制、恢复、回填、再均衡。
- 向其他osd守护进程发送心跳,然后向Mon提供一些监控信息。
OSD的数量关系到系统的数据分布均匀性,数量不应太少,生产实践中至少需要数十上百个量级才有助于Ceph系统的设计优势。当Ceph存储集群设定数据有两个副本时(一共存两份),则至少需要两个OSD守护进程即两个OSD节点,集群才能达到active+clean状态。
- Monitor
一个Ceph集群需要多个Monitor组成的集群,它们通过Paxos同步数据,用来保存OSD的元数据,要求必须是奇数个Monitor监控节点,一般建议至少是3个。拥有以下功能:
-
- 监视ceph集群,维护ceph集群健康状态。
- 维护ceph集群映射关系:Cluster Map(OSD Map,Monitor Map,PG Map,CRUSH Map, MDS Map)。
- 管理集群中所有成员,关系和属性等信息及数据的分发。
如:当用户需要存储数据到ceph时,OSD需要通过Monitor获取最新的Map图,根据Map图和object id计算数据最终存储的位置。
- Manager
Ceph manager 守护进程(Ceph-mgr)是在Kraken版本中引入的,它与monitor守护进程一起运行,拥有以下功能:
-
- 为外部监视和管理系统提供额外的监视和接口。
- 负责跟踪运行时指标和ceph集群的状态,存储利用率,当前性能指标和系统负载。
- MDS
MDS全称Ceph Metadata Server,MDS进程并不是必须的进程,只有需要使用CEPHFS时,才需要配置MDS节点,是CephFS服务依赖的元数据服务。功能如下:
2.1块存储
典型设备: 磁盘阵列,硬盘,主要是将裸磁盘空间映射给主机使用的。
优点:
- 通过Raid与LVM等手段,对数据提供了保护。
- 多块廉价的硬盘组合起来,提高容量。
- 多块磁盘组合出来的逻辑盘,提升读写效率。
缺点:
- 采用SAN架构组网时,光纤交换机,造价成本高。
- 主机之间无法共享数据。
使用场景:
- docker容器、虚拟机磁盘存储分配。
- 日志存储。
- 文件存储。
2.2文件存储
典型设备: FTP、NFS服务器 为了克服块存储文件无法共享的问题,所以有了文件存储。 在服务器上架设FTP与NFS服务,就是文件存储。
优点:
- 造价低,随便一台机器就可以了。
- 方便文件共享。
缺点:
- 读写速率低。
- 传输速率慢。
使用场景:
- 日志存储。
- 有目录结构的文件存储等。
2.3 对象存储
典型设备: 内置大容量硬盘的分布式服务器(swift, s3) 多台服务器内置大容量硬盘,安装上对象存储管理软件,对外提供读写访问功能。
- 优点:
- 具备块存储的读写高速。
- 具备文件存储的共享等特性。
- 使用场景: (适合更新变动较少的数据)
- 图片存储。
- 视频存储。
- Ceph之RADOS说明
RADOS (Reliable, Autonomic Distributed Object Store) 是Ceph的核心之一,作为Ceph分布式文件系统的一个子项目,特别为Ceph的需求设计,能够在动态变化和异质结构的存储设备机群之上提供一种稳定、可扩展、高性能的单一逻辑对象(Object)存储接口和能够实现节点的自适应和自管理的存储系统。
在传统分布式存储架构中,存储节点往往仅作为被动查询对象来使用,随着存储规模的增加,数据一致性的管理会出现很多问题。而新型的存储架构倾向于将基本的块分配决策和安全保证等操作交给存储节点来做,然后通过提倡客户端和存储节点直接交互来简化数据布局并减小io瓶颈。RADOS就是这样一个可用于PB级规模数据存储集群的可伸缩的、可靠的对象存储服务。它包含两类节点:存储节点、管理节点。它通过利用存储设备的智能性,将诸如一致性数据访问、冗余存储、错误检测、错误恢复分布到包含了上千存储节点的集群中,而不是仅仅依靠少数管理节点来处理。
RADOS中的存储节点被称为OSD(object storage device),它可以仅由很普通的组件来构成,只需要包含CPU、网卡、本地缓存和一个磁盘或者RAID,并将传统的块存储方式替换成面向对象的存储。在PB级的存储规模下,存储系统一定是动态的:系统会随着新设备的部署和旧设备的淘汰而增长或收缩,系统内的设备会持续地崩溃和恢复,大量的数据被创建或者删除。
RADOS通过 cluster map来实现这些,Cluster Map会被复制到集群中的所有部分(存储节点、控制节点,甚至是客户端),并且通过怠惰地传播小增量更新而更新。Cluster Map中存储了整个集群的数据的分布以及成员。通过在每个存储节点存储完整的Cluster Map,存储设备可以表现的半自动化,通过peer-to-peer的方式(比如定义协议)来进行数据备份、更新,错误检测、数据迁移等操作。这无疑减轻了占少数的monitor cluster(管理节点组成的集群)的负担。
RADOS的设计如下:
一个RADOS系统包含大量的OSDs 和 很少的用于管理OSD集群成员的monitors。OSD的组成如简介所说。而monitor是一些独立的进程,以及少量的本地存储,monitor之间通过一致性算法保证数据的一致性。
- Ceph CRUSH算法
CRUSH 是一种分布式算法,类似于一致性 hash 算法,用于为 RADOS 存储集群控制数据的分配。Ceph 使用 CURSH 算法来存放和管理数据,它是 Ceph 的智能数据分发机制。Ceph 使用 CRUSH 算法来准确计算数据应该被保存到哪里,以及应该从哪里读取;和保存元数据不同的 是,CRUSH 按需计算出元数据,因此它就消除了对中心式的服务器/网关的需求,它使得 Ceph 客户端能够计算出元数据,该过程也称为 CRUSH 查找,然后和 OSD 直接通信。 如果是把对象直接映射到 OSD 之上会导致对象与 OSD 的对应关系过于紧密和耦合,当 OSD 由于故障发生变更时将会对整个 ceph 集群产生影响。于是 ceph 将一个对象映射到 RADOS 集群的时候分为两步走:
- 首先使用一致性 hash 算法将对象名称映射到 PG。
- 然后将 PG ID 基于 CRUSH 算法映射到 OSD 即可查到对象。
以上两个过程都是以”实时计算”的方式完成,而没有使用传统的查询数据与块设备的对应表的方式,这样有效避免了组件的”中心化”问题,也解决了查询性能和冗余问题。使得 Ceph 集群扩展不再受查询的性能限制。
4.1 数据分布算法挑战
- 数据分布和负载均衡
- 数据分布均衡,使数据能均匀的分布到各个节点上。
- 负载均衡,使数据访问读写操作的负载在各个节点和磁盘的负载均衡。
- 灵活应对集群伸缩
- 系统可以方便的增加或者删除节点设备,并且对节点失效进行处理。
- 增加或者删除节点设备后,能自动实现数据的均衡,并且尽可能少的迁移数据。
- 支持大规模集群
- 要求数据分布算法维护的元数据相对较小,并且计算量不能太大。
- 随着集群规模的增加,数据分布算法开销相对比较小。
4.2 Ceph CRUSH算法说明
- CRUSH算法的全称为:Controlled Scalable Decentralized Placement of Replicated Data,可控的、可扩展的、分布式的副本数据放置算法。
- PG到OSD的映射的过程算法叫做CRUSH 算法。(一个Object需要保存三个副本,也就是需要保存在三个OSD上)。
- CRUSH算法是一个伪随机的过程,他可以从所有的OSD中,随机性选择一个OSD集合,但是同一个PG每次随机选择的结果是不变的,也就是映射的OSD集合是固定的。
4.3 Ceph CRUSH算法原理
CRUSH算法因子:
- 层次化的Cluster Map 反映了存储系统层级的物理拓扑结构。定义了OSD集群具有层级关系的 静态拓扑结构。OSD层级使得 CRUSH算法在选择OSD时实现了机架感知能力,也就是通过规则定义, 使得副本可以分布在不同的机 架、不同的机房中、提供数据的安全性 。
- Placement Rules 决定了一个PG的对象副本如何选择的规则,通过这些可以自己设定规则,用户可以自定义设置副本在集群中的分布。
4.3.1 层级化的Cluster Map
CRUSH Map是一个树形结构,OSD Map更多记录的是OSD的属性(epoch/fsid/pool信息以及osd的ip等等)。
叶子节点是device(也就是osd),其他的节点称为bucket节点,这些bucket都是虚构的节点,可以根据物理结构进行抽象,当然树形结构只有一个最终的根节点称之为root节点,中间虚拟的bucket节点可以是数据中心抽象、机房抽象、机架抽象、主机抽象等。
4.3.2 数据分布策略Placement Rules
数据分布策略Placement Rules主要有以下特点:
- 从CRUSH Map中的哪个节点开始查找
- 使用哪个节点作为故障隔离域
- 定位副本的搜索模式(广度优先 or 深度优先)
rule replicated_ruleset #规则集的命名,创建pool时可以指定rule集。
{
ruleset 1 # 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 #结束
}
4.3.3 Bucket随机算法类型
- 一般的buckets:适合所有子节点权重相同,而且很少添加删除item。
- list buckets:适用于集群扩展类型。增加item,产生最优的数据移动,查找item,时间复杂度O(n)。
- tree buckets:查找复杂度是O (log n), 添加删除叶子节点时,其他节点node_id不变。
- straw buckets:允许所有项通过类似抽签的方式来与其他项公平“竞争”。定位副本时,bucket中的每一项都对应一个随机长度的straw,且拥有最长长度的straw会获得胜利(被选中),添加或者重新计算,子树之间的数据移动提供最优的解决方案。
4.4 CRUSH算法案例
说明: 集群中有部分sas和ssd磁盘,现在有个业务线性能及可用性优先级高于其他业务线,能否让这个高优业务线的数据都存放在ssd磁盘上。
普通用户:
高优用户:
配置规则:
- Ceph的元数据存储
Ceph元数据以key-value的形式存,在RADOS 中有两种实现方式: xattrs 和 omap。
- xattrs(扩展属性)
将元数据保持在对应的文件扩展属性中,并保存在系统磁盘上,要求支持对象存储的本地系统(一般是XFS)支持扩展属性。
- omap(对象映射)
是Object Map 的简称,将元数据保存在本地文件系统之外的key-value存储系统中,使用filestore时是leveldb,使用bluestore时是rocksdb,由于filestore存在功能问题(需要将磁盘格式化为XFS格式)及元数据高可用问题,因此目前ceph主要使用bluestore。
Ceph 可以选多种存储引擎,如filestore,bluestore,kvstore,memstore,目前Ceph使用blustore存储对象数据的元数据。
5.1 Ceph存储引擎 之FileStore
早期Ceph基于filestore存储引擎使用google 的leveldb 保存对象的元数据,Leveldb 是一个持久化存储的键值系统,和 Redis 这种内存型的 KV 系统不同,leveldb 不会像 Redis 一样将数据放在内存从而占用大量的内存空间,而是将大部分数据存储到磁盘上,但是需要把磁盘上的 leveldb 空间格式化为文件系统(XFS)。
filestore 将数据保存到与 Posix 兼容的文件系统(例如 Btrfs、XFS、Ext4)。在 Ceph 后端使用传统的 Linux 文件系统尽管提供了一些好处,但也有代价,如性能、 对象属性与磁盘本地文件系统属性匹配存在限制等。
5.2 Ceph存储引擎 之BlueStore
BlueStore最早在Jewel版本中引入,用于在SSD上替代传统的FileStore。作为新一代的高性能对象存储后端,BlueStore在设计中便充分考虑了对SSD以及NVME的适配。针对FileStore的缺陷,BlueStore选择绕过文件系统,直接接管裸设备,直接进行对象数据IO操作,同时元数据存放在RocksDB,大大缩短了整个对象存储的IO路径。BlueStore可以理解为一个支持ACID事物型的本地日志文件系统。
BlueStore整体架构设计如下图:
BlueStore 的逻辑架构如上图所示,模块的划分都还比较清晰,我们来看下各模块的作用。
- Allocator
BlueStore的磁盘分配器,负责高效的分配磁盘空间,目前支持Stupid和Bitmap两种磁盘分配器,都是仅仅在内存中分配,并不做持久化。
- RocksDB
RocksDB 是 facebook 基于 leveldb 开发的一款键值对数据库,BlueStore 将元数据全部存放至 RocksDB 中,这些元数据包括存储预写式日志、数据对象元数据、Ceph 的 omap 数据信息、以及分配器的元数据 。
- RocksDB 将对象数据的元数据保存在 RocksDB,但是 RocksDB 的数据又放在哪里呢?放在内存怕丢失,放在本地磁盘但是解决 不了高可用,ceph 对象数据放在了每个 OSD 中,那么就在当前 OSD 中划分出一部分空间,格式化为 BlueFS 文件系统用于保存 RocksDB 中的元数据信息(称为 BlueStore),并实 现元数据的高可用,BlueStore 最大的特点是构建在裸磁盘设备之上,并且对诸如 SSD 等 新的存储设备做了很多优化工作。
-
-
- 对全 SSD 及全 NVMe SSD 闪存适配 绕过本地文件系统层,直接管理裸设备,缩短 IO 路径 严格分离元数据和数据,提高索引效率
- 期望带来至少 2 倍的写性能提升和同等读性能 增加数据校验及数据压缩等功能
- 解决日志“双写”问题
- 使用 KV 索引,解决文件系统目录结构遍历效率低的问题 支持多种设备类型
-
-
- RocksDB 通过中间层 BlueRocksDB 访问文件系统的接口。这个文件系统与传统的 Linux 文件系统(例如 Ext4 和 XFS)是不同的,它不是在 VFS 下面的通用文件系统,而是一个用 户态的逻辑。BlueFS 通过函数接口(API,非 POSIX)的方式为 BlueRocksDB 提供类似文 件系统的能力。
- BlueRocksEnv
这是 RocksDB 与 BlueFS 交互的接口;RocksDB 提供了文件操作的接口 EnvWrapper(Env 封装器),可以通过继承实现该接口来自定义底层的读写操作, BlueRocksEnv 就是继承自 EnvWrapper 实现对 BlueFS 的读写。
- BlueFS
BlueFS 是 BlueStore 针对 RocksDB 开发的轻量级文件系统,用于存放 RocksDB 产生的.sst 和.log 等文件。
- BlockDecive
BlueStore 抛弃了传统的 ext4、xfs 文件系统,使用直接管理裸盘的方式; BlueStore 支持同时使用多种不同类型的设备,在逻辑上 BlueStore 将存储空间划分为三层:
-
-
- 慢速(Slow)空间:存储对象数据,可以使用HDD,由BlueStore管理。
- 高速(DB)空间:存储RocksDB的sst文件,可以使用SSD,由BlueFS管理。
- 超高速(WAL)空间:存储RocksDB的log文件,可以使用NVME,由BlueFS管理。
-
不同的空间可以指定使用不同的设备类型,当然也可使用同一块设备。
BlueStore 的设计考虑了 FileStore 中存在的一些硬伤,抛弃了传统的文件系统直接管理裸 设备,缩短了 IO 路径,同时采用 ROW 的方式,避免了日志双写的问题,在写入性能上有 了极大的提高,如下图所示展示了Filestore和Bluestore引擎写数据的速率。
- Ceph通信框架
6.1 Ceph通信框架种类介绍
网络通信框架三种不同的实现方式:
- Simple线程模式
特点:每一个网络链接,都会创建两个线程,一个用于接收,一个用于发送。
缺点:大量的链接会产生大量的线程,会消耗CPU资源,影响性能。
- Async事件的I/O多路复用模式
特点:这种是目前网络通信中广泛采用的方式。k版默认已经使用Asnyc了。
- XIO模式
特点:使用了开源的网络通信库accelio来实现,这种方式需要依赖第三方的库accelio稳定性,目前处于试验阶段。
6.2 Ceph通信框架设计模式
设计模式(Subscribe/Publish): 订阅发布模式又名观察者模式,它意图是“定义对象间的一种一对多的依赖关系, 当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新”。
6.3 Ceph通信框架流程图
步骤:
- Accepter监听peer的请求, 调用 SimpleMessenger::add_accept_pipe() 创建新的 Pipe 到 SimpleMessenger::pipes 来处理该请求。
- Pipe用于消息的读取和发送,该类主要有两个组件,Pipe::Reader,Pipe::Writer用来处理消息读取和发送。
- Messenger作为消息的发布者, 各个 Dispatcher 子类作为消息的订阅者, Messenger 收到消息之后, 通过 Pipe 读取消息,然后转给 Dispatcher 处理。
- Dispatcher是订阅者的基类,具体的订阅后端继承该类,初始化的时候通过 Messenger::add_dispatcher_tail/head 注册到 Messenger::dispatchers. 收到消息后,通知该类处理。
- DispatchQueue该类用来缓存收到的消息, 然后唤醒DispatchQueue::dispatch_thread 线程找到后端的 Dispatch 处理消息。
6.4 Ceph通信框架类图
6.5 Ceph通信数据格式
通信协议格式需要双方约定数据格式,消息的内容主要分为三部分:
- header // 消息头,类型消息的信封
- user data // 需要发送的实际数据
-
- payload // 操作保存元数据
- middle // 预留字段
- data // 读写数据
-
- footer //消息的结束标记
如下为一具体的ceph通信数据格式案例:
7.1 正常IO流程图
步骤:
- client 创建cluster handler。
- client 读取配置文件。
- client 连接上monitor,获取集群map信息。
- client 读写io 根据crshmap 算法请求对应的主osd数据节点。
- 主osd数据节点同时写入另外两个副本节点数据。
- 等待主节点以及另外两个副本节点写完数据状态。
- 主节点及副本节点写入状态都成功后,返回给client,io写入完成。
7.2 新主IO流程图
说明: 如果新加入的OSD1取代了原有的 OSD4成为 Primary OSD, 由于 OSD1 上未创建 PG , 不存在数据,那么 PG 上的 I/O 无法进行,怎样工作的呢?
步骤:
- client连接monitor获取集群map信息。
- 同时新主osd1由于没有pg数据会主动上报monitor告知让osd2临时接替为主。
- 临时主osd2会把数据全量同步给新主osd1。
- client IO读写直接连接临时主osd2进行读写。
- osd2收到读写io,同时写入另外两副本节点。
- 等待osd2以及另外两副本写入成功。
- osd2三份数据都写入成功返回给client, 此时client io读写完毕。
- 如果osd1数据同步完毕,临时主osd2会交出主角色。
- osd1成为主节点,osd2变成副本。
7.3 Ceph IO算法流程
Ceph 需要走完 (Pool, Object) → (Pool, PG) → OSD set → OSD/Disk 完整的链路,才能让 ceph client 知道目标数据 object的具体位置在哪里。数据写入时,文件被切分成object,object先映射到PG,再由PG映射到OSD set。每个pool有多个PG,每个object通过计算hash值并取模得到它所对应的PG。PG再映射到一组OSD(OSD个数由pool的副本数决定),第一个OSD是Primary,剩下的都是Replicas,步骤如下:
- 计算文件到对象的映射
File->Object映射,oid = ino + ono,其中ino 为File的元数据,File的唯一id;ono为File切分产生的某个object的序号,默认以4M切分一个块大小。
- 对象Object到PG的映射
Object -> PG,通过静态hash 算法计算出文件对应的 pool 中的 PG,通过一致性 hash 计算oid的值,将oid映射成一个近似均匀分布的伪随机值,然后和mask按位相与,得到pgid。公式为: hash(oid) & mask-> pgid,其中mask = PG总数m(m为2的整数幂)-1 。
- PG到OSD的映射
通过 CRUSH 把对象映射到 PG 中的 OSD ,通过CRUSH算法通过pgid计算得到对象需要存储到的OSD,公式为:CRUSH(pgid)->(osd1,osd2,osd3)。
- PG 中的主 OSD 将对象写入到硬盘。
- 主 OSD 将数据同步给备份 OSD,并等待备份 OSD 返回确认。
- 主 OSD 将写入完成返回给客户端。
7.3.1 Ceph IO伪代码流程
locator = object_name
obj_hash = hash(locator)
pg = obj_hash % num_pg
osds_for_pg = crush(pg) # returns a list of osds
primary = osds_for_pg[0]
replicas = osds_for_pg[1:]
7.4.2 Ceph PG数量的确定
- PG数量的设置牵扯到数据分布的均匀性问题。
- 预设Ceph集群中的PG数至关重要,公式如下: (结果必须舍入到最接近2的N次幂的值)
- PG 总数 = (OSD 数 * 100) / 最大副本数
- 集群中单个池的PG数计算公式如下:(结果必须舍入到最接近2的N次幂的值)
- PG 总数 = (OSD 数 * 100) / 最大副本数 / 池数
- PGP是为了实现定位而设计的PG,PGP的值应该和PG数量保持一致;pgp_num 数值才是 CRUSH 算法采用的真实值。
- 虽然 pg_num 的增加引起了PG的分割,但是只有当 pgp_num增加以后,数据才会被迁移到新PG中,这样才会重新开始平衡。
7.4 Ceph RBD IO流程
步骤:
- 客户端创建一个pool,需要为这个pool指定pg的数量。
- 创建pool/image rbd设备进行挂载。
- 用户写入的数据进行切块,每个块的大小默认为4M,并且每个块都有一个名字,名字就是object+序号。
- 将每个object通过pg进行副本位置的分配。
- pg根据cursh算法会寻找3个osd,把这个object分别保存在这三个osd上。
- osd上实际是把底层的disk进行了格式化操作,一般部署工具会将它格式化为xfs文件系统。
- object的存储就变成了存储一个文rbd0.object1.file。
7.5 Ceph RBD IO框架图
客户端写数据osd过程:
- 采用的是librbd的形式,使用librbd创建一个块设备,向这个块设备中写入数据。
- 在客户端本地通过调用librados接口,然后经过pool,rbd,object、pg进行层层映射,在PG这一层中,可以知道数据保存在哪3个OSD上,这3个OSD分为主从的系统。
- 客户端与primay OSD建立SOCKET 通信,将要写入的数据传给primary OSD,由primary OSD再将数据发送给其他replica OSD数据节点。
7.6 Ceph Pool和PG分布情况
说明:
- pool是ceph存储数据时的逻辑分区,它起到namespace的作用。
- 每个pool包含一定数量(可配置)的PG。
- PG里的对象被映射到不同的OSD上。
- pool是分布到整个集群的。
- pool可以做故障隔离域,根据不同的用户场景不同进行隔离。
7.7 Ceph 数据扩容PG分布
场景数据迁移流程:
- 现状3个OSD, 4个PG
- 扩容到4个OSD, 4个PG
现状:
扩容后:
说明:
每个OSD上分布很多PG, 并且每个PG会自动散落在不同的OSD上。如果扩容那么相应的PG会进行迁移到新的OSD上,保证PG数量的均衡。
8.1 心跳介绍
心跳是用于节点间检测对方是否故障,以便及时发现故障节点进入相应的故障处理流程,心跳机制可能面临以下问题:
- 故障检测时间和心跳报文带来的负载之间做权衡。
- 心跳频率太高则过多的心跳报文会影响系统性能。
- 心跳频率过低则会延长发现故障节点的时间,从而影响系统的可用性。
故障检测策略应该能够做到:
- 及时:节点发生异常如宕机或网络中断时,集群可以在可接受的时间范围内感知。
- 适当的压力:包括对节点的压力,和对网络的压力。
- 容忍网络抖动:网络偶尔延迟。
- 扩散机制:节点存活状态改变导致的元信息变化需要通过某种机制扩散到整个集群。
8.2 Ceph 心跳检测
OSD节点会监听public、cluster、front和back四个端口
- public端口:监听来自Monitor和Client的连接。
- cluster端口:监听来自OSD Peer的连接。
- front端口:供客户端连接集群使用的网卡, 这里临时给集群内部之间进行心跳。
- back端口:供集群内部使用的网卡。集群内部之间进行心跳。
- hbclient:发送ping心跳的messenger。
8.3 Ceph OSD之间相互心跳检测
步骤:
- 同一个PG内OSD互相心跳,他们互相发送PING/PONG信息。
- 每隔6s检测一次(实际会在这个基础上加一个随机时间来避免峰值)。
- 20s没有检测到心跳回复,加入failure队列。
8.4 Ceph OSD与Mon心跳检测
OSD报告给Monitor:
- OSD有事件发生时(比如故障、PG变更)。
- 自身启动5秒内。
- OSD周期性的上报给Monitor
- OSD检查failure_queue中的伙伴OSD失败信息。
- 向Monitor发送失效报告,并将失败信息加入failure_pending队列,然后将其从failure_queue移除。
- 收到来自failure_queue或者failure_pending中的OSD的心跳时,将其从两个队列中移除,并告知Monitor取消之前的失效报告。
- 当发生与Monitor网络重连时,会将failure_pending中的错误报告加回到failure_queue中,并再次发送给Monitor。
- Monitor统计下线OSD
- Monitor收集来自OSD的伙伴失效报告。
- 当错误报告指向的OSD失效超过一定阈值,且有足够多的OSD报告其失效时,将该OSD下线。
8.5 Ceph心跳检测总结
Ceph通过伙伴OSD汇报失效节点和Monitor统计来自OSD的心跳两种方式判定OSD节点失效。
- 及时:伙伴OSD可以在秒级发现节点失效并汇报Monitor,并在几分钟内由Monitor将失效OSD下线。
- 适当的压力:由于有伙伴OSD汇报机制,Monitor与OSD之间的心跳统计更像是一种保险措施,因此OSD向Monitor发送心跳的间隔可以长达600秒,Monitor的检测阈值也可以长达900秒。Ceph实际上是将故障检测过程中中心节点的压力分散到所有的OSD上,以此提高中心节点Monitor的可靠性,进而提高整个集群的可扩展性。
- 容忍网络抖动:Monitor收到OSD对其伙伴OSD的汇报后,并没有马上将目标OSD下线,而是周期性的等待几个条件:
- 目标OSD的失效时间大于通过固定量osd_heartbeat_grace和历史网络条件动态确定的阈值。
- 来自不同主机的汇报达到mon_osd_min_down_reporters。
- 满足前两个条件前失效汇报没有被源OSD取消。
- 扩散:作为中心节点的Monitor并没有在更新OSDMap后尝试广播通知所有的OSD和Client,而是惰性的等待OSD和Client来获取。以此来减少Monitor压力并简化交互逻辑。
9.1 QOS介绍
QoS (Quality of Service,服务质量)起源于网络技术,它用来解决网络延迟和阻塞等问题,能够为指定的网络通信提供更好的服务能力。
问题: 我们总的Ceph集群的IO能力是有限的,比如带宽,IOPS。如何避免用户争取资源,如何保证集群所有用户资源的高可用性,以及如何保证高优用户资源的可用性。所以我们需要把有限的IO能力合理分配。
9.2 Ceph IO操作类型
- ClientOp:来自客户端的读写I/O请求。
- SubOp:osd之间的I/O请求。主要包括由客户端I/O产生的副本间数据读写请求,以及由数据同步、数据扫描、负载均衡等引起的I/O请求。
- SnapTrim:快照数据删除。从客户端发送快照删除命令后,删除相关元数据便直接返回,之后由后台线程删除真实的快照数据。通过控制snaptrim的速率间接控制删除速率。
- Scrub:用于发现对象的静默数据错误,扫描元数据的Scrub和对象整体扫描的deep Scrub。
- Recovery:数据恢复和迁移。集群扩/缩容、osd失效/从新加入等过程。
9.3 Ceph 官方QOS原理
mClock是一种基于时间标签的I/O调度算法,最先被Vmware提出来的用于集中式管理的存储系统。(目前官方QOS模块属于半成品),基本思想:
- reservation 预留,表示客户端获得的最低I/O资源。
- weight 权重,表示客户端所占共享I/O资源的比重。
- limit 上限,表示客户端可获得的最高I/O资源。
9.4 定制化QOS原理
9.4.1 令牌桶算法介绍
基于令牌桶算法(TokenBucket)实现了一套简单有效的qos功能,满足了云平台用户的核心需求,基本思想如下:
- 按特定的速率向令牌桶投放令牌。
- 根据预设的匹配规则先对报文进行分类,不符合匹配规则的报文不需要经过令牌桶的处理,直接发送。 - 符合匹配规则的报文,则需要令牌桶进行处理。当桶中有足够的令牌则报文可以被继续发送下去,同时令牌桶中的令牌量按报文的长度做相应的减少。
- 当令牌桶中的令牌不足时,报文将不能被发送,只有等到桶中生成了新的令牌,报文才可以发送。这就可以限制报文的流量只能是小于等于令牌生成的速度,达到限制流量的目的。
9.4.2 RBD令牌桶算法流程
步骤:
- 用户发起请求异步IO到达Image中。
- 请求到达ImageRequestWQ队列中。
- 在ImageRequestWQ出队列的时候加入令牌桶算法TokenBucket。
- 通过令牌桶算法进行限速,然后发送给ImageRequest进行处理。
9.4.3 RBD令牌桶算法框架图
现有框架图:
令牌图算法框架图: