Quantcast
Channel: Ceph –麦子迈

解析Ceph: 恢复与数据一致性

$
0
0

0529225621_0

作为一个面向大规模的分布式存储系统,故障处理是作为一个常态异常处理。Ceph 为了细化和保证故障发生和故障恢复的集群高可用性和一致性,在设计上将故障分为两类:

  1. 临时性故障: 主机升级维护,重启,掉电等等在一定时间内可以重新上线 OSD 的故障
  2. 永久性故障: 作为强一致存储系统,状态只跟存储在持久设备的数据有关,因此这类故障主要就是盘损坏或者主机损坏并无法及时转移盘到另外主机。换句话说救是一定时间内无法将原来的 OSD 数据重新加入集群。

Ceph 将所有数据域划分成若干个 PG(Placement Group)管理,每个 PG 都存活在一个 OSD 节点上,因此 PG 是管理、恢复数据的主体。而 Monitor 节点不参与用户数据的任何操作,只提供了 PG 选举的协调作用。PG 所属数据的处理和恢复都由 PG 本身进行协调。

临时性故障

首先这里考虑临时性故障的处理,Ceph 引入了 PGLog 的概念,顾名思义,PGLog 由 PG 维护并且记录了该 PG 所有的操作,其非常类似于关系型数据库领域的 undo log,同时需要将 PGLog 与 Journal 概念划分清楚,Journal 是底层单机存储模块用来维护事务一致性的,它是数据库领域的 redo log。undo log 和 redo log 在数据库的作用与 Ceph 的 PGLog 和 Journal 作用是一致的。PGLog 通常只保存 PG 最近几千条的操作记录,但是在 PG 处于 Degraded 状态时,PGLog 会保存更多的日志条目期望能在故障 PG 重新上线后用来恢复数据。下面来简单描述故障发生导致 OSD 下线的流程:

  1. 某一个 OSD 下线
  2. 如果 OSD 主动下线它会通知 Monitor 自己下线,请做好相关通知工作。如果是异常下线,那么其他 OSD 和 Monitor 会通过 Heartbeat 来得知 OSD 下线同样让 Monitor 知晓
  3. Monitor 重新计算该 OSD 拥有的的 Primary PG,并将结果主动通知这些 PG 所在的 OSD
  4. PG 将自己设为 Degraded 状态后,将会减小自己的副本数,并增加保存的 PGLog 条目数

故障发生后,如果一定时间后重新上线故障 OSD,那么 PG 会进行以下流程:

1. 故障 OSD 上线,通知 Monitor 并注册,该 OSD 在上线前会读取存在持久设备的 PGLog,
2. Monitor 得知该 OSD 的旧有 id,因此会继续使用以前的 PG 分配,之前该 OSD 下线造成的 Degraded PG 会被通知该 OSD 已重新加入
3. 这时候分为两种情况,注意这个情况下 PG 会标志自己为 Peering 状态并暂时停止处理请求:
    3.1 第一种情况是故障 OSD 所拥有的 Primary PG
    3.1.1 它作为这部分数据"权责"主体,需要发送查询 PG 元数据请求给所有属于该 PG 的 Replicate 角色节点。
    3.1.2 该 PG 的 Replicate 角色节点实际上在故障 OSD 下线时期间成为了 Primary 角色并维护了“权威”的 PGLog,该 PG 在得到故障 OSD 的 Primary PG 的查询请求后会发送回应
    3.1.3 Primary PG 通过对比 Replicate PG 发送的元数据和 PG 版本信息后发现处于落后状态,因此它会合并得到的 PGLog并建立“权威” PGLog,同时会建立 missing 列表来标记过时数据
    3.1.4 Primary PG 在完成“权威” PGLog 的建立后就可以标志自己处于 Active 状态
    
    3.2 第二种情况是故障 OSD 所拥有的 Replicate PG
    3.2.1 这时上线后故障 OSD 的 Replicate PG 会得到 Primary PG 的查询请求,发送自己这份“过时”的元数据和 PGLog
    3.2.2 Primary PG 对比数据后发现该 PG 落后并且过时,比通过 PGLog 建立了 missing 列表
    3.2.3 Primary PG 标记自己处于 Active 状态
4. PG 开始接受 IO 请求,但是 PG 所属的故障节点仍存在过时数据,故障节点的 Primary PG 会发起 Pull 请求从 Replicate 节点获得最新数据,Replicate PG 会得到其他 OSD 节点上的 Primary PG 的 Push 请求来恢复数据
5. 恢复完成后标记自己 Clean

第三步是 PG 唯一不处理请求的阶段,它通常会在 1s 内完成来减少不可用时间。但是这里仍然有其他问题,比如在恢复期间故障 OSD 会维护 missing 列表,如果 IO 正好是处于 missing 列表的数据,那么 PG 会进行恢复数据的“插队”操作,主动将该 IO 涉及的数据从 Replicate PG 拉过来,提前恢复该部分数据。这个情况造成的延迟大概在几十毫米,通常来说是可接受的。

永久性故障

上面的流程的前提故障 OSD 在 PGLog 保存的最大条目数以内加入集群都会利用 PGLog 恢复,那么如果在 N 天之后或者发生了永久故障需要新盘加入集群时,PGLog 就无法起到恢复数据的作用,这时候就需要 backfill(全量拷贝) 流程介入。backfill 会将所有数据复制到新上线的 PG,这里的流程跟上述过程基本一致,唯一的差异就是在第三步 Primary PG 发现 PGLog 已经不足以恢复数据时,这时候同样分为两种情况:

  1. 故障 OSD 拥有 Primary PG,该 PG 在对比 PGLog 后发现需要全量拷贝数据,那么毫无疑问 Primary PG 在复制期间已经无法处理请求,它会发送一个特殊请求给 Monitor 告知自己需要全量复制,需要将 Replicate PG 临时性提升为 Primary,等到自己完成了复制过程才会重新接管 Primary 角色
  2. 故障 OSD 拥有 Replicate PG,该 PG 的 Primary 角色会发起 backfill 流程向该 PG 复制数据,由于故障 OSD 是 Replicate 角色,因此不影响正常 IO 的处理

除此之外,恢复数据还需要涉及到恢复数据的带宽控制、优先级等细节问题,这里就不一一赘述了。

小结

总的来说,Ceph 的恢复模块设计原则是在保证数据强一致性的前提下,尽量细化恢复过程来提高数据可用性(请求能得到及时处理),这个细化过程势必带来了极大的复杂性,因此恢复模块实际上也是 Ceph 最复杂的设计之一,值得存储系统领域的开发者借鉴。


解析Ceph: 数据的端到端正确性和 Scrub 机制

$
0
0

1911482

来自How to Prevent Silent Data Corruption

Ceph 的主要一大特点是强一致性,这里主要指端到端的一致性。众所周知,传统存储路径上从应用层到内核的文件系统、通用块层、SCSI层到最后的HBA和磁盘控制器,每层都有发生错误的可能性,因此传统的端到端解决方案会以数据块校验为主来解决(这方面的讨论可以参考SCSI中端到端校验能解决数据完整性问题吗)。而在 Ceph 方面,更是加入了 Ceph 自己的客户端和网络、存储逻辑、数据迁移,势必导致更高的错误概率。

