跳到内容跳到页面导航:上一页 [access key p]/下一页 [access key n]
documentation.suse.com / SUSE Enterprise Storage 7 文档 / 操作和管理指南 / 在集群中存储数据 / 存储的数据管理
适用范围 SUSE Enterprise Storage 7

17 存储的数据管理

CRUSH 算法通过计算数据存储位置来确定如何存储和检索数据。使用 CRUSH,Ceph 客户端无需通过中心服务器或中介程序,即可直接与 OSD 通讯。借助算法确定的数据存储和检索方法,Ceph 可避免单一故障点、性能瓶颈和可伸缩性物理限制。

CRUSH 需要获取集群的索引,它使用 CRUSH 索引以伪随机的方式在 OSD 中存储和检索数据,并以一致的方式在整个集群中分布数据。

CRUSH 索引包含一个 OSD 列表、一个用于将设备聚合到物理位置的“存储桶”列表,以及一个告知 CRUSH 应如何复制 Ceph 集群存储池中数据的规则列表。通过反映安装的底层物理组织,CRUSH 可对相关设备故障的潜在根源建模,从而解决故障的根源。典型的根源包括物理接近、共用电源和共用网络。通过将这些信息编码到集群索引中,CRUSH 归置策略可将对象副本分隔在不同的故障域中,同时维持所需的分布方式。例如,为了消除可能的并发故障,可能需要确保数据副本位于使用不同机架、机柜、电源、控制器和/或物理位置的设备上。

部署 Ceph 集群后,将会生成默认的 CRUSH 索引。这种模式适合 Ceph 沙箱环境。但是,在部署大规模的数据集群时,强烈建议您考虑创建自定义 CRUSH 索引,因为这样做有助于管理 Ceph 集群、提高性能并确保数据安全。

例如,如果某个 OSD 停机,而您需要使用现场支持或更换硬件,则 CRUSH 索引可帮助您定位到发生 OSD 故障的主机所在的物理数据中心、机房、设备排和机柜。

同样,CRUSH 可以帮助您更快地确定故障。例如,如果特定机柜中的所有 OSD 同时停机,故障可能是由某个网络交换机或者机柜或网络交换机的电源所致,而不是发生在 OSD 自身上。

当与故障主机关联的归置组(请参见第 17.4 节 “归置组”)处于降级状态时,自定义 CRUSH 索引还可帮助您确定 Ceph 存储数据冗余副本的物理位置。

CRUSH 索引包括三个主要部分。

  • OSD 设备包括与 ceph-osd 守护进程对应的任何对象存储设备。

  • 存储桶由存储位置(例如设备排、机柜、主机等)及为其指定的权重的分层聚合组成。

  • 规则集由存储桶选择方式组成。

17.1 OSD 设备

为了将归置组映射到 OSD,CRUSH 索引需要 OSD 设备(OSD 守护进程的名称)的列表。设备列表显示在 CRUSH 索引的最前面。

#devices
device NUM osd.OSD_NAME class CLASS_NAME

例如:

#devices
device 0 osd.0 class hdd
device 1 osd.1 class ssd
device 2 osd.2 class nvme
device 3 osd.3class ssd

一般而言,一个 OSD 守护进程映射到一个磁盘。

17.1.1 设备类型

Ceph 的优势之一是 CRUSH 索引能够灵活控制数据归置。这也是集群最难管理的环节之一。设备类型会自动对 CRUSH 索引执行最常见的更改,以前这些更改都需要由管理员手动完成。

17.1.1.1 CRUSH 管理问题

Ceph 集群常由多种存储设备构建而成:HDD、SSD、NVMe,甚至是以上这些类型的混合。我们将这些不同的存储设备类型称为设备类型,以避免与 CRUSH 桶的类型属性(例如 host、rack 和 row,请参见第 17.2 节 “存储桶”了解更多详细信息)产生混淆。受 SSD 支持的 Ceph OSD 比受旋转磁盘支持的 OSD 速度快得多,因此更适合特定工作负载。借助 Ceph,您可轻松为不同数据集或工作负载创建 RADOS 存储池,以及指定不同的 CRUSH 规则来控制这些存储池的数据归置。

具有混合设备类型的 OSD
图 17.1︰ 具有混合设备类型的 OSD

不过,通过设置 CRUSH 规则将数据仅归置到特定类型的设备这个过程十分枯燥。规则是针对 CRUSH 层次结构运作的,但如果将某些设备混合到同一主机或机柜中(如上面的层次结构示例所示),则这些设备默认会混合在一起并显示在层次结构的同一子树中。要手动将它们分隔到单独的树中,需要针对先前版本的 SUSE Enterprise Storage 中的每个设备类型,为每个中间节点创建多个版本。

17.1.1.2 设备类型

Ceph 提供了一个较佳的解决方案,就是为每个 OSD 添加一个名为设备类型的属性。默认情况下,OSD 会根据 Linux 内核所公开的硬件属性,自动将自己的设备类型设置为“hdd”、“ssd”或“nvme”。ceph osd tree 命令输出的新列中会报告这些设备类型:

