Nautilus 新特性:PG 合并和自动调优
自 Ceph 诞生以来,选择和调优 Ceph 集群中的 PG 数量一直是管理 Ceph 集群中最令人沮丧的部分。 选择合适的池的指导原则令人困惑,不同来源之间不一致,并且经常伴随着各种注意事项和例外情况。 最重要的是,如果选择了错误的值,有时无法纠正,并且性能和/或稳定性可能会受到影响。 在 Nautilus 之前的 Ceph 版本中,关键的限制是 pg_num 值始终可以增加(如果值太小),但如果值太大则无法减少。
不再! 在 Nautilus 中,池的 pg_num 值可以减少。 更重要的是,可以启用一个 PG 自动调优器,该调优器允许系统进行任何适当的调整,以便用户可以完全忽略以前的 pg_num 调优的玄学。
那么,什么是 PG? ¶
存储在 RADOS(Ceph 的底层存储层)中的数据对象被分组到逻辑 池中。 池具有诸如复制因子、擦除码方案以及可能用于仅将数据放置在 HDD 或 SSD 上的规则等属性。 在内部,池被分解为 pg_num 放置组,或 PG,基于存储在池中的对象的名称的哈希值。 因此,每个放置组都是整个池的伪随机切片、分片或片段,并且特定 PG 中的所有对象都分组并存储在相同的存储设备(OSD)集上。
只有少量对象的小型池只需要几个 PG。 大型池(例如,包含集群中存储的大部分数据)需要大量的 PG,以确保数据分散在许多设备上,既可以平衡所有 OSD 上的空间利用率,又可以在系统负载下提供良好的并行性。 PG 过少会导致性能瓶颈出现在少量存储设备上,而 PG 过多会导致 Ceph 行为效率低下——在极端情况下,不稳定——这是由于管理每个 PG 所需的内部跟踪造成的。
标准经验法则是我们希望每个 OSD 大约有 100 个 PG,但确定每个池在系统中需要多少 PG(同时考虑复制和擦除码等因素)可能具有挑战性。
PG 分割和合并 ¶
Ceph 自 2012 年以来一直支持 PG“分割”,从而能够将现有 PG 的内容分割成许多较小的 PG,从而增加池的总 PG 数量。 这允许从小规模开始并随后增长的集群随时间扩展。 从 Nautilus 开始,我们现在还可以“合并”两个现有的 PG 成一个较大的 PG,从而减少 PG 的总数。 如果池中的相对数据量随时间减少,因此需要的 PG 更少或更合适,或者整个集群缩小,或者最初选择的 PG 数量过多,这将很有用。
传统上,当增加 PG 数量时,PG 分割是一次性完成的。 例如,要将池的 pg_num 值从 16 调整为 64,可以简单地
$ ceph osd pool set foo pg_num 64
并且集群将一次将每个 16 个 PG 分割成 4 个部分。 以前,还需要执行第二步来调整 placement,以便将这些新的 PG 存储到新的设备上
$ ceph osd pool set foo pgp_num 64
这是耗费大量资源的部分,实际数据会被移动。 从 Nautilus 开始,不再需要第二步:只要 pgp_num 和 pg_num 当前匹配,pgp_num 就会自动跟踪任何 pg_num 更改。 更重要的是,pgp_num 的调整以迁移数据并(最终)收敛到 pg_num 的方式是逐步完成的,以限制系统上的数据迁移负载,这基于新的 target_max_misplaced_ratio 配置选项(默认值为 .05,或 5%)。 也就是说,默认情况下,Ceph 会尝试使“错位”状态且排队进行迁移的数据不超过 5%,从而限制对客户端工作负载的影响。
PG 合并类似于分割,只是在内部 pg_num 值始终一次减少一个 PG。 合并是一个更复杂和微妙的过程,需要暂停 PG 的 IO 几秒钟,并且一次合并一个 PG 允许系统最大限度地减少影响并简化整个过程的复杂性。 当使用如下命令减少 foo 池的 pg_num 时,会设置一个内部 pg_num_target 值,指示 pg_num_的期望值,并且集群会努力缓慢地收敛到该值。 例如,要将池 foo 的 PG 从 64 减少到 4,
$ ceph osd pool set foo pg_num 4 $ ceph osd pool ls detail | grep foo pool 1 'foo' replicated size 3 min_size 2 crush_rule 0 object_hash rjenkins pg_num 63 pgp_num 62 pg_num_target 4 pgp_num_target 4 autoscale_mode warn last_change 391 lfor 0/391/389 flags hashpspool stripe_width 0
PG 自动缩放器 ¶
能够调整 pg_num 值是一个重要的进步,但它并没有解决 PG 调优对大多数用户来说仍然像黑魔法一样的问题。 Nautilus 包含一个新的管理器模块,称为 pg_autoscaler,该模块允许集群考虑实际存储(或预期存储)在每个池中的数据量,并自动选择合适的 pg_num 值。
由于自动缩放器是新的,因此需要在 Nautilus 中显式启用它
$ ceph mgr module enable pg_autoscaler
自动缩放器在每个池的基础上进行配置,并且可以在几种模式下运行
- 在 warn 模式下,如果建议的 pg_num 值与当前值差异太大,则会发出健康警告。 这是新旧池的默认模式。
- 在 autoscaler on 模式下,池 pg_num 会自动调整,无需任何管理员交互。
- 自动缩放器也可以为任何给定池关闭,让管理员像以前一样手动管理 pg_num。
要为特定池启用自动缩放,
$ ceph osd pool set foo pg_autoscale_mode on
启用后,可以通过 CLI 查询所有池的当前状态和建议的调整。 例如,在我们的实验室集群中,我们有
$ ceph osd pool autoscale-status POOL SIZE TARGET SIZE RATE RAW CAPACITY RATIO TARGET RATIO PG_NUM NEW PG_NUM AUTOSCALE device_health_metrics 18331k 3.0 431.3T 0.0000 1 warn
default.rgw.buckets.non-ec 0 3.0 431.3T 0.0000 8 warn
default.rgw.meta 2410 3.0 431.3T 0.0000 8 warn
default.rgw.buckets.index 38637k 3.0 431.3T 0.0000 8 warn
default.rgw.control 0 3.0 431.3T 0.0000 8 warn
default.rgw.buckets.data 743.5G 3.0 431.3T 0.0050 32 on
.rgw.root 1113 3.0 431.3T 0.0000 8 warn
djf_tmp 1169G 3.0 431.3T 0.0079 4096 32 off
libvirt-pool 2048M 3.0 431.3T 0.0000 3000 4 off
data 66692G 3.0 431.3T 0.4529 4096 warn
default.rgw.log 8146k 3.0 431.3T 0.0000 8 warn
metadata 54050M 4.0 431.3T 0.0005 64 4 off
您会注意到,大部分数据位于 CephFS 存储我们所有 QA 结果的“metadata”和“data”池中。 大多数其他池都是来自各种测试的遗留池,并且大多为空。
让我们看一下每一列
- SIZE 列只是报告存储在池中的总数据量(以字节为单位)。 这包括对象数据和 omap 键/值数据。
- TARGET SIZE 报告管理员对池的预期大小的任何输入。 如果池刚刚创建,它最初将不存储任何数据,但管理员通常对最终将存储多少数据有一些概念。 如果提供,则该值与实际大小的较大者用于计算池的理想 PG 数量。
- RATE 值是原始存储消耗与用户存储数据的比率,对于复制的存储桶来说就是复制因子,对于擦除编码的存储桶来说通常是较小的比率。
- RAW CAPACITY 是存储设备通过 CRUSH 映射到池的原始存储容量。
- RATIO 是该总存储池消耗的比例。
- TARGET RATIO 是管理员提供的值,类似于 TARGET SIZE,指示用户期望池消耗集群总存储的比例。
- 最后,PG_NUM 是池的当前 PG 数量,而NEW PG_NUM(如果存在)是建议的值。
- AUTOSCALE 列指示池的模式,即off、warn 或 on**.**
建议的值会考虑几个输入,包括池消耗(或预期消耗)的集群的比例、池分布在哪些 OSD 上以及每个 OSD 的目标 PG 数量(如由 mon_target_pg_per_osd 配置选项定义,默认值为 100)。 自动缩放器将始终选择一个为 2 的幂的 pg_num 值,因为这对于 Ceph 来说效率更高(这意味着同一池中的所有 PG 大小大致相同),并且它只会建议更改 pg_num,如果建议的值是实际值的三倍以上。 这意味着,在大多数情况下,增长的池的 pg_num 值每次更改时都会增加 4 倍,并且除非池的大小发生显著变化,否则它会坚持使用相同的值。
当首次设置集群时,设置池的目标比率通常会有所帮助,以便自动缩放器可以做出良好的初始决策。 例如,如果集群的主要用途是块存储,则可以将 rbd 池的目标比率设置为 .8 并启用 PG 自动缩放
$ ceph osd pool create foo 1 $ rbd pool init foo $ ceph osd pool set foo target_size_ratio .8 $ ceph osd pool set foo pg_autoscale_mode on
此时,集群将自行选择一个 pg_num 并将其在后台应用。
可以使用以下命令控制新创建的池使用的 pg_autoscale_mode
$ ceph config set global osd_pool_default_autoscale_mode <mode>
我可以完全放手吗? ¶
是的。 如果您为新池启用自动缩放,并为现有池启用自动缩放,那么系统将随着数据存储在集群中而扩展 PG。
这种方法的唯一问题是,在数据存储后调整 PG 计数会移动集群中的数据,这代价高昂。 作为经验法则,如果创建了一个空池,然后填充以消耗集群中所有可用空间,那么所有写入的数据在写入后大约会移动一次。 这不是理想的——最好在创建池时提供 target ratio 或 target bytes 值,以便选择合适的初始 PG 计数——但无知的开销至少是有限且合理的。
接下来是什么? ¶
自动化放置组的管理是使 Ceph 更易于部署和为非专家操作的一大步。 在不久的将来,我们预计 pg_autoscaler 模块将默认启用,一旦我们获得更多用户反馈并(希望)对它所做的建议更有信心。
我们渴望获得您对这项新功能的反馈! 请通过邮件列表、IRC 或甚至在下个月在巴塞罗那举行的 Cephalocon 上与我们分享您的想法!
当然,我们还将寻找其他 Ceph 调优和管理令人困惑的领域,并继续努力在这些领域添加自动化功能。
有关更多信息,请参阅有关 放置组的文档,其中包含有关自动缩放行为的更多详细信息。