注意
本文档适用于 Ceph 开发版本。
CRUSH MSR(多步重试)
动机
传统的 CRUSH 有一个重要的限制:具有多个步骤的规则在遇到无法重试的 osd 时。例如,使用一个这样的规则,如果一台特定主机上的所有 OSD 都被标记为失效,包含这些 OSD 的映射最终会出现在另一台主机上(前提是有足够的主机)。确实会发生这种情况。此外,如果一台主机上的 1/8 OSD 被标记为失效,映射到该主机的约 1/8 PG 最终会被重新映射到其他主机,从而保持每个 OSD 的总体利用率。choose steps which hit an 无法服务 ( osd cannot retry prior steps. As an example, with a rule like
rule replicated_rule_1 {
...
step take default class hdd
step chooseleaf firstn 3 type host
step emit
}
one might expect that if all of the OSDs on a particular host are marked out, mappings including those OSDs would end up on another host (provided that there are enough hosts). Indeed, that’s what will happen. Moreover, if 1/8 OSDs on a host are marked out, roughly 1/8 of the PGs mapped to that host will end up remapped to some other host keeping overall per-OSD utilization even.
假设规则写成这样:
rule replicated_rule_1 {
...
step take default class hdd
step choose firstn 3 type host
step choose firstn 1 type osd
step emit
}
只要没有 OSD 被标记为失效,行为就会非常相似。但是,如果 OSD 被标记为失效,映射到该 OSD 的任何 PG 都会被重新映射到同一主机上的其他 OSD,导致这些 OSD 相对于其他主机的 OSD 过度利用。此外,如果一台主机上的所有 OSD 都被标记为失效,映射到该主机的映射将失败,导致 PG 规模过小。
只要目标是将在 N 个 OSD 之间分配到 N 个故障域,解决方案就是使用上面的 chooseleaf 变体。但是,考虑一个用例,我们希望在 4 台主机上分配一个 8+6 EC 编码,以容忍一台主机的丢失和另一台主机上 OSD 的丢失,同时具有 1.75 倍的存储开销。规则必须看起来像这样:chooseleaf variant above. However, consider a use case where we want to split an 8+6 EC encoding over 4 hosts in order to tolerate the loss of a host and an OSD on another host with 1.75x storage overhead. The rule would have to look something like:
rule ecpool-86 {
...
step take default class hdd
step choose indep 4 type host
step choose indep 4 type osd
step emit
}
这将最多将 16 个 OSD 分配到 4 台主机(对于 8+6 编码,它会在前 3 台主机上放置 4 个 OSD,在最后一台主机上放置 2 个),并满足我们的故障要求。但是,由于上述原因,如果存在其他主机可以重新平衡,它会在 OSD 被标记为失效时表现不佳。chooseleaf在这里不是解决方案,因为它不支持在指定类型下方映射超过一个叶子节点。
MSR
CRUSH MSR (多步重试) 规则通过使用不同的下降算法来解决这个问题,该算法在遇到失效的 OSD 时重试所有步骤。在经典的 CRUSH 中是广度优先(对于每个步骤,它在进入下一步之前会完全填充向量),MSR 规则是深度优先——对于每个选择,我们会递归地下降所有步骤,然后再继续下一个选择。上述用例可以用以下规则满足:
rule ecpool-86 {
type msr_indep
...
step take default class hdd
step choosemsr 4 type host
step choosemsr 4 type osd
step emit
}
As with the chooseleaf顶部示例,只要还有备用主机,当 OSD 被标记为失效时,这些 OSD 将按比例重新映射到其他主机。有关如何在保留故障域隔离的同时如何工作的详细信息,请参阅 mapper.c:crush_msr_choose 中的注释。
规则结构
CRUSH MSR 规则是具有类型 CRUSH_RULE_TYPE_MSR_FIRSTN 或 CRUSH_RULE_TYPE_MSR_INDEP 的 crush 规则(参见 mapper.c:rule_type_is_msr)。与经典的 crush 规则不同,单个步骤不会指定 firstn 或 indep。输出顺序由整个规则的规则类型定义。
MSR 规则与传统规则有一些结构上的差异:
规则类型决定映射是 FIRSTN 还是 INDEP。由于下降可以重试步骤,步骤单独指定输出顺序并没有太大的意义,而且我并没有意识到有任何用例会从中受益。
MSR 规则must应该被结构化为(可能为空的)config 步骤前缀(CRUSH_RULE_SET_CHOOSE_MSR*)后面跟着一系列 EMIT 块,每个 EMIT 块都由一个 TAKE 步骤、一系列 CHOOSE_MSR 步骤和以一个 EMIT 步骤结束。
MSR 步骤必须choosemsr. choose和chooseleaf是不允许的。
工作空间
MSR 规则对工作空间也有不同的要求。传统的 CRUSH 需要 3 个大小为 result_max 的向量用于工作空间——两个用于交替处理每个规则,另外还有一个chooseleaf。MSR 规则需要 N 个向量,其中 N 是最长 EMIT 块中 eafcf8: choosemsrchoosemsr步骤的数量,因为它需要保留每个下降过程中做出的所有选择。
有关 mapper.h/c:crush_work_size、crush_msr_scan_rule 的详细信息,请参阅。
实现
mapper.h/c:crush_do_rule 在内部分支到 mapper.c:crush_msr_do_rule,用于类型为 CRUSH_RULE_TYPE_MSR_* 的规则(参见 mapper.c:rule_type_is_msr)。
mapper.c 中的 MSR 相关函数用更多关于算法的详细信息进行了注释。
由 Ceph 基金会带给您
Ceph 文档是一个社区资源,由非盈利的 Ceph 基金会资助和托管Ceph Foundation. 如果您想支持这一点和我们的其他工作,请考虑加入现在加入.