cephuser@adm > ceph osd tree
 ID CLASS WEIGHT   TYPE NAME      STATUS REWEIGHT PRI-AFF
 -1       83.17899 root default
 -4       23.86200     host cpach
 2   hdd  1.81898         osd.2      up  1.00000 1.00000
 3   hdd  1.81898         osd.3      up  1.00000 1.00000
 4   hdd  1.81898         osd.4      up  1.00000 1.00000
 5   hdd  1.81898         osd.5      up  1.00000 1.00000
 6   hdd  1.81898         osd.6      up  1.00000 1.00000
 7   hdd  1.81898         osd.7      up  1.00000 1.00000
 8   hdd  1.81898         osd.8      up  1.00000 1.00000
 15  hdd  1.81898         osd.15     up  1.00000 1.00000
 10  nvme 0.93100         osd.10     up  1.00000 1.00000
 0   ssd  0.93100         osd.0      up  1.00000 1.00000
 9   ssd  0.93100         osd.9      up  1.00000 1.00000

如果设备类型自动检测失败(例如由于未通过 /sys/block 正确向设备驱动程序公开设备的相关信息而导致失败),您可以使用命令行调整设备类型:

cephuser@adm > ceph osd crush rm-device-class osd.2 osd.3
done removing class of osd(s): 2,3
cephuser@adm > ceph osd crush set-device-class ssd osd.2 osd.3
set osd(s) 2,3 to class 'ssd'

17.1.1.3 设置 CRUSH 归置规则

CRUSH 规则可限制对特定设备类型执行归置操作。例如,您可以通过运行以下命令来创建仅将数据分布在 SSD 磁盘上的“fast”副本存储池:

cephuser@adm > ceph osd crush rule create-replicated RULE_NAME ROOT FAILURE_DOMAIN_TYPE DEVICE_CLASS

例如:

cephuser@adm > ceph osd crush rule create-replicated fast default host ssd

创建名为“fast_pool”的存储池并将其分配给“fast”规则:

cephuser@adm > ceph osd pool create fast_pool 128 128 replicated fast

创建纠删码规则的过程略有不同。首先,创建包含所需设备类型对应属性的纠删码配置。然后,在创建纠删码存储池时使用该配置:

cephuser@adm > ceph osd erasure-code-profile set myprofile \
 k=4 m=2 crush-device-class=ssd crush-failure-domain=host
cephuser@adm > ceph osd pool create mypool 64 erasure myprofile

为应对您需要手动编辑 CRUSH 索引来自定义规则的情况,该语法已经过扩展,允许指定设备类型。例如,上述命令生成的 CRUSH 规则如下所示:

rule ecpool {
  id 2
  type erasure
  min_size 3
  max_size 6
  step set_chooseleaf_tries 5
  step set_choose_tries 100
  step take default class ssd
  step chooseleaf indep 0 type host
  step emit
}

此处的重要差别是“take”命令包含额外的“class CLASS_NAME”后缀。

17.1.1.4 其他命令

要列出 CRUSH 索引中使用的设备类型,请运行以下命令:

cephuser@adm > ceph osd crush class ls
[
  "hdd",
  "ssd"
]

要列出现有的 CRUSH 规则,请运行以下命令:

cephuser@adm > ceph osd crush rule ls
replicated_rule
fast

要查看名为“fast”的 CRUSH 规则的详细信息,请运行以下命令:

cephuser@adm > ceph osd crush rule dump fast
{
		"rule_id": 1,
		"rule_name": "fast",
		"ruleset": 1,
		"type": 1,
		"min_size": 1,
		"max_size": 10,
		"steps": [
						{
										"op": "take",
										"item": -21,
										"item_name": "default~ssd"
						},
						{
										"op": "chooseleaf_firstn",
										"num": 0,
										"type": "host"
						},
						{
										"op": "emit"
						}
		]
}

要列出属于“ssd”类型的 OSD,请运行以下命令:

cephuser@adm > ceph osd crush class ls-osd ssd
0
1

17.1.1.5 从旧版 SSD 规则迁移到设备类型

在早于版本 5 的 SUSE Enterprise Storage 中,要写入适用于设备的规则,您需要手动编辑 CRUSH 索引并为每个具体的设备类型(例如 SSD)维护并行的层次结构。自 SUSE Enterprise Storage 5 起,设备类型特性透明地实现了这一目的。

您可以使用 crushtool 命令将旧版规则和层次结构转换为基于类型的新版规则。系统提供以下几种转换类型:

crushtool --reclassify-root ROOT_NAME DEVICE_CLASS

此命令会获取 ROOT_NAME 下的层次结构中的所有内容,并将通过

take ROOT_NAME

引用该根的所有规则调整为

take ROOT_NAME class DEVICE_CLASS

它会对存储桶重新编号,以便为指定类型的“shadow tree”使用旧 ID。因此,数据不会发生移动。

例 17.1︰ crushtool --reclassify-root

假设有以下现有规则:

rule replicated_ruleset {
   id 0
   type replicated
   min_size 1
   max_size 10
   step take default
   step chooseleaf firstn 0 type rack
   step emit
}

如果您将根“default”重新分类为“hdd”类型,规则将变为

rule replicated_ruleset {
   id 0
   type replicated
   min_size 1
   max_size 10
   step take default class hdd
   step chooseleaf firstn 0 type rack
   step emit
}
crushtool --set-subtree-class BUCKET_NAME DEVICE_CLASS

此方法会将根目录为 BUCKET_NAME 的子树中的每个设备标记为指定的设备类型。