因为 Ceph 作为一个应用层的路径,它利用了 POSIX 接口进行存储并支持 Parity Read/Write,这时候如果封装固定数据块并且加入校验数据会导致较严重的性能问题,因此 Ceph 在这方面只是引入 Scrub 机制(Read Verify)来保证数据的正确性。

简单来说,Ceph 的 OSD 会定时启动 Scrub 线程来扫描部分对象,通过与其他副本进行对比来发现是否一致,如果存在不一致的情况,Ceph 会抛出这个异常交给用户去解决。

Scrub 流程

/*
 * Chunky scrub scrubs objects one chunk at a time with writes blocked for that
 * chunk.
 *
 * The object store is partitioned into chunks which end on hash boundaries. For
 * each chunk, the following logic is performed:
 *
 *  (1) Block writes on the chunk
 *  (2) Request maps from replicas
 *  (3) Wait for pushes to be applied (after recovery)
 *  (4) Wait for writes to flush on the chunk
 *  (5) Wait for maps from replicas
 *  (6) Compare / repair all scrub maps
 *
 * This logic is encoded in the very linear state machine:
 *
 *           +------------------+
 *  _________v__________        |
 * |                    |       |
 * |      INACTIVE      |       |
 * |____________________|       |
 *           |                  |
 *           |   +----------+   |
 *  _________v___v______    |   |
 * |                    |   |   |
 * |      NEW_CHUNK     |   |   |
 * |____________________|   |   |
 *           |              |   |
 *  _________v__________    |   |
 * |                    |   |   |
 * |     WAIT_PUSHES    |   |   |
 * |____________________|   |   |
 *           |              |   |
 *  _________v__________    |   |
 * |                    |   |   |
 * |  WAIT_LAST_UPDATE  |   |   |
 * |____________________|   |   |
 *           |              |   |
 *  _________v__________    |   |
 * |                    |   |   |
 * |      BUILD_MAP     |   |   |
 * |____________________|   |   |
 *           |              |   |
 *  _________v__________    |   |
 * |                    |   |   |
 * |    WAIT_REPLICAS   |   |   |
 * |____________________|   |   |
 *           |              |   |
 *  _________v__________    |   |
 * |                    |   |   |
 * |    COMPARE_MAPS    |   |   |
 * |____________________|   |   |
 *           |   |          |   |
 *           |   +----------+   |
 *  _________v__________        |
 * |                    |       |
 * |       FINISH       |       |
 * |____________________|       |
 *           |                  |
 *           +------------------+
 *
 * The primary determines the last update from the subset by walking the log. If
 * it sees a log entry pertaining to a file in the chunk, it tells the replicas
 * to wait until that update is applied before building a scrub map. Both the
 * primary and replicas will wait for any active pushes to be applied.
 *
 * In contrast to classic_scrub, chunky_scrub is entirely handled by scrub_wq.
 *
 * scrubber.state encodes the current state of the scrub (refer to state diagram
 * for details).
 */

Ceph 的 PG.cc 源文件中的 ASCII 流程描述已经非常形象了,这里只简述内容和补充部分信息。

  1. OSD 会以 PG 为粒度触发 Scrub 流程,触发的频率可以通过选项指定,而一个 PG 的 Scrub 启动都是由该 PG 的 Master 角色所在 OSD 启动
  2. 一个 PG 在普通的环境下会包含几千个到数十万个不等的对象,因为 Scrub 流程需要提取对象的校验信息然后跟其他副本的校验信息对比,这期间被校验对象的数据是不能被修改的。因此一个 PG 的 Scrub 流程每次会启动小部分的对象校验,Ceph 会以每个对象名的哈希值的部分作为提取因子,每次启动对象校验会找到符合本次哈希值的对象,然后进行比较。这也是 Ceph 称其为 Chunky Scrub 的原因。
  3. 在找到待校验对象集后,发起者需要发出请求来锁定其他副本的这部分对象集。因为每个对象的 master 和 replicate 节点在实际写入到底层存储引擎的时间会出现一定的差异。这时候,待校验对象集的发起者会附带一个版本发送给其他副本,直到这些副本节点与主节点同步到相同版本。
  4. 在确定待校验对象集在不同节点都处于相同版本后,发起者会要求所有节点都开始计算这个对象集的校验信息并反馈给发起者。
  5. 该校验信息包括每个对象的元信息如大小、扩展属性的所有键和历史版本信息等等,在 Ceph 中被称为 ScrubMap。
  6. 发起者会比较多个 ScrubMap并发现不一致的对象,不一致对象会被收集最后发送给 Monitor,最后用户可以通过 Monitor 了解 Scrub 的结果信息

用户在发现出现不一致的对象后,可以通过 “ceph pg repair [pg_id]” 的方式来启动修复进程,目前的修复仅仅会将主节点的对象全量复制到副本节点,因此目前要求用户手工确认主节点的对象是”正确副本”。另外,Ceph 允许 Deep Scrub 模式来全量比较对象信息来期望发现 Ceph 本身或者文件系统问题,这通常会带来较大的 IO 负担,因此在实际生产环境中很难达到预期效果。

Scrub 问题

正如流程所述,目前的 Scrub 有以下问题:

  1. 在发现不一致对象后,缺少策略来自动矫正错误,比如如果多数副本达成一致,那么少数副本对象会被同化
  2. Scrub 机制并不能及时解决存储系统端到端正确的问题,很有可能上层应用早已经读到错误数据

对于第一个问题,目前 Ceph 已经有 Blueprint 来加强 Scrub 的修复能力,用户启动 Repair 时会启动多数副本一致的策略来替代目前的主副本同步策略。

对于第二个问题,传统端到端解决方案会更多采用固定数据块附加校验数据的“端到端校验”方案,但是 Ceph 因为并不是存储设备空间实际的管理和分配者,它依赖于文件系统来实现存储空间的管理,如果采用对象校验的方式会严重损耗性能。因此在从文件系统到设备的校验需要依赖于文件系统,而 Ceph 包括客户端和服务器端的对象正确性校验只能更多的依赖于 Read Verify 机制,在涉及数据迁移时需要同步的比较不同副本对象的信息来保证正确性。目前的异步方式会允许期间发生错误数据返回的可能性。

解析Ceph: 网络层的处理

$
0
0

在现在的网络编程实现中,大多数项目都会采用基于事件通知的异步网络 IO 方式来实现。目前无论是 Epoll 还是 Kqueue 都已经成为主流网络编程知识,本文就不介绍这些基本概念和使用了。主要围绕目前 Ceph 的网络层实现来解构和探讨如何重构。

总体设计

