学习自世民大神的博客:http://www.cnblogs.com/sammyliu/p/4804037.html

正在入门ceph,懵懂中,随手作下笔记。


Ceph 集群的逻辑结构由 Pool 和 PG (Placement Group)来定义。

1、Pool:

一个 Pool 是 Ceph 中的一些对象的逻辑分组,它并不表示一个连续的分区,而只是一个逻辑概念,类似于将二进制数据打了tag一样然后根据tag归类一样。它类似于 LVM 中的 Volume Group,类似于一个命名空间。RBD Image 类似于 LVM 中的 Logical Volume。RBD Image 必须且只能在一个 Pool 中。Pool 由若干个PG组成。其属性包括:

  • 所有性和访问权限

  • 对象副本数目

  • PG 数目

  • CRUSH 规则集合

Ceph Pool 有两种类型:

  1. Replicated pool:拷贝型 pool,通过生成对象的多份拷贝来确保在部分 OSD 丢失的情况下数据不丢失。这种类型的 pool 需要更多的裸存储空间,但是它支持所有的 pool 操作。

  2. Erasure-coded pool:纠错码型 pool(类似于 Software RAID)。在这种 pool 中,每个数据对象都被存放在 K+M 个数据块中:对象被分成 K 个数据块和 M 个编码块;pool 的大小被定义成 K+M 块,每个块存储在一个 OSD 中;块的顺序号作为 object 的属性保存在对象中。可见,这种 pool 用更少的空间实现存储,即节约空间;纠删码实现了高速的计算,但有2个缺点,一个是速度慢,一个是只支持对象的部分操作(比如:不支持局部写)。这篇文章 详细介绍了其原理和细节。

Pool 提供如下的能力:

  1. Resilience(弹力):即在确保数据不丢失的情况允许一定的 OSD 失败,这个数目取决于对象的拷贝(copy/replica)份数。对拷贝型 pool 来说,Ceph 中默认的拷贝份数是2,这意味着除了对象自身外,它还有一个另外的备份。你可以自己决定一个 Pool 中的对象的拷贝份数。

  2. Placement Groups(放置组):Ceph 使用 PG 来组织对象,这是因为对象可能成千上万,因此一个一个对象来组织的成本是非常高的。PG 的值会影响 Ceph 集群的行为和数据的持久性。你可以设置 pool 的 PG 数目。推荐的配置是,每个 OSD 大概 100 个 PG。

  3. CRUSH Rules (CRUSH 规则):数据映射的策略。系统默认提供 “replicated_ruleset"。用户可以自定义策略来灵活地设置 object 存放的区域。比如可以指定 pool1中所有objecst放置在机架1上,所有objects的第1个副本放置在机架1上的服务器A上,第2个副本分布在机架1上的服务器B上。 pool2中所有的object分布在机架2、3、4上,所有Object的第1个副本分布在机架2的服务器上,第2个副本分布在机架3的服 器上,第3个副本分布在机架4的服务器上。详细的信息可以参考这些文档 (1)(2)(3)(4)

  4. Snapshots(快照):你可以对 pool 做快照。

  5. Set Ownership:设置 pool 的 owner 的用户 ID。

  6. Ceph 集群创建后,默认创建了 data,metadata 和 rbd 三个存储池。


2、PG

 PG 概念非常复杂,主要有如下几点:

  • PG 也是对象的逻辑集合。同一个PG 中的所有对象在相同的 OSD 上被复制。

  • PG 聚合一部分对象成为一个组(group),这个组被放在某些OSD上(place),合起来就是 Placemeng Group (放置组)了。

  • Epoch:PG map 的版本号,它是一个单调递增的序列。

  • Peering:见下文的状态(8)描述。详细过程请参阅 Ceph:pg peering过程分析

  • Acting set:支持一个 PG 的所有 OSD 的有序列表,其中第一个 OSD 是主OSD,其余为次。acting set 是 CRUSH 算法分配的,但是不一定已经生效了。

  • Up set:某一个 PG map 历史版本的 acting set。在大多数情况下,acting set 和 up set 是一致的,除非出现了 pg_temp。

  • Current Interval or Past Interval:若干个连续的版本号,这些版本中 acting 和 up set 保持不变。

  • PG temp:在Ceph 正在往主 OSD 回填数据时,这个主OSD是不能提供数据服务的,这时候,它会向 MON 申请一个临时的 acting set,这就是 PG temp。举个例子,现在 acting set 是[0,1,2],出现了一点事情后,它变为 [3,1,2],此时 osd.3 还是空的因此它无法提供数据服务因此它还需要等待backfilling过程结束,因此,它会向 MON 申请一个临时的 set 比如 [1,2,3],此时将由 osd.1 提供数据服务。回填过程结束后,该临时 set 会被丢弃,重新由 osd.3 提供服务。

  • 主 (primary) OSD:在 acting set 中的首个 OSD,负责接收客户端写入数据;默认情况下,提供数据读服务,但是该行为可以被修改。它还负责 peering 过程,以及在需要的时候申请 PG temp。

  • 次 (replica)OSD:在 acting set 中的除了第一个以外的其余 OSD。

  • 流浪 (stray) OSD:已经不是 acting set 中了,但是还没有被告知去删除数据 的 OSD。

  • PG 的 acting set 是由 CRUSH 算法根据 CRUSH Rules 动态地计算得出的。