--set-subtree-class 通常与 --reclassify-root 选项结合使用,以确保该根中的所有设备均标为正确的类型。不过,其中一些设备可能特意使用了不同的类型,因此您不需要重新对它们进行标记。在此类情况下,请勿使用 --set-subtree-class 选项。请记住,这样的重新映射并不完美,因为之前的规则是跨多个类型的设备分发的,而调整后的规则将仅映射到指定设备类型的设备。

crushtool --reclassify-bucket MATCH_PATTERN DEVICE_CLASS DEFAULT_PATTERN

此方法允许将特定于类型的并行层次结构与常规层次结构合并。例如,许多用户会有类似以下的 CRUSH 索引:

例 17.2︰ crushtool --reclassify-bucket
host node1 {
   id -2           # do not change unnecessarily
   # weight 109.152
   alg straw
   hash 0  # rjenkins1
   item osd.0 weight 9.096
   item osd.1 weight 9.096
   item osd.2 weight 9.096
   item osd.3 weight 9.096
   item osd.4 weight 9.096
   item osd.5 weight 9.096
   [...]
}

host node1-ssd {
   id -10          # do not change unnecessarily
   # weight 2.000
   alg straw
   hash 0  # rjenkins1
   item osd.80 weight 2.000
   [...]
}

root default {
   id -1           # do not change unnecessarily
   alg straw
   hash 0  # rjenkins1
   item node1 weight 110.967
   [...]
}

root ssd {
   id -18          # do not change unnecessarily
   # weight 16.000
   alg straw
   hash 0  # rjenkins1
   item node1-ssd weight 2.000
   [...]
}

此函数会将与给定模式相匹配的每个存储桶重新分类。模式的格式可能为 %suffixprefix%。在上面的示例中,您需要使用 %-ssd 模式。对于每个匹配的存储桶,与“%”通配符相匹配的名称的其余部分指定了基本存储桶。所匹配存储桶中的所有设备都会标记为指定的设备类型,随后会移至基本存储桶中。如果基本存储桶不存在(例如,如果“node12-ssd”存在,但“node12”不存在),则系统会创建基本存储桶,并将其关联到指定的默认父存储桶下。系统会为新的阴影存储桶保留旧的存储桶 ID,以防数据移动。系统会对包含引用旧存储桶的 take 步骤的规则进行调整。

crushtool --reclassify-bucket BUCKET_NAME DEVICE_CLASS BASE_BUCKET

您可以使用不包含通配符的 --reclassify-bucket 选项来映射单个存储桶。例如,在上面的示例中,我们希望将“ssd”存储桶映射到默认存储桶。

用于转换由上述片段组成的索引的最后一个命令将如下所示:

cephuser@adm > ceph osd getcrushmap -o original
cephuser@adm > crushtool -i original --reclassify \
  --set-subtree-class default hdd \
  --reclassify-root default hdd \
  --reclassify-bucket %-ssd ssd default \
  --reclassify-bucket ssd ssd default \
  -o adjusted

要确认转换是否正确,可以使用 --compare 选项。该选项会测试大量对 CRUSH 索引的输入,并比较是否会产生相同的结果。这些输入通过适用于 --test 的相同选项来控制。对于上面的示例,命令将如下所示:

cephuser@adm > crushtool -i original --compare adjusted
rule 0 had 0/10240 mismatched mappings (0)
rule 1 had 0/10240 mismatched mappings (0)
maps appear equivalent
提示
提示

如果存在差异,括号中将会显示重新映射的输入比率。

如果您对调整后的 CRUSH 索引满意,便可将其应用于集群:

cephuser@adm > ceph osd setcrushmap -i adjusted

17.1.1.6 详细信息

有关 CRUSH 索引的更多详细信息,请参见第 17.5 节 “CRUSH 索引操作”

有关 Ceph 存储池的更多一般详细信息,请参见第 18 章 “管理存储池

有关纠删码存储池的更多详细信息,请参见第 19 章 “纠删码存储池

17.2 存储桶

CRUSH 索引包含 OSD 的列表,可将这些 OSD 组织成存储桶的树形结构排列形式,以便将设备聚合到物理位置。单个 OSD 构成树形结构中的树叶。

0

osd

特定的设备或 OSD(osd.1osd.2 等)。

1

host

包含一个或多个 OSD 的主机的主机名。

2

chassis

机架中包含该 host 的机箱的标识符。

3

rack

计算机机柜。默认值为 unknownrack

4

row

由一系列机柜组成的设备排。

5

pdu

“Power Distribution Unit”(电源分配单元)的缩写。

6

pod

“Point of Delivery”(分发点)的缩写。在此环境中为一组 PDU 或一组机架排。

7

room

包含多排机架的房间。

8

datacenter

包含一个或多个房间的物理数据中心。

9

region

全球的地理地区(例如 NAM、LAM、EMEA、APAC 等)

10

root

OSD 存储桶的树形结构根节点(通常设为 default)。

提示
提示

您可以修改现有类型,以及创建自己的存储桶类型。

Ceph 的部署工具可生成 CRUSH 索引,其中包含每个主机的存储桶,以及名为“default”的根(可用于默认的 rbd 存储池)。剩余的存储桶类型提供了一种存储有关节点/存储桶的物理位置信息的方法,当 OSD、主机或网络硬件发生故障,并且管理员需要访问物理硬件时,这种方法可大大简化集群管理工作。

存储桶具有类型、唯一的名称(字符串)、以负整数表示的唯一 ID、相对于其项目总容量/权限的权重、存储桶算法(默认为 straw2)和哈希(默认为 0,代表 CRUSH 哈希 rjenkins1)。一个存储桶可以包含一个或多个项目。项目可由其他存储桶或 OSD 组成。项目可能会有一个权重来反映该项目的相对权重。