在 Ceph 项目伊始的 06 年,那时候在网络编程还是线程模型当道的年头,Ceph 采用了简单粗暴的采用了每两个线程对应一个终端的方式,其中一个用于监听和读取该终端的读事件,另一个用于写事件。我们可以简单称这两个线程为一条连接的读线程和写线程。读线程得到请求以后会解析网络流并开始构建消息,然后派发到后面的 Dispatcher。写线程在大部分时候会处于 Sleep 状态,直到有新的消息需要发送才会被唤醒。

Ceph 在目前的网络层面上有三个重要概念,分别是 Messenger,Pipe,Connection。Messenger 实际上可以理解为一个监听地址和多个连接的集合。比如每个 OSD 中会有 cluster_messenger 和 public_messenger,顾名思义 cluster_messenger 负责给 OSD 与其他 OSD 和 Monitor 的通信并提供了一个监听地址,public_messenger 负责与客户端的通信并提供了一个面向客户端的监听地址。因此 cluster_messenger 中负责的连接会全部是面向其他 OSD 或者 Monitor 的连接。Pipe 实际上是一个 Session 的载体,为了解决网络连接不稳定或者临时闪断连接的问题,Pipe 会一直维护面向一个终端地址的会话状态,如类似 TCP 包序号的消息序号和发送队列。Connection 就是一个 socket 的 wrapper,它从属于某一个 Pipe。

一个会话的逻辑

QQ20140930-1

上图主要聚焦 OSD 端的网络逻辑,客户端实际上是一模一样的网络实现只是不会拥有一个监听端口。网络上层的业务实际上只需要关注一个逻辑上的持久会话,通过 Dispatcher 得到消息处理,然后通过 Connection 接口把消息放到发送队列发送。

QQ20140930-2

上面这个图主要描述了一个会话建立的流程,其中 banner 类似于一个宣告,然后互相了解对方的地址信息。主要逻辑在于 connection message 中的信息,服务器端会校验这些连接信息并确保面向这个地址的连接只有一条,如果 client 发送了一个已经建立会话的地址,服务器端会考虑是否需要替换或者废弃当前连接。另外在这里会需要确定是否要发送验证信息(图中省略)。在会话成功后,实际上就对双方当前的 Pipe 状态达成了一致。

线程问题

实际上我们从中很容易发现这个线程模型是存在重大问题的,也就是随着一个实体(如 OSD)的增加会线性增加一个实体的线程数目。线程的增加会导致严重的 Context Switch 损耗,线程级的 Context Switch 大概在 us 级别,会影响延迟敏感性应用的性能并且对系统造成资源压力。

因此,在去年 Accelio 提交了基于开源的一个 RPC 库的高性能的 Ceph 网络层实现,另外,作者也在上个月完成了一个基于事件通知的异步 Messenger 实现,主要将之前同步的 SimpleMessenger 改造成状态机并且实现了一个简单的事件管理器。相对于 accelio 的实现,本人的实现希望避免引入一个巨大的 RPC 库造成诸多不便,会大大限制 Ceph 在网络层实现上的范围,也可能会引来第三方库使用的问题。而实际上 Ceph 只需要一个简单的事件管理器即可高效的达到目的。

解析Ceph: Librbd 的克隆问题

$
0
0

在较早的文章就指出 Librbd 在卷的克隆时会形成子卷对父卷的依赖,在产生较长的克隆依赖链后会有严重的性能损耗。OpenStack Cinder 会有一个选项专门用来 flatten 这种较长依赖链,在超过阀值后选择强制 flatten。本篇文章主要会阐述这种依赖的问题和根源,并且给出目前的解决方案。

QQ20130715-13

卷的克隆

在 Librbd 中,每个卷实际上是由一个 metadata object 进行维护并管理卷元数据和一对 data objects 构成。普通的读写 IO 不会修改 metadata object 而只会修改 data objects,且 metadata object 不含有 data objects 的任意信息,只有针对卷的操作如创建快照、克隆、修改大小等重量级操作才会修改 metadata object(每个客户端会维持一个 refresh id,当发生这种重量操作时,通过 Ceph Notification 机制可以通知所有该卷的客户端需要重新获取最新的 metadata object)。这样的好处是,在正常读写 IO 逻辑下,客户端是不需要修改 metadata object,这样就可以将 metadata object 看成是只读信息。多个客户端就可以同时对一个卷进行 IO 读写,因为 data object 在 OSD 端是线性化的。

而克隆操作本质上复制了一个 metadata object,并且链接向父卷,而 data objects 是不存在的。因此在每次读操作时会先向本卷可能的 data object 访问。在返回对象不存在错误后会向父卷访问对应的对象最终决定这块数据是否存在。因此当存在多个层级的克隆链后,读操作需要更多的损耗去读上级卷的 data objects。只有当本卷的 data object 存在后(也就是写操作后),才不需要访问上级卷。

卷索引表