其主要特点如下:

  • 基本特点

    • PG 确定了 pool 中的对象和 OSD 之间的映射关系。一个 object 只会存在于一个 PG 中,但是多个 object 可以在同一个 PG 内。

    • Pool 的 PG 数目是创建 pool 时候指定的,Ceph 官方有推荐的计算方法。其值与 OSD 的总数的关系密切。当Ceph 集群扩展 OSD 增多时,根据需要,可以增加 pool 的 PG 数目。

    • 对象的副本数目,也就是被拷贝的次数,是在创建 Pool 时指定的。该分数决定了每个 PG 会在几个 OSD 上保存对象。如果一个拷贝型 Pool 的size(拷贝份数)为 2,它会包含指定数目的 PG,每个 PG 使用两个 OSD,其中,第一个为主 OSD (primary),其它的为从 OSD (secondary)。不同的 PG 可能会共享一个 OSD。

    • Ceph 引入 PG 的目的主要是为了减少直接将对象映射到 OSD 的复杂度。

    • PG 也是Ceph 集群做清理(scrubbing)的基本单位,也就是说数据清理是一个一个PG来做的。

    • PG 和 OSD 之间的映射关系由 CRUSH 决定,而它做决定的依据是 CRUSH 规则(rules)。CRUSH 将所有的存储设备(OSD)组织成一个分层结构,该结构能区分故障域(failure domain),该结构中每个节点都是一个 CRUSH bucket。详细情况请阅读 CRUSH 相关的文档。

  • PG 和 OSD 的关系是动态的:

    • 当新的 OSD 被加入集群后,已有OSD上部分PG将可能被挪到新OSD上;此时PG 和 OSD 的关系会发生改变。

    • 当已有的某 OSD down 了并变为 out 后,其上的 PG 会被挪到其它已有的 OSD 上。

    • 但是大部分的 PG 和 OSD 的关系将会保持不变,在状态变化时,Ceph 尽可能只挪动最少的数据。

    • up:守护进程运行中,能够提供IO服务;

    • down:守护进程不在运行,无法提供IO服务;

    • in:包含数据;

    • out:不包含数据

    • 一开始在 PG 被创建的时候,MON 根据 CRUSH 算法计算出 PG 所在的 OSD。这是它们之间的初始关系。

    • Ceph 集群中 OSD 的状态是不断变化的,它会在如下状态之间做切换:

    • 部分 PG 和 OSD 的关系会随着 OSD 状态的变化而发生变化。

    • 客户端根据 Cluster map 以及 CRUSH Ruleset 使用 CRUSH 算法查找出某个 PG 所在的 OSD 列表(其实是 up set)。

    • PG-Object-OSD 的关系如下图所示:

      Ceph+Openstack相关入门——Ceph的pool与PG_Openstack

    • PG 的创建过程(详细过程请参考 PG 的创建过程):

      • MON 节点上有PGMonitotor,它发现有 pool 被创建后,判断该 pool 是否有 PG。如果有PG,则一一判断这些 PG 是否已经存在,如果不存在,则开始下面的创建 PG 的过程。

      • 创建过程的开始,设置PG 状态为 Creating,并将它加入待创建PG队列 creating_pgs,等待被处理。

      • 开始处理后,使用 CRUSH 算法根据当前的 OSD map 找出来 up/acting set,加入 PG map 中以这个 set 中 OSD 为索引的队列 creating_pgs_by_osd。(看起来只会加入到主OSD的队列中)。

      • 队列处理函数将该 OSD 上需要创建的 PG 合并,生成消息MOSDPGCreate,通过消息通道发给 OSD。

      • OSD 收到消息字为 MSG_OSD_PG_CREATE 的消息,得到消息中待创建的 PG 信息,判断类型,并获取该PG的其它OSD,加入队列 creating_pgs (似乎是由主 OSD 负责发起创建次 OSD 上的PG),再创建具体的 PG。

      • PG 被创建出来以后,开始 Peering 过程。

    • PG 值的确定:创建 pool 时需要确定其 PG 的数目,在 pool 被创建后也可以调整该数字,该数目会影响到:

          那如何确定一个 Pool 中有多少 PG?Ceph 不会自己计算,而是给出了一些参考原则,让 Ceph 用户自己计算:

      • 少于 5 个 OSD, 建议设为  128

      • 5 到 10 个 OSD,建议设为 512

      • 10 到 50 个 OSD,建议设为 4096

      • 50 个 OSD 以上,就需要有更多的权衡来确定 PG 数目

      • 你可以使用 pgcalc 工具

      • 数据的持久性:考虑pool 的 size 为 3,表明每个 PG 会将数据存放在 3 个 OSD 上。当一个 OSD down 了后,一定间隔后将开始 recovery 过程,recovery结束前,有部分 PG 的数据将只有两个副本。这时候和需要被恢复的数据的数量有关系,如果该 OSD 上的 PG 过多,则花的时间将越长,风险将越大。如果此时再有一个 OSD down 了,那么将有一部分 PG 的数据只有一个副本,recovery 过程继续。如果再出现第三个 OSD down 了,那么可能会出现部分数据丢失。可见,每个 OSD 上的PG数目不宜过大,否则,会降低数据的持久性。这也就要求在添加 OSD 后,PG 的数目在需要的时候也需要相应增加。

      • 数据的均匀分布性:CRUSH 算法会伪随机地保证 PG 被选中来存放客户端的数据,它还会尽可能地保证所有的 PG 均匀分布在所有的 OSD 上。比方说,有10个OSD,但是只有一个 size 为 3 的 pool,它只有一个 PG,那么10个 OSD 中将只有三个 OSD 被用到。但是 CURSH 算法在计算的时候不会考虑到OSD上已有数据的大小。比方说,100万个4K对象共4G均匀地分布在10个OSD上的1000个PG内,那么每个 OSD 上大概有400M 数据。再加进来一个400M的对象(假设它不会被分割),那么有三块 OSD 上将有 400M + 400M = 800 M 的数据,而其它七块 OSD 上只有 400M 数据。

      • 资源消耗:PG 作为一个逻辑实体,它需要消耗一定的资源,包括内存,CPU 和带宽。太多 PG 的话,则占用资源会过多。

      • 清理时间:Ceph 的清理工作是以 PG 为单位进行的。如果一个 PG 内的数据太多,则其清理时间会很长。

    • PG 的状态也是不断变化的,其主要状态包括:

      • Creating 创建中:PG 正在被创建。

      • Peering 对等互联:表示一个过程,该过程中一个 PG 的所有 OSD 都需要互相通信来就PG 的对象及其元数据的状态达成一致。处于该状态的PG不能响应IO请求。Peering的过程其实就是pg状态从初始状态然后到active+clean的变化过程。一个 OSD 启动之后,上面的pg开始工作,状态为initial,这时进行比对所有osd上的pglog和pg_info,对pg的所有信息进行同步,选举primary osd和replica osd,peering过程结束,然后把peering的结果交给recovering,由recovering过程进行数据的恢复工作。

      • Active 活动的:Peering 过程完成后,PG 的状态就是 active 的。此状态下,在主次OSD 上的PG 数据都是可用的。

      • Clean 洁净的:此状态下,主次 OSD 都已经被 peered 了,每个副本都就绪了。

      • Down:PG 掉线了,因为存放其某些关键数据(比如 pglog 和 pginfo,它们也是保存在OSD上)的副本 down 了。

      • Degraded 降级的:某个 OSD 被发现停止服务 (down)了后,Ceph MON 将该 OSD 上的所有 PG 的状态设置为 degraded,此时该 OSD 的 peer OSD 会继续提供数据服务。这时会有两种结果:一是它会重新起来(比如重启机器时),需要再经过 peering 过程再到clean 状态,而且 Ceph 会发起 recovery (恢复)过程,使该 OSD 上过期的数据被恢复到最新状态;二是 OSD 的 down 状态持续 300 秒后其状态被设置为 out,Ceph 会选择其它的 OSD 加入 acting set,并启动回填(backfilling)数据到新 OSD 的过程,使 PG 副本数恢复到规定的数目。详情可以参考 PG 的数据恢复过程

      • Recovering 恢复中:一个 OSD down 后,其上面的 PG 的内容的版本会比其它OSD上的 PG 副本的版本落后。在它重启之后(比如重启机器时),Ceph 会启动 recovery 过程来使其数据得到更新。

      • Backfilling 回填中:一个新 OSD 加入集群后,Ceph 会尝试级将部分其它 OSD 上的 PG 挪到该新 OSD 上,此过程被称为回填。与 recovery 相比,回填(backfill)是在零数据的情况下做全量拷贝,而恢复(recovery)是在已有数据的基础上做增量恢复。

      • Remapped 重映射:每当 PG 的 acting set 改变后,就会发生从旧  acting set 到新 acting set 的数据迁移。此过程结束前,旧 acting set 中的主 OSD 将继续提供服务。一旦该过程结束,Ceph 将使用新 acting set 中的主 OSD 来提供服务。

      • Stale 过期的:OSD 每隔 0.5 秒向 MON 报告其状态。如果因为任何原因,主 OSD 报告状态失败了,或者其它OSD已经报告其主 OSD down 了,Ceph MON 将会将它们的 PG 标记为 stale 状态。 

      • PG 的所有的状态是一个类似树形的结构,每个状态可能存在子状态,子状态还可能存在子状态,如下图所示:

      • Ceph+Openstack相关入门——Ceph的pool与PG_Pool_02