[bucket-type] [bucket-name] {
  id [a unique negative numeric ID]
  weight [the relative capacity/capability of the item(s)]
  alg [the bucket type: uniform | list | tree | straw2 | straw ]
  hash [the hash type: 0 by default]
  item [item-name] weight [weight]
}

下面的示例说明如何使用存储桶来聚合存储池,以及诸如数据中心、机房、机柜和设备排的物理位置。

host ceph-osd-server-1 {
        id -17
        alg straw2
        hash 0
        item osd.0 weight 0.546
        item osd.1 weight 0.546
}

row rack-1-row-1 {
        id -16
        alg straw2
        hash 0
        item ceph-osd-server-1 weight 2.00
}

rack rack-3 {
        id -15
        alg straw2
        hash 0
        item rack-3-row-1 weight 2.00
        item rack-3-row-2 weight 2.00
        item rack-3-row-3 weight 2.00
        item rack-3-row-4 weight 2.00
        item rack-3-row-5 weight 2.00
}

rack rack-2 {
        id -14
        alg straw2
        hash 0
        item rack-2-row-1 weight 2.00
        item rack-2-row-2 weight 2.00
        item rack-2-row-3 weight 2.00
        item rack-2-row-4 weight 2.00
        item rack-2-row-5 weight 2.00
}

rack rack-1 {
        id -13
        alg straw2
        hash 0
        item rack-1-row-1 weight 2.00
        item rack-1-row-2 weight 2.00
        item rack-1-row-3 weight 2.00
        item rack-1-row-4 weight 2.00
        item rack-1-row-5 weight 2.00
}

room server-room-1 {
        id -12
        alg straw2
        hash 0
        item rack-1 weight 10.00
        item rack-2 weight 10.00
        item rack-3 weight 10.00
}

datacenter dc-1 {
        id -11
        alg straw2
        hash 0
        item server-room-1 weight 30.00
        item server-room-2 weight 30.00
}

root data {
        id -10
        alg straw2
        hash 0
        item dc-1 weight 60.00
        item dc-2 weight 60.00
}

17.3 规则集

CRUSH 索引支持“CRUSH 规则”概念,这些规则确定存储池的数据归置。对于大型集群,您可能会创建许多存储池,其中每个存储池各自可能具有自己的 CRUSH 规则组和规则。默认 CRUSH 索引具有适用于默认根的规则。如果您想使用更多根和更多规则,则需稍后自行创建,或者在创建新存储池时让系统自动创建。

注意
注意

大多数情况下,无需修改默认规则。创建新存储池时,该存储池的默认规则组为 0。

规则采用以下格式:

rule rulename {

        ruleset ruleset
        type type
        min_size min-size
        max_size max-size
        step step

}
ruleset

一个整数。将规则分类,使其属于一个规则组。通过在存储池中设置规则组来激活。必须指定此选项。默认值为 0

type

一个字符串。描述了适用于“副本”或“纠删码”存储池的规则。必须指定此选项。默认值为 replicated

min_size

一个整数。如果存储池组创建的副本数小于此数字,CRUSH 将不选择此规则。必须指定此选项。默认值为 2

max_size

一个整数。如果存储池组创建的副本数大于此数字,CRUSH 将不选择此规则。必须指定此选项。默认值为 10

step take bucket

采用以名称指定的存储桶,并开始在树中向下迭代。必须指定此选项。有关在树中迭代的说明,请参见第 17.3.1 节 “迭代节点树”

step targetmodenum type bucket-type

target 可以是 choosechooseleaf。如果设置为 choose,则会选择许多存储桶。chooseleaf 直接从存储桶集的每个存储桶的子树中选择 OSD(叶节点)。

mode 可以是 firstnindep。请参见第 17.3.2 节 “firstn 和 indep

选择给定类型的存储桶的数量。其中,N 是可用选项的数量,如果 num > 0 且 < N,则选择该数量的存储桶;如果 num < 0,则表示 N - num;如果 num == 0,则选择 N 个存储桶(全部可用)。跟在 step takestep choose 后使用。

step emit

输出当前值并清空堆栈。通常在规则的末尾使用,但也可在同一规则中用来构成不同的树。跟在 step choose 后使用。

17.3.1 迭代节点树

可采用节点树的形式来查看使用存储桶定义的结构。在此树中,存储桶是节点,OSD 是叶。

CRUSH 索引中的规则定义如何从此树中选择 OSD。规则从某个节点开始,然后在树中向下迭代,以返回一组 OSD。无法定义需要选择哪个分支。CRUSH 算法可确保 OSD 集能够满足复制要求并均衡分布数据。

使用 step take bucket 时,节点树中的迭代从给定的存储桶(而不是存储桶类型)开始。如果要返回树中所有分支上的 OSD,该存储桶必须是根存储桶。否则,以下步骤只会在子树中迭代。

完成 step take 后,接下来会执行规则定义中的一个或多个 step choose 项。每个 step choose 项从前面选定的上层节点中选择定义数量的节点(或分支)。

最后,使用 step emit 返回选定的 OSD。

step chooseleaf 是一个便捷函数,可直接从给定存储桶的分支中选择 OSD。