因此,自然而然我们就需要解决这个问题,就是为每个卷创建一个索引来避免额外的父卷读取操作。在 Ceph Giant 版本的 CDS 上就提出了这个 BP (https://wiki.ceph.com/Planning/Blueprints/Hammer/librbd%3A_shared_flag%2C_object_map)。主要有两种实现思路:

  1. 索引数据是不可靠的: 只允许一个客户端操作一个卷,索引数据在内存中更新并且阶段性持久化。这样的好处是最大程度减少正常读写 IO 额外损耗,但是会在客户端 Crash 后造成索引数据丢失。因此客户端需要假设持久化的索引是不可靠的,并且在实际的 IO 操作后”训练”索引
  2. 索引数据是可靠的: 在每次需要更新索引数据的 IO 操作中附加更新索引数据的 IO,因此会增加正常读写 IO 的负载,但是可以让索引数据真实可信

在上两个月,作为 BP 的作者先实现了第一个方案,在 maillist 的讨论中”惨遭”婉拒。后来因为要参与到 Messenger 的重构中,因此本来打算改成第二个方案的实现也拖后了。现在 Redhat 的 Jason 在跟我邮件沟通后毅然承担起了重新实现第二种方案的大梁,目前已在 PR list 中。

卷索引副产品

在实现卷索引后,会导致之前卷的多客户端特性遭到挑战。因此索引数据更新相对来说仍然是个比较常规的数据操作,如果依赖于 Ceph Notification 会造成严重的性能损耗,因此会使得一个卷只能被一个客户端进行读写 IO 操作。

通过卷索引后,Librbd 可以支持更强大的统计功能了,可以根据卷索引信息统计父卷和子卷的差距来有效统计子卷目前实际占用大小。

解析 Ceph: Ceph 的社区

$
0
0

hands-holding-ceph

之前这个系列的文章主要研究和讨论 Ceph 设计和实现的问题,但是一个成功的开源项目往往并不只是项目本身有很好的实现,项目的社区往往在中后期的开发和普及发挥重要作用。因此,本文要介绍 Ceph 社区本身及其开发、测试、集成的体系。

开发者

说到参与开源项目,开发者如何贡献代码往往是第一个话题。贡献者可以在文档、本地化、Ceph 核心代码、各种接口库、上下游项目对接(QEMU, Hadoop等等)来帮助 Ceph。同时跟大部分现在的开源项目类似,Ceph 的代码托管在 Github(https://github.com/ceph/ceph) 上,新手第一步需要做的就是从源码编译安装一次,对 Ceph 的代码有初步的认识。

其次,当期望向社区提交代码时,你需要阅读社区提供的提交补丁文档,其中主要介绍了在每个 commit 必须在 commit message 的末尾加上一行:

Signed-off-by: Random J Developer random@developer.example.org

然后里面详细列出了如何提交一个 commit 到社区主干的 git 命令列表,通常来说,你需要熟悉基本的 git 操作和工作流。

最后,根据提交的补丁的类型,你需要在本地跑一些单元测试,并保证 code style 的一致性。

完成 Pull Request以后,在 Github 的 Pull Request(https://github.com/ceph/ceph/pulls)页面,你会看到你提交的补丁。因为 Ceph 目前来说已经是一个比较庞大的代码组织架构,每个模块都会有负责的维护者,比如 LibRBD 模块是 Josh Durgin,RadosGateWay 是 Yehuda Sadeh等等,当有多模块交叉的补丁或者一些不太容易确定维护者的时候,Sage 一般会去 Review 和 Merge。当你提交补丁时,你最好看一下修改的源文件的变更历史的主要来源来确定这部分代码的主要维护者,这样在提交补丁以后如果并没有人来主动认领,你可以主动通过 IRC、邮件列表或者在 Github 直接询问。除此之外,每个 Pull Request 都会被打上 label 方便查看。在补丁提交后的一段时间内,会有一个测试机器人会主动拉下你的代码跑一次单元测试并把结果回复在 Pull Request 上,如果出现 Error 状态,可以通过查看错误日志来修复,当你无法正确修复问题时,同样可以找相关的维护者寻求帮助。

最后,通常在经过 1-2 个核心开发者 review 后,大部分变更都需要跑一次集成测试,目前主要是 Sage 和 Samjust 会去定期跑一次最近的变更,如果发生测试失败的情况,他们会寻找错误原因 commit。

Ceph 的贡献者情况既可以通过 Github 提供的图表来了解,也可以参考(http://metrics.ceph.com/)。

测试体系

上面提到了代码经过单元测试和基础的集成测试以后就可以进入代码主干了,但这并不是项目质量保证的终点。Ceph 社区从 N 前开始就有自己的测试服务器集群,通过这个页面(http://ceph.com/docs/master/dev/sepia/)可以了解集群概括,这个页面并不会及时更新,现在应该会拥有一批更新的服务器了。

首先,通过 Gitbuilder(http://gitbuilder.ceph.com/) 你可以发现各种机器不同体系结构和发行版的目录,这是 Ceph 的最基本的兼容性覆盖和包测试体系。进入任意一个目录如(http://gitbuilder.sepia.ceph.com/gitbuilder-ceph-tarball-trusty-i386-basic/#origin/master)都可以发现每个 Branch 的运行情况。

其次,Pulpito(http://pulpito.ceph.com/)是 Ceph 集成测试 dashboard,通过该页面可以看到最近集群在跑的集成测试集和代码分支。通过导航的不同维度可以查找相关的测试集结果。所有变更都会在这个页面跑一次基础集成测试集,然后在每次开发版发布时跑一次完整的集成测试集,在发布正式版本时会额外加入升级测试集确保集群平滑升级。Ceph QA suite包括了所有的测试用例,Teuthlogy是 Ceph 的集成测试框架,主要就是由 Teuthlogy 来驱动所有的 QA 测试用例并输出。

当你的变更出现集成测试用例无法通过时,子模块维护者通常会告诉你在 Pulpito 对应的失败用例的日志,你可以根据日志结果分析失败原因并修复。但实在无法找到原因时你或许希望得到测试集群的具体信息如数据和原始日志,这些原始数据只能通过 VPN 登入,可以在 IRC 上 ping 相关维护者来得到这些数据。

最后 Ceph 发布的大版本类似于 Ubuntu 的发布管理,每两个大版本会有一个长期维护版本(LTS),社区的测试集群会确保 LTS 版本之间的无缝升级,并且 LTS 会维护大约 2 年的时间,也就是当出现严重 bug 和漏洞时,LTS 都会得到 backport 并发布新的修复版本。

项目和进度管理

Ceph 使用了 Redmine(http://tracker.ceph.com/projects/ceph/issues) 进行 Bug & Feature 管理,用户和开发者发现的 Bug 都需要预先登记到这里,基本上每天都会有相关负责人来确认和进一步分析 Bug 记录。确认的 Bug 会在第一时间得到修复并根据影响范围决定是否 backport,用户和开发者也可以提交对 Ceph 的 feature 需求到这里,相关负责人会根据难易和需求急迫安排开发计划。

在汇报一个 Bug 时,最好详细列出出现问题的 Ceph 版本、集群概括,问题描述、相关的历史操作步骤和相关日志以及推测。

Ceph 在每次大版本开始之前都会有一个 Design Summit,会议是在线举行,在开始之前会号召大家提交 Blueprint 然后有社区管理者来根据时区调度讨论日程表。通常每次 Summit 都分为两天,第一天是偏向欧洲时区,第二天偏向亚洲时区,而美国时区往往在两天都是在合适的时间。在 (https://wiki.ceph.com/Planning/Blueprints/)你可以看到每次 Design Summit 讨论的 BP,通过链接可以直接看到 BP 描述和当时的讨论录像。

小结

通过以上简要介绍我们可以到一个开源项目需要涉及的广度与深度,这些都是需要非常多的时间的一步步构建和组织。而作为一个存储系统,可靠性和正确性是首要前提,目标是下一代存储系统的 Ceph 在整个开发和发布流程也进一步确保了其可靠的质量,这也是 Ceph 为何能吸引众多厂商甚至包括老牌存储厂商的原因之一。

解析 Ceph: FileJournal 的作用

$
0
0

很多的用户在提到 Ceph 性能的时候都会提到“写放大”这点,实际上就是 FileJournal 在起作用。只要使用默认的 FileStore,所有数据包括 metadata 都会在 FileJournal 上预写一份。那么本文就会介绍 FileJournal 在 FileStore 存储引擎上提供的作用。

作用

Snip20150215_1

FileJournal 就是数据库中常见的 WAL(Write Ahead Log) 实现,主要提供了事务的一致性和原子性。Ceph 数据访问所提供的写操作在落到 ObjectStore 时实际上会产生多个写操作,为了保证用户层面的写操作的原子性,避免 FileStore 在执行多个操作时发生意外造成中间状态而无法追溯或者回滚,我们需要引入 Journal 来作为日志。使得 OSD 进程在非正常退出后再启动可以从 Journal 中恢复之前正在执行的操作。

除此之外,FileJournal 提供了更短的写操作耗时,因为用户 IO 操作到达 FileStore 以后,只要经过 FileJournal 存储后都可以立即回复给用户,无需等待操作正常落盘。对于大量随机小写来说,这实际上能大大提高单个 OSD 的处理能力。

工作流程

如上图所示,所有 PG 层提交事务都会在 FileStore 经过一层 Throttle 直接进入 FileJournal 队列。然后有后面的不同类型线程都是单一线程,以 Pipeline 的形式最大化 FileJournal 的吞吐量。IO 从 Journal Queue 被提取后由 Write Thread 进行处理,图上只标出了 AIO,实际上如果 OS 不支持 AIO+DIO 的方式,那么就会采用 write+flush 的组合。在这里,Write Thread 会尽可能获取多的队列事务进行批量提交,每个事务都会以页对齐的方式补零后者重新编排,最后提交 IO。Write Finish Thread 实际上只在 AIO+DIO 中存在,主要是为了收割正在进行的 IO,收购后提交给 Finisher Thread。

可能的改进

日志的实现实际上并不是一个简单的话题,它的逻辑非常简单但在 IO 程序中起到非常重要的作用,也是用户写操作最重要的延时消耗者。因此如何最大化日志来提高 IO 吞吐量和延迟的讨论早存在于学术和工业届。Pipeline、减小临界区和批量提交是主要的手段,FileJournal 采用多个线程协同的方式而不是多个独立工作线程单独工作的形式,两者各有优劣。目前 FileJournal 在设计上没有太大的问题,在实现上需要更加 SMART,解决不同大小 IO size 的相互影响。除此之外,非常大或者对象存储的工作场景下,跳过 FileJournal 直接落盘是用户期待的方式,但是目前 FileJournal 与 FileStore 耦合严重,因此社区会重起一个新的 Backend 来解决这些问题。

云上的 NAS —以 CephFS 为例

$
0
0

AWS 于今日发布了其 EFSElastic File System 产品,旨在云环境中提供 NAS 服务,终于填补上了公有云领域最后一块传统存储领地。其主要提供 NFS V4 版本协议,单纯只支持 NFS V4 这个 NFS 中唯一带状态的协议然后考虑到 AWS 目前基础软件现状这点不得不让我思考 Amazon 在云存储上的深厚功底了。

众所周知,DAS、SAN 和 NAS 是传统企业存储对使用方式类型的三种区分,其中 DAS 对应于 EBS(Elastic Block System) 服务,这里的 EBS 虚指所有云厂商的块存储系统,SAN 作为 DAS 的增强在传统企业存储占据主导地位,但是在云环境中的作用并不是这么明显,因为 SAN 相对于 DAS 更多的提供了数据保护、功能增强、更强性能的作用,在云环境下这些特性往往是底层存储系统所提供并附加到虚拟卷上。因此 SAN 只剩下的集中控制器提供的共享存储功能是需要提供的。因此,在云环境下的少部分 EBS 实现会增加多 VM 挂载能力,使得 EBS 同时覆盖了 DAS 和 SAN 的使用场景。当然不同云厂商提供的 EBS 在实现和产品提供上有着巨大差异,因此在云端由 EBS 提供的虚拟卷往往需要根据云厂商本身的 EBS 实现而提供传统 SAN 所具备的能力。

那么,剩下的 NAS 作为传统企业存储的另一支柱在云环境下的展现是不可或缺的,NAS 通常以标准的文件系统协议如 NFS、CIFS 被用户访问,传统企业 NAS 如 EMC 的 Isilon, NetApp 的 FAS。在传统企业存储中 NAS 跟 SAN 同样是主要的数据存储方式,在传统 IT 迁移到云基础架构的阶段中,提供 NAS 服务是不可或缺的迁移基础之一。即使在在面向云基础架构(IAAS, PAAS)的新业务、架构下 NAS 依然有其发挥之处,通过共享目录来解决业务的并发或者控制面的数据存储,大数据场景更是云 NAS 的重要用武之处。

因此,这里会以 OpenStack 作为共享文件服务的控制层,以 Ceph 作为数据平面讲讲具体如何在云基础架构中提供 NAS 服务。

OpenStack Manila & CephFS

OpenStack Manila 项目从 13 年 8 月份开始进入社区视野,主要由 EMC、NetApp 和 IBM 的开发者驱动,是一个提供共享文件系统 API 并封装不同后端存储驱动的孵化项目。目前主要的驱动有 EMC VNX、GlusterFS、IBM GPFS、华为、NetApp 等。而 Ceph 作为目前 Cinder 项目最活跃的开源后端实现,自然希望在 Manila 上仍然提供强有力的支持,何况 CephFS 本就是 Ceph 社区寄以厚望的组件。而从共享文件服务本身考虑,一个能横向扩展的分布式存储支持是其服务本身最重要的支撑,从目前的整个分布式文件存储方案(狭义的 POSIX 兼容)上来看,CephFS 也是佼佼者之一。

ceph-arch

在 14 年初的一次 Ceph Core Standup IRC 会议上,Sage 提到在目前 RadosGW, Ceph RBD 都成功作为 OpenStack 后端存储项目支持后蒸蒸日上的情况,那么 CephFS 是不是也可以考虑进入 OpenStack 存储选项之列。当时的 Manila 已经有所耳闻,社区决定将一些目光投入 Manila。但是随着后来 Redhat 收购 Inktank 的计划,大量精力仍被放在已有成熟体系的完善上,因此暂时没有对 CephFS 与 Manila 整合的动作。从 14 年的下半年开始,本人以及另一位同事开始考虑并设计实现将 CephFS 与 Manila 整合并纳入现有云体系中。在 Redhat 收购 Ceph 后,CephFS 是最大的受益者,更多的开发者和资源投入其中。15年 2 月,Sage 重新在 Maillist 中号召 CephFS 对 Manila 的支持上,大致总结出目前潜在的四种思路:

  1. Default Driver: 使用 RBD 作为 Manila Service VM 的后端,在 VM 上启动 NFS 实例提供服务
  2. Ganesha Driver: 使用 Ganesha 将 CephFS 重新 Reexport 出去
  3. Native CephFS Driver: 在 Guest VM 上直接使用原生 CephFS Module 访问
  4. VirtFS Driver: 将 CephFS 挂载在 Host 端,VM 通过 VirtFS 访问

在 Ceph I 版的 CDS 上讨论这些思路的利弊openstack manila and ceph,毫无疑问第一种是最简单也是性能最低的思路,而第二种仅仅是将 RBD 变成 CephFS,从理论上来将可以一定程度提供更好的性能。而第三种是最直接的方式,但是在云环境下实际上是不太会允许 VM 业务网络 能够直接访问后端的存储网络的,而在 VM 上直接提供对于 CephFS 的访问也暴露了 CephFS 目前简陋的安全隔离性,因此大概也只能在内部小规模私有云中被接受。而第四种在理论上提供了最好的使用模型,完全如果 virtio-block 的模型将文件系统从 Host 上暴露给 Guest VM,利用高效的 virtio 框架作为 guest <-> host 数据传输支撑,Host 直接访问 CephFS 集群来在 Host 端通过聚集效应获得更好的性能支持。

VirtFS & 9p

我们知道 Virtio 提供了一种 Host 与 Guest 交互的 IO 框架,而目前 KVM 的块存储主要使用的就是 virtblk 进行块设备指令交互,那么 VirtFS 作为文件系统指令的交互后端是如何作为呢?

VirtFS 是 IBM 于 2010 年提交的 PaperVirtFS—A virtualization aware File System pass-through的主要成果,其主要利用 9P 作为 virtfs 的协议指令在 Host 与 VM 中交互,9p协议并不是一种面向普通文件系统场景更不是面向虚拟化设计的文件系统协议,主要以简单和面向对象为特点,而 9p 在 Linux 内核中早有相应的驱动从而可以减少客户端内核工作量,而为了支持现有 Unix/Linux 下 VFS 复杂的文件指令语意,VirtFS 专门扩展了 9p 协议使得支持扩展属性和 Linux 文件权限体系命名为 9P2000.L。而 VirtFS 目前在 Host 上的后端主要是 Local FileSystem,这时候我们既可以通过 Mount CephFS 目录到 Host 系统或者直接通过 libcephfs userspace library 来直接通过 QEMU 访问来绕过 Host Kernel。虽然目前 libcephfs 在 IO 带宽上内媲美内核实现,但是在多文件压测上仍然逊色于内核模块,而 libcephfs 理论上是能提供更完美的 IO 路径。

因此,在基于 OpenStack 的云平台下,使用 CephFS 作为共享文件服务的存储后端,利用 VirtFS 作为 Guest 到 Host 的管道我们可以拥有一个理想的 IO 路径,提供高效的性能、充分的隔离性和客户端支持。最后一步实际上是 9p 协议在 VirtFS 实现上的低效性,通过简单阅读 9p 协议和其实现,我们可以了解到 9p 作为简单文件系统协议,在 Linux 典型的 IO 场景下缺乏控制流缓存这一本质缺陷,完全不在客户端实现任何结构缓存或者类似优化机制,而 QEMU 端虽然存在一定的结构缓存,但是因为其对后端共享文件系统的未知性,依然不会缓存。因此,VirtFS 已然可以提供超过本地块设备的单文件 IO 读写性能,但在大量文件控制加数据流这一典型场景下仍存在大量问题,解决好从 Guest 到 QEMU 的 9p 协议性能问题是这一方案目前最后的一公里。参考在 CDS 这个 Topic 的讨论

最后,虽然上述主要讲述 Ceph 在文件共享服务中的情况,但是应用到其他存储后端甚至是其他 Hypervisor 依然有可参考性,比如目前火热的 Docker(这个方向是 Sage 和作者本人在今年的合作点之一)!

解析 Ceph: OSD 端操作自定义扩展

$
0
0

LibRados 是 Ceph 集群提供的基本 API 库,它封装了对象的增删改查操作,对象级快照能力,单对象的事务能力和基本的统计,池管理。实际上,在绝大多数传统应用场景下,基本的增删改查是无法实现应用需求的,比如原子计数器,复杂的条件写操作等等。大部分键值数据库实际上都会面临这个窘境,然后通过丰富 API 比如增加 CAS(Compare And Swap)方法,带一些基本条件判断的写操作。但是,应用的复杂性使得不断会有一些特殊的要求,如果只提供基本甚至丰富全面的接口不仅会增加接口复杂性,增加维护难度,并且仍然会存在缺口。Ceph 提供了基本的 CMP 接口来直接供用户使用,但是为了满足在分布式存储上构建 Data Aware 计算的需求,Ceph 提供了更加弹性的方式。

Snip20150731_1

因此,类似于 Lua 之于 Redis,Ceph 提供了动态加载二进库的方式来增加对于用户定义操作的支持,可以使用 LibRados 提供的 exec 方法来执行特定要求:

void exec(const char *cls, const char *method, bufferlist& inbl, bufferlist *obl, int *prval)

cls 是方法集合名称,method 是方法名称,inbl 和 obl 都是一个序列化参数列表,caller 和该方法实现端会自己解释该序列化字符串。

注册方法

举一个例子,比如实现一个原子计数器方法,那么用户可以定义如下的操作:

方法集合名: atomic_counter
方法名: atomic_add
方法参数(inbl):
name(计数器名字)
返回值(obl):
value(目前数值)

有了这个目标以后,可以在 ceph 的 src/cls 目录下新建一个文件为 atomic_counter/atomic_counter.cc,实现 atomic_add 方法:

static int atomic_add(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
{
  string name;
  uint64_t value;

  bufferlist::iterator iter = in->begin();
  try {
    ::decode(name, iter);
  } catch (const buffer::error &err) {
    return -EINVAL;
  }

  int r = read_key(hctx, name, &value);
  value++;

  ::encode(value, *out);
  r = cls_cxx_map_set_val(hctx, name, out);
  return 0;
}

这个方法简单实现了从参数里获得计数器名字,然后递增再存回去,将递增后的值返回给用户。然后使用 cls_register_cxx_method 注册该方法。具体例子可以参考 src/cls/hello/hello.cc 样例。

为何需要自定义操作?

实际上,看起来上面那个方法非常冗长和麻烦,远不如提供一个 Native 的计数器来的简便。但是在复杂的应用需求下,有大量复杂的逻辑可以在此实现。比如 src/cls/rbd/rbd.cc 实现了众多提供 rbd 操作的方法,比如创建快照,克隆等等。通过自定义操作可以方便的定义一个复杂的操作,并在服务器端提供全局唯一的锁操作。

当然,除了为了应付应用对于接口的需求外,更多的为了减少数据的传输量。我们知道像 Oracle 的 Exadata 就提供了在存储端进行简单计算的能力,避免造成在计算节点上数据集中造成的大量带宽和延迟。类似的,Ceph 作为一个分布式存储系统,除了标准的存储接口如 POSIX,块接口和对象接口外,LibRados 提供的接口语意和可扩展方法使得一个依赖于 Ceph 的分布式应用变得更加高效。比如一个分布式的日志系统ZLOG,所有的日志数据存储在 Ceph 集群里,这时候我们需要对日志做基本的搜索,这时候如果我们在应用层构建搜索逻辑,实际上就需要把所有的 Ceph 数据导入到计算节点进行处理,而利用扩展的操作就使得在存储节点上进行计算。

我们通用可以参考社区用户的一个例子,直接在扩展中封装了 LUA 解释器DYNAMIC OBJECTS IN LUA! 客户端可以直接发送 LUA 代码给 OSD,然后在 OSD 执行 LUA 代码。


解析 Ceph: CephFS 进展

$
0
0

CephFS 一直是 Ceph 开发者心头的一块重地,不管是从 Ceph 项目伊始就是为了分布式文件系统打造,还是到现在一个严格意义的 POSIX 接口实现的分布式 NAS 系统存在极大的复杂性挑战,使得 CephFS 从最开始的众星捧月到失去耐心,而在 Inktank 被 RedHat 收购后重新被注入一股强心剂,不管是 RedHat 还是 Inktank 都对支持 CephFS 都有极大的关注度。在通常意义上来讲(也是社区内部的看法),Ceph 目前主要还是活跃于云环境,在其他领域仍处于尝鲜或者存在较大的切入难度,而 CephFS 被社区贯以极大的希望去拓展广泛的 NAS 领域,而新兴的容器不管是 Docker,Kubernetes 还是 Mesos 又或者 Host OS 如 Atomic,CoreOS,Snappy Ubuntu 都有与 CephFS 联手的极大需求。拿 Sage Weil 的话来说,容器存储是 Ceph 需要征讨的下一个领地。

从社区到 Redhat,整体的优先级顺序分别是“性能”,“CephFS”,“跟新兴云平台的合作”,“与大数据平台的合作”,我们从这里看到 CephFS 在社区里面的优先地位。由于 CephFS 存在极大的变动性,本文更多关注于从用户角度理解 CephFS 的概括,进展,对于 IO 或者实际实现并不多涉及。

难度

CephFS 目前所受的广泛关注实际上也是与其本身的复杂性有关,众所周知,一个 Scale Out 的系统本质上在于把所有数据解耦分离,而一个 POSIX 文件系统是很难做到这点:

  1. 多个客户端的同时写必须是“成功”或者“完全失败” → 锁机制
  2. Inode 由于目前的层级关系存在依赖性
  3. 客户端是带状态的系统
  4. 数据丢失将对整个子树造成影响
  5. 分布式系统本身的复杂性带来对 POSIX 语意的影响,如文件系统满,客户端/服务器挂了,客户端实现有差异

但正因为一个文件系统实现了众多的特性,使得应用可以非常享受逻辑业务本身。如果 SQL 与 NOSQL 关系一样。

架构

QQ20150903-1@2x

CephFS 继承了 RADOS 的扩展性和恢复能力,使用 MDS 组件管理所有 POSIX 相关的元数据,MDS 不会负责实现任何数据的存储而依赖于 RADOS 本身。

ceph-deploy mds create myserver
ceph osd pool create fs_data
ceph osd pool create fs_metadata
ceph fs new myfs fs_metadata fs_data
mount -t cephfs x.x.x.x:6789 /mnt/ceph

这段简单的命令构成了如何在一个 RADOS 集群上构建一个新的 CephFS 集群,我们可以看到每一个 FS 都存在两类 Pool 分别是 Metadata Pool 和 Data Pool,我们可以使用 CRUSH 规则来为 Metadata Pool 使用更快的存储,而 Data Pool 使用更慢的存储。

CephFS 的元数据中每个目录会作为一个或者多个 Object 存储,类似 . 的命名方式。同时每个 inode 和 dentry 信息也会被内置其中,该类 Object 会被存储到 Metadata Pool 中。而文件实际数据也以类似的 . 存储到 Data Pool 中。同时还会像 XFS Log 一样存在 Log Object 存在于 Metadata Pool,是为了实现涉及多个 Object 的事务性操作准备,因为 RADOS 并不提供多对象的原子性。该 Log Object 包含了最近的所有元数据操作,在存在意外时可以使用 Log Object Replay 之前的数据。

除了本地文件系统都具备的典型结构外,CephFS 还有另外一类 MDSTable Object 用来存储每个 MDS 的 Session,Inode 分配情况,Snapshot ID 和状态等等。这些对象也是存在于 Metadata Pool。

现状和发展

Firefly 依赖所有的 CephFS 工作分成以下部分:

  1. 优雅的错误处理
  2. 集群问题的监测和汇报
  3. 提供恢复工具
  4. 大量的 QA 测试集

从实际的变化来看,比如 cephfs-journal-tool 用来对被损害的对象做恢复,同时改变了之前的日志格式,使得能够跳过日志数据被破坏的片段。而 cephfs-table-tool 用来修复 session/inode/snap 相关的对象恢复。在文件系统快写满时,会允许 Delete 相关操作继续同时会拒绝其他操作包括 fsync 等。同时支持对于客户端的管理,如:

ceph osd blacklist add 
ceph daemon mds. session evict
ceph daemon mds. osdmap barrier

未来的主要进展主要是在提供一个完整的 FSCK & Repair 工具,同时对 多 MDS 协同,快照等功能进行加固。FSCK 能力被社区及其重视,这实际上是其他几乎所有分布式文件系统所不能提供的,Sage 也将此看做是标记 CephFS 为 “Production Ready” 的标志,他希望在 J 版能够做到这点。拥有 FSCK 意味着 CephFS 能够经受更多的数据破坏和潜在的 Bug,使得文件系统受影响的危害性大大减少。但是对于 CephFS FSCK 难度也是显而易见的,因为我们需要修复一个 RADOS 集群数据而不是一块磁盘,大量的数据使得我们几乎不可能将修复情况全部存储在内存中,集群的庞大性使得对于修复的时间也是一个亟待考验的事情。

整个修复方案分为两部分,第一部分是从整个文件系统角度,至上而下。在修复过程中,会使用深度优先算法检查每个文件对象的正确性,目录对象是不是正确描述了整个目录情况,同时提供一些额外的 Scrub Stamp 来标记过往的检查时间。而第二部分是从文件或者目录角度去回溯每个文件或者给定目录的正确性,去 RADOS 做数据遍历。

小结

总而言之,CephFS 是 Ceph 世界里下一个被期待的重大事件,它使得 Ceph 在统一存储的路上可以跨出一大步来完成庞大生态系统的闭环化。

Ceph 生态系统

$
0
0

Ceph 是一个致力于构建下一代存储的项目,由 Sage Weil 从 04 年开始进行,在 08 年开始建立开源社区并接纳外部的开发者加入项目。从 10 年开始,来自 Yahoo,Suse,Canonical,Intel 等第一批开发者开始进入 Ceph 社区协作开发,在 12 年进入 OpenStack Cinder 成为重要的存储驱动,13 年开始在 OpenStack 用户间逐渐试用,在 14 年 Ceph 逐渐吸引越来越多来自不同厂商的开发者加入,在 14 年中,Ceph 的实际控制者 Inktank 被 Redhat 收购,被注入强心剂和得到更广泛的支持。至今 Ceph 已经成为最广泛的全球开源软件定义存储项目,拥有一个得到众多 IT 厂商支持的协同开发模式。

对于用户来说,Ceph 是一个拥有丰富特性,连接众多其他开源项目的成熟生态系统,在完善的测试基础设施和较为稳定的开发周期和模式运行下,Ceph 正被越来越多企业用户的部署和使用。

平台生态系统

不管是商业系统还是开源项目,任何一个强壮的开发生态体系都依赖于三个重要的支持:技术平台,持续创新环境和广泛的用户基础。比如 IOS 这个开放的开发平台通过超百万的 APP 和来自全球数亿用户的使用构成了循环的生态体系,Facebook 通过其开发者平台得到来自数十万个在线应用和亿万用户(80% 以上来自非美加用户)的支持,OpenStack 项目通过其不断演进的工具,服务和新项目,加上全球私有云,公有云用户的运行支持,构建了现在最流行的开源云平台。

后面我们关注 Ceph 的技术平台,持续创新环境和广泛的用户基础这三个方面。

Snip20160131_1

技术平台

Ceph 项目致力于成为未来存储的核心,其设计原则有以下几点:

  1. 所有组件必须能够横向扩展,没有单点故障并运行在普通商用硬件上
  2. 尽可能自我管理
  3. 开源,以 LGPL 授权

  4. 使用 client/cluster 而不是 client/server 的访问方式

Ceph 通过实现类 POSIX 接口的对象存储接口来构建底层通用的存储系统,上层通过堆叠不同存储标准(如 POSIX,块接口和 S3/Swift)来实现不同存储场景的应用。这个方式也是 Ceph 统一存储目标的技术基础。

Snip20160131_2

项目开发迭代周期

目前 Ceph 社区采用每半年一个版本发布的方式来进行特性和功能的开发,每个版本发布需要经历设计,开发,新功能冻结,持续若干个版本的 Bug 修复周期后正式发布下一个稳定版本。

Ceph 会维护了多个稳定版本来保证持续的 Bug 修复来保证用户的存储安全,社区会有一支稳定版本发布团队来维护已发布版本,每个涉及到之前版本的 Bug 都会被该团队移植回稳定版本,并且经过完整 QA 测试后发布下一个稳定版本。

每个 commit 都需要经过单元测试,模块维护者 review,并通过 QA 测试子集后才能合并到主线。社区维护了一个较大规模的测试集群来保证代码质量,丰富的测试案例和错误注入机制保证了项目的稳定可靠。

Ceph Developer Summit

Ceph 会在上一个版本特性冻结之前开始下一个版本的特性设计,主要依赖于 Ceph Developer Summit(CDS) 的机制来进行讨论。CDS 主要在线上进行,通过多人视频方式进行沟通,参与者通过 ppt,pad 和在线演说来进行,特性的讨论和结论主要由发起者和模块技术领导人来完成,可以通过这个页面来了解过去 CDS 的历史记录。

一个 Blueprint 需要提交者经过严密的考虑,然后交给 CDS 的 Chairman (通常是 Sage 和 Patrick) 去调度相应的时间去讨论,通常会根据时区进行安排。每个 Blueprint 必须有清晰的提交者和所有人,不仅仅是讨论这个想法的目的和实现结果,还需要考虑具体的实现方式和结果是不是能在目前的 Ceph 中得到满足。

贡献者

目前 Ceph 社区由来自超过 40 个公司的上百名开发者持续贡献代码,平均每星期的代码 Commits 超过 150 个,每个版本通常在 2000 个 commits 左右,代码增减行数在 10w 行以上。在过去的几个版本发布中,贡献者的数量和参与公司明显增加。

由于 Ceph 社区并没有良好的社区贡献排行网站,上图来自 OpenStack stackalytics 提供的最近一次 Release,Liberty 期间 Ceph 的 Line of Code(LoC) 代码贡献排行。其中 Redhat 贡献了四分之三的代码,Intel 和来自国内的 SDS 初创公司 XSky 分别排名第二和第三。

非常有意思的是 Ceph 的使用用户占据了相当的贡献排名,一定程度上反映了 Ceph 目前的现状,要能够真正掌控 Ceph 必须得深入社区并随之成长。因此,对于一个并不是像 Linux 一样成熟的开源项目,特别还是一个存储系统来说,代码贡献程度基本决定了对于 Ceph 的理解,风险控制和使用程度。社区内部的形成的开发,使用问题,迭代,修复,升级,测试流程闭环产生的效应能够大大提高参与公司对于 Ceph 的理解。大部分真正大规模使用或者基于 Ceph 的产品的公司都参与或间接参与到了社区其中,这非常类似于早期的 Linux 和 OpenStack 情况。

Snip20160131_3

持续创新环境

从传统IT基础架构的生态链看,各个层级的行业领导者纷纷为Ceph投入人力,物力来持续推动不断创新的运行,开发和生产环境。

如上图所示,Redhat,Suse 和 Canonical 构成了 Ceph 软件发行包的厂商,Intel,Mellanox,AMD 和 Cisco 分别在不同的硬件组件层面推动自身融入 Ceph 体系,SanDisk,HDS 和 Fujitsu 都在自身的存储系统上采用 Ceph 整合,CERN 和德国电信分别是 Ceph 社区参与和回馈最多的企业用户。

Ceph 通过其开放的社区和插件化的代码架构来包容越来越多的底层厂商参与其中,不管是 Mellanox 推动 Infiniband/RDMA,还是希捷的 Kinetic API,或是 Intel x86 架构,ARM 都在积极的参与其中,利用自身的优势来持续对 Ceph 软件体系进行创新发展。

比如在网络层面,通过插件方式的网络 IO 栈选择,相对于默认情况下的 TCP/IP Kernel 栈,Mellanox 联合 Redhat 提供了基于 RDMA 的网络方案,Solarflare 正在准备支持基于 OpenOnLoad 的 Kernel TCP Offload 方案。在底层存储上,默认方案是基于 Linux 通用本地文件系统构建的存储引擎,

但同时通过其多元化的存储引擎设计,可以通过 KeyValueStore 支持硬件直接暴露 KV 接口的设备比如希捷的 Kinetic API,而且因为 SSD 本身在底层是一个类 KV 的页访问方式,类似 Samsung 和 SanDisk 为了避免块接口语义转换,在推出的 Flash 一体机都采用私有的 KV 库对接 Ceph 存储引擎。同时通过 MemStore 封装的内存管理 API 通过 libpmem可以实现对 NVDIMM 或者 NVRAM 的管理。

广泛的用户基础

Ceph 项目的 vision 是突破长久以来存储厂商封闭垄断的现状,将存储系统架构于普通商用硬件之上,并且为统一存储和异构管理这一目标发展。

从 OpenStack 后端存储流行起步,Ceph 目前广泛使用在传统企业,互联网之中。

CERN

CERN IT 部门在 13 年中开始就运行了一个单一集群超过 10000 个 VM 和 100000 个 cpu cores 的云平台,主要用来做物理数据分析。这个集群后端 Ceph 包括了 3PB 的原始容量,在云平台中作为一千多个 Cinder 卷和一千五百多个 Glance 景象的存储池。在 15 年开始测试单一 30 PB 的块存储 RBD 集群。

DreamHost

DreamHost 从 12 年开始运行基于 Ceph RadosGW 的大规模对象存储集群,单一集群在 3PB 以下,大约由不到十个机房集群组成,直接为客户提供给对象存储服务。

Yahoo Flick

Yahoo Flick 自 13 年开始逐渐试用 Ceph 对象存储替换原有的商业存储,目前大约由十个机房构成,每个机房在 1-2 PB 之间,存储了大约 2500 亿个对象。