ceph 简介
什么是 Ceph?
-
Ceph 是一种为优秀的性能、可靠性和可扩展性而设计的
统一的
、分布式
的存储系统。-
统一的
: 意味着 Ceph 可以一套存储系统同时提供对象存储
、块存储
和文件系统
存储三种功能,以便在满足不同应用需求的前提下简化部署和运维。 -
分布式
: 在 Ceph 系统中则意味着真正的无中心结构
和没有理论上限的系统规模可扩展性
。
-
为什么要关注 Ceph?
- Ceph 本身确实具有较为突出的优势。其先进的核心设计思想,概括为八个字
“无需查表,算算就好”
。
ceph 架构
ceph 系统 自下向上 可以分为四个层次:
基础存储系统
RADOS
(Reliable, Autonomic, Distributed
Object
Store
,即可靠的、自动化的、分布式的对象存储)基础库
LIBRADOS
-
高层应用接口
-
rgw
(RADOS Gateway) -
RBD
(Rados Block Device) -
CephFS
(Ceph File System)
-
应用层
rados
Ceph 的存储集群(Storage Cluster),又称为 RADOS(Reliable, Autonomic Distributed Object Store),顾名思义,它提供了一個可靠、能自我管理的分布式对象存储。RADOS 是 Ceph 存储系统的核心。Ceph 的数据访问方法(如 RBD、CephFS、RADOSGW、librados)的所有操作都是在 RADOS 层之上构建的。当 Ceph 集群接收到来自客户端的写请求时,CRUSH算法首先计算出存储位置,然后这些信息传递到 RADOS 层进行进一步处理。RADOS 以小对象的形式将数据分发到集群内的所有节点,最后将这些对象存储在 OSD 中。当配置的复制数大于 1 时,RADOS 负责数据的可靠性,它复制对象,创建副本并将它们存储在不同的故障区域中。 RADOS 包含两个核心组件:OSD
和 MON
。
Ceph Monitor
-
Ceph monitor 维护
cluster map
的"主副本"。这意味着,Ceph 客户端只需连接一个 Ceph monitor 并检索当前的 cluster map,便可确定所有 Ceph monitor 和 Ceph OSD 的位置,即获得全局系统状态记录的数据结构
。cluster map 主要包含 5 个方面的信息:- mon map
ceph mon dump
- osd map
ceph osd dump
- pg map
ceph pg dump
- crush map
ceph osd crush dump
ceph osd getcrushmap -o {filename}
-
crushtool -
d
{comp-crushmap-filename} -
o
{decomp-crushmap-filename}
- mds map
ceph fs dump
- mon map
Ceph 客户端必须先连接 Ceph monitor,然后才能从 Ceph OSD 读取或写入 Ceph OSD。利用 cluster map 的当前副本和 CRUSH 算法,Ceph 客户端可以计算任何对象的位置。计算对象位置的能力使得 Ceph 客户端能够直接与 Ceph OSD 通信,这是 Ceph 高可扩展性和性能的一个重要方面。
Ceph monitor 也提供身份验证和日志记录服务。Ceph monitor 将 monitor 服务中的所有更改写入到单个 Paxos 实例,而
Paxos
将更改写入到 KV 存储,以获得强一致性
。Monitor 之间同步可参考: MONITOR STORE SYNCHRONIZATION
Ceph OSD
OSD 是 Ceph 存储集群中最重要的一个基础组件,它负责将实际的数据以对象的形式存储在每一个集群节点的物理磁盘中。对于任何读写操作,客户端首先向 MON 请求 cluster map,然后客户端就可以直接和 OSD 进行 I/O 操作。
一个 Ceph 集群包含多个 OSD。一个典型的 Ceph 集群部署方案会为集群节点上的每个物理磁盘创建一个 OSD daemon,这是推荐的做法。以多副本为例,OSD 上的每个对象都有一个主副本和几个辅副本,辅副本分散在其他 OSD。一个 OSD 对于一些对象是主副本,同时对于其他对象可能是辅副本,存放辅副本的 OSD 受主副本 OSD 控制,如果主副本OSD 异常(或者对应的磁盘故障),辅副本 OSD 可以成为主副本 OSD。
osd 会检查自身的状态以及其他 osd 的状态,并向 monitor 汇报。
ceph pool
Ceph pool 是一个用来存储对象的逻辑分区,每个池都包含一定数量的 PG,进而实现把一定数量的对象映射到集群内部不同 OSD 上的目的。 Ceph pool 还支持快照功能,以及为对象设置所有者和访问权限。
RBD
RBD 对外提供块存储,可以被映射、格式化,进而像其他磁盘一样挂载到服务器。
RGW/RADOSGW
RGW,Ceph 对象网关,也称做 RADOS 网关,它是一个代理,可以将 HTTP 请求转换为 RADOS,也可以把 RADOS 转换为 HTTP 请求,从而提供 restful 接口,兼容 S3 和 Swift。Ceph 对象网关使用 Ceph对象网关守护进程(RGW)与 librgw、librados 交互。
Ceph Manager
Ceph 管理器软件,可以收集整个集群的所有状态。包括 dashboard, prometheus 等等。
Ceph Metadata Server
MDS 是 Ceph 文件系统的元数据服务器,跟踪文件层次结构并存储元数据。只有 CephFS 才需要。
CephFS 在 RADOS 层之上提供了一个兼容 POSIX
的文件系统。它使用 MDS
作为守护进程,负责管理其元数据并将它和其他数据分开。CephFS 使用 cephfuse 模块(FUSE
)扩展其在用户空间文件系统方面的支持(就是将 CephFS 挂载到客户端机器上)。它还允许直接与应用程序交互,使用 libcephfs 库直接访问 RADOS 集群。
Ceph 寻址流程
三次映射
- File -> Object -> PG -> OSD
基本概念
File —— 此处的 file 就是用户需要存储或者访问的文件。对于一个基于 Ceph 开发的对象存储应用而言,这个 file 也就对应于应用中的 “对象”,也就是用户直接操作的 “对象”。
Object —— 此处的 object 是 RADOS 所看到的“对象”。Object 与上面提到的 file 的区别是,object 的最大 size 由 RADOS 限定(通常为 2MB 或 4MB),以便实现底层存储的组织管理。因此,当上层应用向 RADOS 存入 size 很大的 file 时,需要将 file 切分成统一大小的一系列 object(最后一个的大小可以不同)进行存储。
PG(Placement Group)—— 顾名思义,PG 的用途是对 object 的存储进行组织和位置映射。具体而言,一个 PG 负责组织若干个 object(可以成千上万个甚至更多),但一个 object 只能被映射到一个PG中,即,PG 和 object 之间是“一对多”
映射关系。同时,一个 PG 会被映射到多个 OSD 上,而每个 OSD 上都会承载大量的 PG,即,PG 和 OSD 之间是“多对多”
映射关系。在实践当中,n 至少为 2,如果用于生产环境,则至少为 3(对于副本池而言)。一个 OSD 上的 PG 则可达到数百个。事实上,PG 数量的设置牵扯到数据分布的均匀性问题。PG 里的一些概念可参考: PLACEMENT GROUP CONCEPTS
为什么要引入 PG?
- PG 相当于一个虚拟组件,出于集群伸缩,性能方面的考虑。
- 如果没有 PG,则 object 直接映射到 osd 上,百万千万级别甚至更多的对象管理和追踪起来会很困难。因为正常情况下,osd 数量固定的情况下,PG 数量也是固定的(2 的整数次幂,有专门的计算公式)。记录每个 OSD 承载了哪些 PG 是可行的,而且其变化不频繁,开销小。 在 OSD 故障后,很容易获得 OSD 承载的 PG 列表,并计算出各个 PG 的另外几个副本在哪个 OSD。有了这些信息,才具备了故障处理的可行性。
File -> object 映射
这次映射的目的是,将用户要操作的 file,映射为 RADOS 能够处理的 object。其映射十分简单,本质上就是按照 object 的最大 size 对 file 进行切分。这种切分的好处:
- 让大小不限的 file 变成最大 size 一致、可以被 RADOS 高效管理的 object;
- 让对单一 file 实施的串行处理变为对多个 object 实施的并行化处理。
object 有自己的 ID,二进制数据以及由键值对组成的元数据信息。且 ID 是集群唯一的。
Object -> PG 映射
在 file 被映射为一个或多个 object 之后,就需要将每个 object 独立地映射到一个 PG 中去。计算公式: hash(oid) & mask -> pgid 根据 RADOS 的设计,给定 PG 的总数为 m(m 应该为 2 的整数幂),则 mask 的值为 m-1。因此,哈希值计算和按位与操作的整体结果事实上是从所有 m 个 PG 中近似均匀地随机选择一个。基于这一机制,当有大量 object 和大量 PG 时,RADOS 能够保证 object 和 PG 之间的近似均匀映射。具体可以参考:CALCULATING PG IDS
PG -> OSD 映射
第三次映射就是将作为 object 的逻辑组织单元的 PG 映射到数据的实际存储单元 OSD。如前面图所示,RADOS 采用一个名为 CRUSH 的算法,将 pgid 代入其中,然后得到一组共 n 个 OSD。这 n 个 OSD 即共同负责存储和维护一个 PG 中的所有 object。前已述及,n 的数值可以根据实际应用中对于可靠性的需求而配置,在生产环境下通常为 3。具体到每个 OSD,则由其上运行的 OSD deamon 负责执行映射到本地的 object 在本地文件系统中的存储、访问、元数据维护等操作。 需要注意的是,PG -> OSD 映射
和 “
object
-> PG”
映射中采用的哈希算法不同,这个 CRUSH 算法的结果不是绝对不变的,而是受到其他因素的影响。其影响因素主要有:
- 一是当前系统状态,也就是
cluster map
。当系统中的 OSD 状态、数量发生变化时,cluster map 可能发生变化,而这种变化将会影响到 PG 与 OSD 之间的映射。 - 二是存储策略配置。这里的策略主要与安全相关。利用策略配置,系统管理员可以指定承载同一个 PG 的 3 个 OSD 分别位于数据中心的不同服务器乃至机架上,从而进一步改善存储的可靠性。
数据操作流程
以 file 写入过程为例
当某个 client 需要向 Ceph 集群写入一个 file 时,首先需要在本地完成寻址流程,将 file 变为一个 object,然后找出存储该 object 的一组三个 OSD。 找出三个 OSD 后,client 将直接和 Primary OSD 通信,发起写入操作(步骤1)。Primary OSD 收到请求后,分别向 Secondary OSD 和 Tertiary OSD 发起写入操作(步骤2、3)。当 Secondary OSD 和 Tertiary OSD 各自完成写入操作后,将分别向 Primary OSD 发送确认信息(步骤4、5)。当 Primary OSD 确信其他两个 OSD 的写入完成后,则自己也完成数据写入,并向 client 确认 object 写入操作完成(步骤6)。
集群维护
由若干个 monitor 共同负责整个 Ceph 集群中所有 OSD 状态的发现与记录,并且共同形成 cluster map 的 master 版本,然后扩散至全体 OSD 以及 client。OSD 使用 cluster map 进行数据的维护,而 client 使用 cluster map 进行数据的寻址。 monitor 并不主动轮询各个 OSD 的当前状态。正相反,OSD 需要向 monitor 上报状态信息。常见的上报有两种情况:一是新的OSD被加入集群,二是某个 OSD 发现自身或者其他 OSD 发生异常。在收到这些上报信息后,monitor 将更新 cluster map 信息并加以扩散。
Cluster map 的内容
- Epoch,即版本号,为一个单调递增序列,Epoch 越大,则 cluster map 版本越新。
- 各个 OSD 的网络地址。
- 各个 OSD 的状态。up 或者 down,表明 OSD 是否正常工作;in 或者 out,表明 OSD 是否在至少一个 PG 中。
- CRUSH 算法配置参数。表明了 Ceph 集群的物理层级关系(cluster hierarchy),位置映射规则(placement rules)。
osd 状态:
状态 | Up | Down |
---|---|---|
In | 正常运行,且承载至少一个 PG 的数据(标准工作状态 | 发生异常,但仍然承载至少一个 PG 的数据(刚发生异常) |
out | 正常运行,未承载任何 PG(新加入或故障修复重新加入的 OSD) | 彻底发生故障,不再承载任何 PG |
CEPH 重新平衡和恢复
当有新的 osd 加入集群或者移除了 osd,就会把状态上报给 Monitor,Monitor 知道了 osd map 发生了变化就会触发 rebalancing
,确保 pg 能够平滑的移动到各个 osd 上。以 pg 为整体进行数据重平衡,重平衡的过程中可能会影响性能。一次性加入的 osd 越多,数据 rebalancing 就越频繁,业务也可能因此受到影响。生产环境中,强烈建议一次只添加一个 osd,最大限度的减少性能和业务的影响。
新增一个 OSD
首先根据配置信息与 monitor 通信,monitor 将其加入 cluster map,并设置为 up 且 out 状态,再将最新版本的cluster map 发给这个新 OSD。
自动化的故障恢复(Failure recovery)
收到 monitor 发过来的 cluster map 之后,这个新 OSD 计算出自己所承载的 PG 以及和自己承载同一个 PG 的其他 OSD。然后与这些 OSD 取得联系。如果这个 PG 目前处于降级状态(即承载该 PG 的 OSD 个数少于正常值),则其他 OSD 将把这个 PG 内的所有对象和元数据赋值给新 OSD。数据复制完成后,新 OSD 被置为 up 且 in 状态,cluster map 也更新。
自动化的故障探测(Failure detection)过程
如果一个 OSD 发现和自己共同承担一个 PG 的另一个 OSD 无法联通,则会将这一情况上报 monitor。此外,如果一个 OSD deamon 发现自身工作状态异常,也将把异常情况主动上报给 monitor。此时,monitor 将把出现问题的 OSD 的状态设置为 down 且 in。如果超过某一预定时间期限该 OSD 仍然无法恢复正常,则其状态将被设置为 down 且 out。如果该 OSD 能够恢复正常,则其状态会恢复成 up 且 in。具体可以参考: CONFIGURING MONITOR/OSD INTERACTION
数据一致性检查
ceph 会定期去检查指定冗余副本数的数据是否一致。分两种情况检查:
scrub
比较轻量级的检查,主要检查元数据(metadata )信息,比如文件名、object属性、大小等,如果不一样,就会从主 pg 复制一份过去。一般每天都会检查。
deeper scrubbing
深度一致性检查,主要对比数据内容。数据量比较大的时候,这个检查相对来说比较耗费资源。一般每周检查。
参考链接
- ceph architecture
- Ceph PGs