图 17.2 “示例树”中提供了说明如何使用 step 在树中迭代的示例。在下面的规则定义中,橙色箭头和数字与 example1aexample1b 对应,蓝色箭头和数字与 example2 对应。

示例树
图 17.2︰ 示例树
# orange arrows
rule example1a {
        ruleset 0
        type replicated
        min_size 2
        max_size 10
        # orange (1)
        step take rack1
        # orange (2)
        step choose firstn 0 host
        # orange (3)
        step choose firstn 1 osd
        step emit
}

rule example1b {
        ruleset 0
        type replicated
        min_size 2
        max_size 10
        # orange (1)
        step take rack1
        # orange (2) + (3)
        step chooseleaf firstn 0 host
        step emit
}

# blue arrows
rule example2 {
        ruleset 0
        type replicated
        min_size 2
        max_size 10
        # blue (1)
        step take room1
        # blue (2)
        step chooseleaf firstn 0 rack
        step emit
}

17.3.2 firstn 和 indep

CRUSH 规则定义有故障节点或 OSD 的替换项(请参见第 17.3 节 “规则集”)。关键字 step 要求使用 firstnindep 参数。图 17.3 “节点替换方法”提供了示例。

firstn 将替换节点添加到工作节点列表的末尾。如果某个节点发生故障,其后的正常节点会移位到左侧,以填充有故障节点留下的空缺。这是副本存储池的默认方法,也是需要采取的方法,因为次要节点已包含所有数据,因此可立即接管主要节点的职责。

indep 为每个工作节点选择固定的替换节点。替换有故障节点不会更改剩余节点的顺序。这对于纠删码存储池而言是所需的行为。在纠删码存储池中,节点上存储的数据取决于在选择节点时它所在的位置。如果节点的顺序发生变化,受影响节点上的所有数据都需要重新放置。

节点替换方法
图 17.3︰ 节点替换方法

17.4 归置组

Ceph 会将对象映射到归置组 (PG)。归置组是指逻辑对象存储池的分片或片段,可将对象以组形式归置到 OSD 中。归置组可减少 Ceph 将数据存储到 OSD 中时每个对象的元数据量。如果归置组的数量较多(例如,每个 OSD 有 100 个归置组),将能实现较佳的平衡。

17.4.1 使用归置组

归置组 (PG) 聚合了存储池内的对象。主要原因是基于每个对象来跟踪对象归置和元数据的计算成本较高。例如,包含数百万个对象的系统无法直接跟踪各个对象的归置。

存储池中的归置组
图 17.4︰ 存储池中的归置组

Ceph 客户端负责计算对象将属于哪个归置组。它会对对象 ID 进行哈希处理,并根据所定义存储池中的 PG 数及存储池的 ID 来应用操作。

归置组内的对象内容存储在一组 OSD 中。例如,在大小为 2 的副本存储池中,每个归置组将对象存储到两个 OSD 中:

归置组和 OSD
图 17.5︰ 归置组和 OSD

如果 OSD 2 发生故障,则系统会将另一个 OSD 指定给归置组 1,并在该 OSD 中填充 OSD 1 内所有对象的副本。如果存储池大小从 2 变为 3,则系统会向归置组另外再分配一个 OSD,并在该 OSD 中填充归置组内所有对象的副本。

归置组并不拥有 OSD,它们与同一存储池甚至其他存储池内的其他归置组共享 OSD。如果 OSD 2 发生故障,归置组 2 也将需要使用 OSD 3 来恢复对象的副本。

当归置组的数量增加时,系统会向新归置组分配 OSD。CRUSH 函数的结果也会发生更改,而且系统会将之前的归置组的部分对象复制到新归置组并将它们从旧归置组删除。

17.4.2 确定 PG_NUM 的值

注意
注意

从 Ceph Nautilus (v14.x) 开始,您可以使用 Ceph Manager pg_autoscaler 模块根据需要自动扩展 PG。如果要启用此功能,请参考第 6.1.1.1 节 “Default PG and PGP counts”

创建新存储池时,您仍可手动选择 PG_NUM 的值:

root # ceph osd pool create POOL_NAME PG_NUM

PG_NUM 无法自动计算得出。以下是一些常用的值,选择哪个值取决于集群中的 OSD 数量:

少于 5 个 OSD:

PG_NUM 设置为 128。

5 到 10 个 OSD:

PG_NUM 设置为 512。

10 到 50 个 OSD:

PG_NUM 设置为 1024。

随着 OSD 数量的增加,选择正确的 PG_NUM 值也变得愈加重要。PG_NUM 对集群的行为以及 OSD 发生故障时的数据持久性具有很大影响。

17.4.2.1 计算超过 50 个 OSD 的归置组

如果 OSD 数量低于 50,请使用第 17.4.2 节 “确定 PG_NUM 的值”中所述的预选值。如果 OSD 数量超过 50,建议为每个 OSD 使用约 50 到 100 个归置组,以平衡资源的使用、数据持久性和数据分布。对于单个对象存储池,您可以使用以下公式来计算基线数量:

total PGs = (OSDs * 100) / POOL_SIZE

其中,POOL_SIZE 是副本的个数(如果是副本存储池)或 ceph osd erasure-code-profile get 命令所返回的“k”和“m”之和(如果是纠删码存储池)。应将结果舍入到最接近的 2 的幂。对于 CRUSH 算法,建议进行舍入,以便均衡归置组之间的对象数。

例如,如果集群包含 200 个 OSD 和大小为 3 个副本的存储池,您需要按如下方式预估 PG 数:

          (200 * 100) / 3 = 6667

最接近的 2 的幂为 8192

使用多个数据存储池存储对象时,您需要确保在每个存储池的归置组数与每个 OSD 的归置组数之间取得平衡。您需要采用合理的归置组总数,在不过度占用系统资源或导致互联过程过慢的前提下,确保每个 OSD 的差异保持在合理的较低水平。

例如,如果集群包含 10 个存储池,每个存储池有 512 个归置组(位于 10 个 OSD 中),则表示共有 5,120 个归置组分布于 10 个 OSD 中,即每个 OSD 有 512 个归置组。这样的设置不会使用过多资源。但是,如果创建了 1000 个存储池,且每个存储池有 512 个归置组,那么每个 OSD 需要处理约 50,000 个归置组,这样完成互联所需的资源和时间便会显著增加。

17.4.3 设置归置组数量

注意
注意

从 Ceph Nautilus (v14.x) 开始,您可以使用 Ceph Manager pg_autoscaler 模块根据需要自动扩展 PG。如果要启用此功能,请参考第 6.1.1.1 节 “Default PG and PGP counts”

如果您仍需手动指定存储池中的归置组数量,则需要在创建存储池时指定(请参见第 18.1 节 “创建存储池”)。为存储池设置归置组后,您可以运行以下命令来增加归置组的数量:

root # ceph osd pool set POOL_NAME pg_num PG_NUM

增加归置组数量后,您还需要增加要归置的归置组数量 (PGP_NUM),以便您的集群重新达到平衡。PGP_NUM 是考虑要通过 CRUSH 算法归置的归置组数。增加 PG_NUM 会分割归置组,但在增加 PGP_NUM 之前数据不会迁移到较新的归置组。PGP_NUM 应等于 PG_NUM。要增加应归置的归置组数量,请运行以下命令:

root # ceph osd pool set POOL_NAME pgp_num PGP_NUM

17.4.4 获取归置组数量

要获取存储池中的归置组数量,请运行以下 get 命令:

root # ceph osd pool get POOL_NAME pg_num

17.4.5 获取集群的 PG 统计数据

要获取集群内归置组的统计数据,请运行以下命令:

root # ceph pg dump [--format FORMAT]

有效格式为“plain”(默认值)和“json”。

17.4.6 获取卡住的 PG 统计数据

要获取所有卡在指定状态的归置组的统计数据,请运行以下命令:

root # ceph pg dump_stuck STATE \
 [--format FORMAT] [--threshold THRESHOLD]

可能的状态有:“inactive”(PG 由于在等待拥有最新数据的 OSD 恢复启用状态而无法处理读取或写入)、“unclean”(PG 包含未复制所需次数的对象)、“stale”(PG 处于未知状态,即托管 PG 的 OSD 未在 mon_osd_report_timeout 选项所指定的时间间隔内向 Monitor 集群报告相关信息)、“undersized”或“degraded”。

有效格式为“plain”(默认值)和“json”。

该阈值定义归置组至少卡住多少秒(默认为 300 秒)后系统会将其包含到返回的统计数据中。

17.4.7 搜索归置组索引

要搜索特定归置组的索引,请运行以下命令:

root # ceph pg map PG_ID

Ceph 将返回归置组索引、归置组和 OSD 状态:

root # ceph pg map 1.6c
osdmap e13 pg 1.6c (1.6c) -> up [1,0] acting [1,0]

17.4.8 检索归置组统计数据

要检索特定归置组的统计数据,请运行以下命令:

root # ceph pg PG_ID query

17.4.9 洗刷归置组

要洗刷(第 17.6 节 “洗刷归置组”)归置组,请运行以下命令:

root # ceph pg scrub PG_ID

Ceph 会检查主节点和副本节点、生成归置组内所有对象的编目,并对它们进行比较,以确保没有缺少或不匹配的对象且对象的内容均一致。假设所有副本均匹配,最后的语义整理便可确保所有与快照相关的对象元数据均一致。错误通过日志来报告。

17.4.10 设置归置组回填和恢复的优先顺序

您可能会遇到数个归置组需要恢复和/或回填,而其中一些归置组存储的数据比其他归置组更为重要的情况。例如,这些 PG 可能存储着运行中计算机所使用的映像数据,其他 PG 则可能存储的是由非活跃计算机使用的数据或相关度较低的数据。在该情况下,您可能需要优先恢复这些归置组,以便更早地恢复存储在这些归置组中的数据的性能和可用性。要将特定归置组标记为在回填或恢复过程中优先处理,请运行以下命令:

root # ceph pg force-recovery PG_ID1 [PG_ID2 ... ]
root # ceph pg force-backfill PG_ID1 [PG_ID2 ... ]

这将导致 Ceph 先对指定归置组执行恢复或回填,然后再处理其他归置组。这并不会中断当前正在进行的回填或恢复,而是会使指定的 PG 尽快得到处理。如果您改变了主意或将错误的归置组设为优先处理,请使用以下命令取消优先顺序:

root # ceph pg cancel-force-recovery PG_ID1 [PG_ID2 ... ]
root # ceph pg cancel-force-backfill PG_ID1 [PG_ID2 ... ]

cancel-* 命令会删除 PG 的“force”标志,使其按默认顺序接受处理。同样,这并不会影响当前正在处理的归置组,只会影响仍在排队的归置组。完成归置组恢复或回填后,系统即会自动清除“force”标志。

17.4.11 还原丢失的对象

如果集群丢失了一个或多个对象,而您已决定放弃搜索丢失的数据,则需要将未找到的对象标记为“lost”。

如果在查询过所有可能的位置后仍未找到这些对象,您可能需要放弃这些丢失的对象。这可能是由于几种故障同时发生(这种情况很少见)导致的,致使集群在写入本身恢复之前便得知写入已执行。

目前唯一支持的选项为“revert”,该选项会回滚到对象的先前版本,或在有新对象时完全忽略丢失的对象。要将“未找到”的对象标记为“lost”,请运行以下命令:

  cephuser@adm > ceph pg PG_ID mark_unfound_lost revert|delete

17.4.12 启用 PG 自动扩展器

归置组 (PG) 是 Ceph 分布数据方式的详细内部实现。通过启用 PG 自动扩展功能,您可以允许集群根据集群的使用情况创建或自动调整 PG。

系统中的每个存储池都有一个 pg_autoscale_mode 属性,可将其设为 offonwarn

自动扩展器按存储池配置,可在以下三种模式下运行:

off

为此存储池禁用自动扩展功能。由管理员为每个存储池选择合适的 PG 数量。

on

为给定存储池启用 PG 计数自动调整功能。

warn

一旦应调整 PG 计数,系统将发出运行状况告警。

要为现有存储池设置自动扩展模式,请运行以下命令:

cephuser@adm > ceph osd pool set POOL_NAME pg_autoscale_mode mode

您也可以运行以下命令,以配置将应用于日后创建的所有存储池的默认 pg_autoscale_mode

cephuser@adm > ceph config set global osd_pool_default_pg_autoscale_mode MODE

您可以运行以下命令来查看每个存储池、它的相关使用情况,以及对 PG 计数的任何更改建议:

cephuser@adm > ceph osd pool autoscale-status

17.5 CRUSH 索引操作

本节介绍基本的 CRUSH 索引操作方法,例如编辑 CRUSH 索引、更改 CRUSH 索引参数,以及添加/移动/删除 OSD。

17.5.1 编辑 CRUSH 索引

要编辑现有的 CRUSH 索引,请执行以下操作:

  1. 获取 CRUSH 索引。要获取集群的 CRUSH 索引,请执行以下命令:

    cephuser@adm > ceph osd getcrushmap -o compiled-crushmap-filename

    Ceph 会将编译的 CRUSH 索引输出 (-o) 到您指定名称的文件。由于该 CRUSH 索引采用编译格式,您必须先将其反编译,然后才能对其进行编辑。

  2. 反编译 CRUSH 索引。要反编译 CRUSH 索引,请执行以下命令:

    cephuser@adm > crushtool -d compiled-crushmap-filename \
     -o decompiled-crushmap-filename

    Ceph 将对已编译的 CRUSH 索引进行反编译 (-d),并将其输出 (-o) 到您指定名称的文件。

  3. 至少编辑“设备”、“存储桶”和“规则”中的其中一个参数。

  4. 编译 CRUSH 索引。要编译 CRUSH 索引,请执行以下命令:

    cephuser@adm > crushtool -c decompiled-crush-map-filename \
     -o compiled-crush-map-filename

    Ceph 会将编译的 CRUSH 索引存储到您指定名称的文件。

  5. 设置 CRUSH 索引。要设置集群的 CRUSH 索引,请执行以下命令:

    cephuser@adm > ceph osd setcrushmap -i compiled-crushmap-filename

    Ceph 将输入您所指定文件名的已编译 CRUSH 索引,作为集群的 CRUSH 索引。

提示
提示:使用版本控制系统

请为导出并修改过的 CRUSH 索引文件使用 git 或 svn 这样的版本控制系统。这可以让可能发生的回滚变得简单。

提示
提示:测试新 CRUSH 索引

请使用 crushtool --test 命令测试经过调整的新 CRUSH 索引,并与应用新 CRUSH 索引之前的状态进行比较。以下命令开关十分有用:--show-statistics--show-mappings--show-bad-mappings--show-utilization--show-utilization-all--show-choose-tries

17.5.2 添加或移动 OSD

要在运行中集群的 CRUSH 索引中添加或移动 OSD,请执行以下命令:

cephuser@adm > ceph osd crush set id_or_name weight root=pool-name
bucket-type=bucket-name ...
id

一个整数。OSD 的数字 ID。必须指定此选项。

name

一个字符串。OSD 的全名。必须指定此选项。

weight

一个双精度值。OSD 的 CRUSH 权重。必须指定此选项。

root

一个键/值对。默认情况下,CRUSH 层次结构包含 default 存储池作为根。必须指定此选项。

bucket-type

键/值对。可在 CRUSH 层次结构中指定 OSD 的位置。

下面的示例将 osd.0 添加到层次结构,或移动之前某个位置的 OSD。

cephuser@adm > ceph osd crush set osd.0 1.0 root=data datacenter=dc1 room=room1 \
row=foo rack=bar host=foo-bar-1

17.5.3 ceph osd reweightceph osd crush reweight 之间的差异

有两个相似的命令都可更改 Ceph OSD 的权重。它们的使用情境不同,可能会造成混淆。

17.5.3.1 ceph osd reweight

用法:

cephuser@adm > ceph osd reweight OSD_NAME NEW_WEIGHT

ceph osd reweight 用于对 Ceph OSD 设置覆盖权重。此值介于 0 到 1 之间,会强制 CRUSH 重新放置将以其他方式存储于此驱动器上的数据。该命令不会更改为 OSD 上方的存储桶指定的权重,它是一种在正常 CRUSH 分布出现问题时的纠正措施。例如,如果您的其中一个 OSD 处于 90%,而其他 OSD 处于 40%,则您可缩小此权重,以尝试对其进行补偿。

注意
注意:OSD 权重是暂时的

请注意,ceph osd reweight 并非永久性设置。当某个 OSD 被标记为“out”时,它的权重会被设置为 0,当它一旦重新被标记为“in”,其权重又会更改为 1。

17.5.3.2 ceph osd crush reweight

用法:

cephuser@adm > ceph osd crush reweight OSD_NAME NEW_WEIGHT

ceph osd crush reweight 用于设置 OSD 的 CRUSH 权重。此权重可以是任意值(通常是以 TB 为单位的磁盘大小),用于控制系统尝试分配给 OSD 的数据量。

17.5.4 删除 OSD

要从运行中集群的 CRUSH 索引中删除 OSD,请执行以下命令:

cephuser@adm > ceph osd crush remove OSD_NAME

17.5.5 添加存储桶

要向运行中集群的 CRUSH 索引添加某个存储桶,请执行 ceph osd crush add-bucket 命令:

cephuser@adm > ceph osd crush add-bucket BUCKET_NAME BUCKET_TYPE

17.5.6 移动存储桶

要将某个存储桶移到 CRUSH 索引层次结构中的不同位置,请执行以下命令:

cephuser@adm > ceph osd crush move BUCKET_NAME BUCKET_TYPE=BUCKET_NAME [...]

例如:

cephuser@adm > ceph osd crush move bucket1 datacenter=dc1 room=room1 row=foo rack=bar host=foo-bar-1

17.5.7 删除存储桶

要从 CRUSH 索引层次结构中删除某个存储桶,请执行以下命令:

cephuser@adm > ceph osd crush remove BUCKET_NAME
注意
注意:仅限空存储桶

从 CRUSH 层次结构中只能删除空存储桶。

17.6 洗刷归置组

除了为对象创建多个副本外,Ceph 还可通过洗刷归置组来确保数据完整性(请参见第 1.3.2 节 “归置组”了解有关归置组的详细信息)。Ceph 的洗刷类似于在对象存储层运行 fsck。对于每个归置组,Ceph 都会生成一个包含所有对象的编目,并比较每个主对象及其副本,以确保不会有缺失或不匹配的对象。每天的浅层洗刷会检查对象大小和属性,而每周的深层洗刷则会读取数据并使用校验和来确保数据完整性。

洗刷对于维护数据完整性非常重要,但该操作可能会降低性能。您可以通过调整以下设置来增加或减少洗刷操作:

osd max scrubs

同时针对一个 Ceph OSD 执行的洗刷操作数量上限。默认值为 1。

osd scrub begin hourosd scrub end hour

按小时定义的一天内可以执行洗刷的时间段(0 到 24)。默认开始时间为 0,结束时间为 24。

重要
重要

如果归置组的洗刷间隔超出 osd scrub max interval 设置的值,则无论您定义了何种洗刷时间段,都将执行洗刷。

osd scrub during recovery

允许恢复期间执行洗刷。如果将此选项设置为“false”,则当存在工作的恢复进程时,将禁止安排新的洗刷。已在运行的洗刷将继续执行。此选项有助于降低忙碌集群上的负载。默认值为“true”。

osd scrub thread timeout

洗刷线程超时前的最长时间(以秒为单位)。默认值为 60。

osd scrub finalize thread timeout

洗刷完成线程超时前的最长时间(以秒为单位)。默认值为 60*10。

osd scrub load threshold

规范化的最大负载。当系统负载(由 getloadavg()online cpus 数量之比定义)高于此数字时,Ceph 将不会执行洗刷。默认值为 0.5。

osd scrub min interval

当 Ceph 集群负载较低时洗刷 Ceph OSD 的最短间隔(以秒为单位)。默认值为 60*60*24(一天一次)。

osd scrub max interval

无论集群负载如何都洗刷 Ceph OSD 的最长间隔(以秒为单位)。默认值为 7*60*60*24(一周一次)。

osd scrub chunk min

单次操作期间要洗刷的对象存储块数量下限。洗刷期间,Ceph 会阻止向单个块写入数据。默认值为 5。

osd scrub chunk max

单次操作期间要洗刷的对象存储块数量上限。默认值为 25。

osd scrub sleep

洗刷下一组块之前休眠的时间。增大此值会降低整个洗刷操作的速度,但对客户端操作的影响较小。默认值为 0。

osd deep scrub interval

深层洗刷(完整读取所有数据)的间隔。osd scrub load threshold 选项不会影响此设置。默认值为 60*60*24*7(一周一次)。

osd scrub interval randomize ratio

在安排归置组的下一次洗刷作业时,为 osd scrub min interval 值增加一个随机延迟。该延迟为一个随机的值,小于 osd scrub min interval * osd scrub interval randomized ratio 所得结果。因此,该默认设置实际上是将洗刷随机地安排在允许的时间段 [1, 1.5] * osd scrub min interval 内执行。默认值为 0.5。

osd deep scrub stride

执行深层洗刷时读取的大小。默认值为 524288 (512 kB)。