存储策略指南

Red Hat Ceph Storage 4

为 Red Hat Ceph Storage 集群创建存储策略

Red Hat Ceph Storage Documentation Team

摘要

本文档提供了创建存储策略的说明,包括创建 CRUSH 层次结构、估算 PG 数量、确定要创建和管理池的存储池类型。
红帽承诺替换我们的代码、文档和网页属性中存在问题的语言。我们从这四个术语开始: master、slave、blacklist 和 whitelist。这些更改将在即将发行的几个发行本中逐渐实施。详情请查看 CTO Chris Wright 信息

第 1 章 概述

从 Ceph 客户端的角度来看,与 Ceph 存储集群交互非常简单:

  1. 连接到集群
  2. 创建池 I/O 上下文

这一极简单的界面是 Ceph 客户端如何选择您定义的其中一个存储策略。存储策略对 Ceph 客户端而言不可见,除了存储容量和性能外。

下图显示了从客户端开始到红帽 Ceph 存储群集的逻辑数据流。

arch 数据流

1.1. 什么是存储策略?

存储策略是一种存储服务特定用例的数据的方法。例如,如果您需要为 OpenStack 等云平台存储卷和镜像,可以选择使用基于 SSD 的日志将数据存储在具有合理性能的 SAS 驱动器上。相反,如果您需要存储 S3 或 Swift 兼容网关的对象数据,您可以选择使用更经济的方式,如 SATA 驱动器。Ceph 可以适应同一 Ceph 集群中的两种情况,但您需要一种向云平台(如 OpenStack 中的 Glance 和 Cinder)提供 SAS/SSD 存储策略的方法,以及为您的对象存储提供 SATA 存储的方法。

存储策略包括存储介质(硬盘、SSD 和 rest)、CRUSH 映射,这些映射为存储介质设置性能和故障域、放置组数量和池接口。Ceph 支持多种存储策略。使用案例、成本/优势性能权衡和数据持久性是推动存储策略的主要考虑因素。

  1. 使用案例: Ceph 提供海量存储容量,并支持众多用例。例如,Ceph 块设备客户端是 OpenStack 等云平台的领先存储后端,为具有高性能功能的卷和镜像提供无限制存储,如写时复制克隆。相比之下,Ceph 对象网关客户端是云平台的领先存储后端,可为音频、位图、视频和其他数据等对象提供 RESTful S3 兼容和 Swift 兼容对象存储。
  2. 成本/性能提升:Faster 更好.越大越好。越耐用越好。但是,每种出色的质量都有价格,并相应地权衡了成本/收益。从性能角度考虑以下用例:SSD 可以为相对较小的数据和日志量提供非常快速的存储。存储数据库或对象索引可能受益于非常快的 SSD 池,但对其他数据而言非常昂贵。带有 SSD 日志的 SAS 驱动器以经济的价格为卷和图像提供快速性能。没有 SSD 日志地 SATA 驱动器可提供低成本存储,同时整体性能也较低。在创建 CRUSH 的 OSD 层次结构时,您需要考虑用例和可接受的成本/性能权衡。
  3. 持久性: 在大型集群中,硬件故障是预期的,而非例外。但是,数据丢失和服务中断仍然不可接受。因此,数据的持久性非常重要。Ceph 通过对象的多个深度副本或纠删代码和多个编码区块来解决数据持久性。多个副本或多个编码区块会带来额外的成本/优势:存储较少的副本或编码区块,但可能会导致服务以降级状态写入请求。通常,一个带有两个额外副本的对象(即 size = 3)或两个编码区块可能会允许集群在集群恢复时以降级状态写入服务。CRUSH 算法通过确保 Ceph 将额外的副本或编码区块存储在群集内的不同位置来协助此过程。这样可确保单个存储设备或节点的故障不会导致丢失防止数据丢失所需的所有副本或编码区块。

您可以在存储策略中捕获用例、成本/优势性能平衡和数据持久性,并将其作为存储池提供给 Ceph 客户端。

重要

Ceph 的对象复制或编码区块使得 RAID 过时。不要使用 RAID,因为 Ceph 已经处理数据持久性,降级的 RAID 对性能有负面影响,并且使用 RAID 恢复数据比使用深度副本或纠删代码区块要慢得多。

1.2. 配置存储策略

配置存储策略是指将 Ceph OSD 分配到 CRUSH 层次结构、定义池的 PG 数量,以及创建池。常规步骤是:

  1. 定义存储策略: 存储策略要求您分析您的用例、成本/优势性能权衡和数据持久性。然后,您可以创建适合该用例的 OSD。例如,您可以为高性能池创建 SSD 支持的 OSD;SAS 驱动器/SSD 日志支持 OSD 以实现高性能块设备卷和镜像;或者,SATA 支持的 OSD 用于低成本存储。理想情况下,用例中的每个 OSD 应当具有相同的硬件配置,以便您具有一致的性能配置文件。
  2. 定义 CRUSH 层次结构: Ceph 规则在 CRUSH 层次结构中选择一个节点(通常是 root),并确定用于存储 PG 的适当 OSD 及其包含的对象。您必须创建 CRUSH 层次结构和 CRUSH 规则,以用于您的存储策略。CRUSH 层次结构通过 CRUSH 规则设置直接分配到池。
  3. 计算 PG:Ceph 将池分片到 PG 中。您需要为您的池设置适当数量的 PG,并在您将多个池分配到同一 CRUSH 规则时,保持在健康的 PG 数量内。
  4. 创建池: 最后,您必须创建一个池,并确定它使用的是复制存储还是纠删代码存储。您必须为池设置放置组数量、池的规则和持久性(大小或 K+M 编码 区块)。

请记住,池是 Ceph 客户端与存储集群的接口,但存储策略对 Ceph 客户端完全透明(容量和性能除外)。

第 2 章 CRUSH 管理

CRUSH(可扩展哈希下的受控复制)算法确定如何通过计算数据存储位置存储和检索数据。

 

任何足够高级的技术都与魔法无关。

 
 -- Arthur C. Clarke

2.1. CRUSH 简介

存储集群的 CRUSH map 描述了 CRUSH 层次结构中的设备位置,以及 Ceph 存储数据的各个层次结构的规则。

CRUSH map 包含至少一个节点层次结构并离开。Ceph 中名为"buckets"的层次结构节点是其类型定义的任何存储位置聚合。例如,行、机架、机箱、主机和设备。层次结构的每个小部件基本上由存储设备列表中的一个存储设备组成。leaf 始终包含在一个节点或"bucket"。 CRUSH map 也有一个规则列表,它们决定了 CRUSH 存储和检索数据的方式。

注意

将 OSD 添加到集群时,存储设备会添加到 CRUSH map 中。

CRUSH 算法根据每个设备的权重值在存储设备之间分发数据对象,比较均匀的概率分布。CRUSH 根据管理员定义的层次结构群集映射分发对象及其副本或纠删编码区块。CRUSH map 代表可用的存储设备和逻辑 bucket,它们含有规则,并通过扩展使用该规则的每个池来表示。

若要将 PG map 到故障域或性能域之间的 OSD,CRUSH map 定义 bucket 类型层次结构列表;即,位于生成的 CRUSH map 中的 类型 下。创建 bucket 层次结构的目的是通过其故障域或性能域或两者分隔机节点。故障域包括主机、机箱、机架、电源分配单元、pod、行、室和数据中心。性能域包括特定配置的故障域和 OSD。例如,SSD、带有 SSD 日志的 SAS 驱动器、SATA 驱动器等。在 RHCS 3 中,设备具有一个 的概念,如 hddssdnvme,从而更加快速地构建 CRUSH 层次结构和类设备。

除代表 OSD 的 leaf 节点外,其他层次结构是任意的,如果默认类型不满足您的要求,您可以根据自己的需求对其进行定义。我们建议根据您的组织的硬件命名约定来调整 CRUSH map bucket 类型,并使用反映物理硬件名称的实例名称。您的命名实践可以更加轻松地管理集群,并在 OSD 或其他硬件出现故障时对问题进行故障排除,并且管理员需要远程或物理访问主机或其他硬件。

在以下示例中,存储桶层次结构具有四个 leaf bucket(osd 1-4)、两个节点存储桶(主机 1-2)和一个机架节点(机架 1)。

CRUSH 层次结构

由于 leaf 节点反映 CRUSH map 开头 设备列表下声明的存储设备,因此无需将它们声明为 bucket 实例。层次结构中的第二个最低存储桶类型通常聚合设备;即,它通常是包含存储介质的计算机,并且使用管理员更喜欢描述它的任何术语,如"node"、"computer"、"server,"、"host"、"machine"等等。在高密度环境中,看到每个卡和每个机箱的多个主机/节点越来越常见。确保也考虑卡和机箱故障,例如,如果节点出现故障可能会导致大量主机/节点及其 OSD 发生故障,则需要拉取卡或机箱。

在声明存储桶实例时,指定其类型,将其指定唯一名称作为字符串,为它分配一个可选的唯一 ID,以负整数表示,指定相对于其项目的总容量或功能的权重,指定 bucket 算法,如 straw 以及通常 0 反映哈希算法 rjenkins1 的哈希值。bucket 可以具有一个或多个项目。项目可以由节点存储桶或离开组成。项目可以具有一个权重来反映项目的相对权重。

2.1.1. 动态放置数据

Ceph 客户端和 Ceph OSD 都使用 CRUSH map 和 CRUSH 算法。

  • Ceph 客户端: 通过将 CRUSH map 分发到 Ceph 客户端,CRUSH 支持 Ceph 客户端直接与 OSD 通信。这意味着 Ceph 客户端避免中央化对象查找表,该表可以充当单一故障点、性能瓶颈、集中查找服务器的连接限制,以及对存储群集可扩展性的物理限制。
  • Ceph OSD: 通过将 CRUSH map 分发到 Ceph OSD,Ceph 使 OSD 能够处理复制、回填和恢复。这意味着 Ceph OSD 代表 Ceph 客户端处理对象副本(或编码区块)的存储。这也意味着 Ceph OSD 对集群有足够的了解,可以重新平衡集群(回填)并从故障中动态恢复。

2.1.2. 建立故障域

有多个对象副本或 M 纠删代码区块有助于防止数据丢失,但这不足以解决高可用性问题。通过反映 Ceph 存储群集的底层物理组织,CRUSH 可以建模,从而解决潜在的关联设备故障来源。通过将集群的拓扑编码到集群映射中,CRUSH 放置策略可以在不同故障域中分隔对象副本或纠删代码区块,同时仍然保持所需的伪随机分布。例如,为了解决并发故障的可能性,可能需要确保数据副本或纠删代码区块位于使用不同的 shelves、机架、电源、控制器或物理位置的设备中。这有助于防止数据丢失,并允许集群处于降级状态。

2.1.3. 建立性能域

Ceph 可以支持多种层次结构,将一种类型的硬件性能配置文件与其他类型的硬件性能配置文件分隔开。例如,CRUSH 可以为硬盘创建一个层次结构,并为 SSD 创建另一个层次结构。性能域 - 由于需要支持不同的性能特性,因此将底层硬件的性能配置集考虑到性能域 - 由于需要支持不同的性能特性,因此越来越流行。从操作角度而言,它们只是具有多个 bucket 的 CRUSH map。使用案例示例包括:

  • 虚拟机: 作为 OpenStack、CloudStack、ProxMox 或 OpenNebula 等云平台的后端的 Ceph 主机倾向于使用最稳定、最高性能的文件系统,如 SAS 驱动器上的 XFS,以及分区的高性能 SSD 用于日志,因为 XFS 不会同时进行日志处理。为了保持一致的性能配置文件,此类用例应在 CRUSH 层次结构中聚合类似的硬件。
  • 对象存储: Ceph 主机充当 S3 和 Swift 接口的对象存储后端的 Ceph 主机可能会利用更低成本的存储介质,如 SATA 驱动器,这些介质可能不适用于虚拟机,减少用于对象存储的成本,而将更经济的存储主机与在云平台上存储卷和镜像相分离。HTTP 往往成为对象存储系统的瓶颈。
  • 冷存储 :为冷存储设计而设计的系统 - 正常访问的数据,或者有重排性能要求的数据检索 -​might 利用价格较低的存储介质和纠删代码。但是,纠删代码可能需要一些额外的 RAM 和 CPU,因此与用于对象存储或虚拟机的主机的 RAM 和 CPU 要求不同。
  • SSD 支持的池: SSD 昂贵,但与硬盘相比具有显著的优势。SSD 没有寻道时间,它们提供较高的总吞吐量。除了将 SSD 用于日志外,群集还可以支持 SSD 支持的池。常见的用例包括高性能 SSD 池。例如,可以将 Ceph 对象网关的 .rgw.buckets.index 池映射到 SSD,而非 SATA 驱动器。红帽不支持索引池的 HDD 设备。如需有关支持的配置的更多信息,请参阅 Red Hat Ceph Storage: 支持的配置 文章。

在 RHCS 3 及更高版本中,CRUSH map 支持设备 的概念。Ceph 可以发现存储设备的各个方面,并且自动分配 hddssdnvme 等类。但是,CRUSH 不限于这些默认值。例如,CRUSH 层次结构也可能用于分隔不同类型的工作负载。例如,SSD 可用于日志或 write-ahead 日志、bucket 索引或原始对象存储。CRUSH 可以支持不同的设备类别,如 ssd-bucket-indexssd-object-storage,因此 Ceph 不会将相同的存储介质用于不同的工作负载,提高性能可预测性和一致性。

2.1.3.1. 在 RHCS 3 及稍后使用不同的设备类

若要在 RHCS 3 中创建性能域,请使用设备类和单个 CRUSH 层次结构。只需将 OSD 添加到 CRUSH 层次结构的方式与使用 CLI 的 RHCS 2 相同。然后执行以下操作:

  1. 为每个设备添加一个类。例如:

    # ceph osd crush set-device-class <class> <osdId> [<osdId>]
    # ceph osd crush set-device-class hdd osd.0 osd.1 osd.4 osd.5
    # ceph osd crush set-device-class ssd osd.2 osd.3 osd.6 osd.7
  2. 然后,创建规则来使用该设备。

    # ceph osd crush rule create-replicated <rule-name> <root> <failure-domain-type> <class>
    # ceph osd crush rule create-replicated cold default host hdd
    # ceph osd crush rule create-replicated hot default host ssd
  3. 最后,将池设置为使用 规则。

    ceph osd pool set <poolname> crush_rule <rule-name>
    ceph osd pool set cold_tier crush_rule cold
    ceph osd pool set hot_tier crush_rule hot

使用 RHCS 3 和更高版本时,无需手动编辑 CRUSH map!

2.2. CRUSH 层次结构

CRUSH map 是定向式图形,因此它可以容纳多个层次结构(如性能域)。创建和修改 CRUSH 层次结构的最简单方法是使用 Ceph CLI;不过,您也可以解译 CRUSH map,编辑它,对其进行重新编译,并将它激活。

使用 Ceph CLI 声明 bucket 实例时,您必须指定其类型,并为它指定唯一名称(字符串)。Ceph 自动分配 bucket ID,将算法设置为 straw,将哈希设为 0,反映 rjenkins1,然后设置权重。在修改已编译的 CRUSH 映射时,为存储桶分配以负整数表示的唯一 ID(可选),指定相对于其项目的总容量/功能权重,指定 bucket 算法(通常是 straw)和哈希(通常表示 哈希 算法 rjenkins1)。

bucket 可以具有一个或多个项目。项目可以包含节点存储桶(如机架、行、主机)或离开(如 OSD 磁盘)。项目可以具有一个权重来反映项目的相对权重。

在修改已编译的 CRUSH map 时,您可以使用以下语法声明节点存储桶:

[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 | straw ]
    hash [the hash type: 0 by default]
    item [item-name] weight [weight]
}

例如,我们使用上图定义两个主机 bucket 和一个机架 bucket。OSD 在主机存储桶中声明为项目:

host node1 {
    id -1
    alg straw
    hash 0
    item osd.0 weight 1.00
    item osd.1 weight 1.00
}

host node2 {
    id -2
    alg straw
    hash 0
    item osd.2 weight 1.00
    item osd.3 weight 1.00
}

rack rack1 {
    id -3
    alg straw
    hash 0
    item node1 weight 2.00
    item node2 weight 2.00
}
注意

在示例中,请注意机架 bucket 不包含任何 OSD。而是包含较低级别的主机 bucket,并在 item 条目中包含其权重的总和。

2.2.1. CRUSH 位置

CRUSH 位置是 OSD 在 CRUSH map 的层次结构方面的位置。当您在命令行界面上表达 CRUSH 位置时,CRUSH 位置指定符采用描述 OSD 位置的名称/值对的列表。例如,如果某一 OSD 位于特定的行、机架、机箱和主机中,并且是 默认 CRUSH 树的一部分,其 crush 位置可以描述为:

root=default row=a rack=a2 chassis=a2a host=a2a1

注:

  1. 密钥的顺序无关紧要。
  2. 密钥名称(左 = )必须是有效的 CRUSH 类型。默认情况下,其中包括 rootdatacenter、room、line、 pod pdurack、cha ssishost。您可以编辑 CRUSH map,以更改类型以符合您的需要。
  3. 您不需要指定所有存储桶/密钥。例如,默认情况下,Ceph 自动将 ceph-osd 守护进程的位置设置为 root=default host={HOSTNAME} (基于来自 hostname -s的输出)。

2.2.2. 添加 Bucket

若要添加 bucket 实例到 CRUSH 层次结构,可指定 bucket 名称及其类型。bucket 名称在 CRUSH map 中必须是唯一的。

ceph osd crush add-bucket {name} {type}

如果您计划使用多个层次结构(例如,针对不同的硬件性能配置文件),请考虑根据其硬件类型或用例命名存储桶。

例如,您可以为固态硬盘(ssd)、带有 SSD 日志(hdd-journal)的 SAS 磁盘创建层次结构,并为 SATA 驱动器创建另一个层次结构(hdd):

ceph osd crush add-bucket ssd-root root
ceph osd crush add-bucket hdd-journal-root root
ceph osd crush add-bucket hdd-root root

Ceph CLI 输出:

added bucket ssd-root type root to crush map
added bucket hdd-journal-root type root to crush map
added bucket hdd-root type root to crush map
重要

不支持在存储桶名称中使用冒号(:)。

添加层次结构所需的每种 bucket 类型的实例。以下示例演示了如何添加一行中的 bucket,其中包含 SSD 主机的机架和对象存储的主机机架。

ceph osd crush add-bucket ssd-row1 row
ceph osd crush add-bucket ssd-row1-rack1 rack
ceph osd crush add-bucket ssd-row1-rack1-host1 host
ceph osd crush add-bucket ssd-row1-rack1-host2 host
ceph osd crush add-bucket hdd-row1 row
ceph osd crush add-bucket hdd-row1-rack2 rack
ceph osd crush add-bucket hdd-row1-rack1-host1 host
ceph osd crush add-bucket hdd-row1-rack1-host2 host
ceph osd crush add-bucket hdd-row1-rack1-host3 host
ceph osd crush add-bucket hdd-row1-rack1-host4 host
注意

如果您已经使用 Ansible 自动化应用或其他工具来添加 OSD 到集群中,则主机节点可以已在 CRUSH map 中。

完成这些步骤后,请查看您的树。

ceph osd tree

请注意,层次结构保持扁平状态。将存储桶添加到 CRUSH map 后,您必须将它们移到层次结构位置。

2.2.3. 移动 Bucket

在创建初始集群时,Ceph 具有名为 default 的根 bucket 的默认 CRUSH map,您的初始 OSD 主机显示在 默认 bucket 下。当您添加 bucket 实例到 CRUSH map 时,它会出现在 CRUSH 层次结构中,但不一定显示在特定 bucket 下。

若要将 bucket 实例移到 CRUSH 层次结构中的特定位置,可指定 bucket 名称及其类型。例如:

ceph osd crush move ssd-row1 root=ssd-root
ceph osd crush move ssd-row1-rack1 row=ssd-row1
ceph osd crush move ssd-row1-rack1-host1 rack=ssd-row1-rack1
ceph osd crush move ssd-row1-rack1-host2 rack=ssd-row1-rack1

完成这些步骤后,您可以查看树。

ceph osd tree
注意

您还可以使用 ceph osd crush create-or-move 在移动 OSD 时创建一个位置。

2.2.4. 删除 Bucket

若要从 CRUSH 层次结构中移除 bucket 实例,可指定 bucket 名称。例如:

ceph osd crush remove {bucket-name}

或者:

ceph osd crush rm {bucket-name}
注意

bucket 必须为空才能将其删除。

如果您要删除更高级别的存储桶(如 default),请检查池是否使用 CRUSH 规则来选择该 bucket。如果是这样,您需要修改 CRUSH 规则;否则,peering 会失败。

2.2.5. bucket Algorithms

在使用 Ceph CLI 创建 bucket 时,Ceph 会默认将算法设置为 straw。Ceph 支持四种 bucket 算法,每种算法代表性能和提升效率之间的权衡。如果您不确定要使用的存储桶类型,我们建议使用 straw bucket。bucket 算法是:

  1. 统一: 统一存储桶聚合设备,其权重 完全相同。例如,当公司委托或停用硬件时,他们通常使用许多具有完全相同的物理配置(例如批量采购)的机器。当存储设备的权重完全相同时,您可以使用 统一 bucket 类型,它允许 CRUSH 持续将副本映射到统一 bucket。使用非统一权重时,您应该使用其他 bucket 算法。
  2. list :列出存储桶将其内容聚合为链接列表。根据 RUSH(Replication Under Scalable Hashing) P 算法,列表是 扩展集群的 自然和直观选择:对象被重新定位到具有某种适当概率的最新设备,或者像以前一样保留在旧设备上。结果是在将项目添加到存储桶时的最佳数据迁移。但是,从列表中的中部或尾部删除的项目可能会导致大量不必要的移动,使列表存储桶非常适合 (或很少)缩小 的情况。
  3. :树形 bucket 使用二进制搜索树。当 bucket 包含较大的项目集时,它们比列出存储桶更高效。根据 RUSH(可扩展哈希下的复制) R 算法,树 bucket 减少了 O(log n)的放置时间,使其适合管理大得多的设备或嵌套 bucket。
  4. straw(默认): list 和 Tree bucket 使用拆分和聚合策略,从而指定特定项目(例如,列表开头的项目)或无需考虑整个项目子树。这提高了副本放置流程的性能,但也可能会在 bucket 的内容因为项目的添加、删除或重新加权而改变时引入不最佳的行为。straw bucket 类型允许所有项目都比较"compete",通过类似于大量 straws 的过程进行副本放置。

2.3. CRUSH 中的 Ceph OSD

具有 OSD 的 CRUSH 层次结构后,将 OSD 添加到 CRUSH 层次结构中。您也可以从现有的层次结构中移动或删除 OSD。Ceph CLI 用法具有以下值:

id
描述
OSD 的数字 ID。
类型
整数
必填
示例
0
name
描述
OSD 的全名。
类型
字符串
必填
示例
osd.0
weight
描述
OSD 的 CRUSH 权重。
类型
必填
示例
2.0
root
描述
OSD 所在的层次结构或树的根 bucket 的名称。
类型
键值对.
必填
示例
root=defaultroot=replicated_rule
bucket-type
描述
个或多个 name-value 对,其中 name 是 bucket 类型,值是 bucket 的名称。您可以在 CRUSH 层次结构中为 OSD 指定 CRUSH 位置。
类型
健值对。
必填
示例
datacenter=dc1 room=room1 row=foo rack=bar host=foo-bar-1

2.3.1. 查看 CRUSH 中的 OSD

ceph osd crush tree 命令在树 视图中打印 CRUSH bucket 和项。使用此命令来确定特定 bucket 中的 OSD 列表。它将打印类似于 ceph osd 树 的输出。

要返回更多详细信息,请执行以下操作:

# ceph osd crush tree -f json-pretty

该命令返回类似如下的输出:

[
    {
        "id": -2,
        "name": "ssd",
        "type": "root",
        "type_id": 10,
        "items": [
            {
                "id": -6,
                "name": "dell-per630-11-ssd",
                "type": "host",
                "type_id": 1,
                "items": [
                    {
                        "id": 6,
                        "name": "osd.6",
                        "type": "osd",
                        "type_id": 0,
                        "crush_weight": 0.099991,
                        "depth": 2
                    }
                ]
            },
            {
                "id": -7,
                "name": "dell-per630-12-ssd",
                "type": "host",
                "type_id": 1,
                "items": [
                    {
                        "id": 7,
                        "name": "osd.7",
                        "type": "osd",
                        "type_id": 0,
                        "crush_weight": 0.099991,
                        "depth": 2
                    }
                ]
            },
            {
                "id": -8,
                "name": "dell-per630-13-ssd",
                "type": "host",
                "type_id": 1,
                "items": [
                    {
                        "id": 8,
                        "name": "osd.8",
                        "type": "osd",
                        "type_id": 0,
                        "crush_weight": 0.099991,
                        "depth": 2
                    }
                ]
            }
        ]
    },
    {
        "id": -1,
        "name": "default",
        "type": "root",
        "type_id": 10,
        "items": [
            {
                "id": -3,
                "name": "dell-per630-11",
                "type": "host",
                "type_id": 1,
                "items": [
                    {
                        "id": 0,
                        "name": "osd.0",
                        "type": "osd",
                        "type_id": 0,
                        "crush_weight": 0.449997,
                        "depth": 2
                    },
                    {
                        "id": 3,
                        "name": "osd.3",
                        "type": "osd",
                        "type_id": 0,
                        "crush_weight": 0.289993,
                        "depth": 2
                    }
                ]
            },
            {
                "id": -4,
                "name": "dell-per630-12",
                "type": "host",
                "type_id": 1,
                "items": [
                    {
                        "id": 1,
                        "name": "osd.1",
                        "type": "osd",
                        "type_id": 0,
                        "crush_weight": 0.449997,
                        "depth": 2
                    },
                    {
                        "id": 4,
                        "name": "osd.4",
                        "type": "osd",
                        "type_id": 0,
                        "crush_weight": 0.289993,
                        "depth": 2
                    }
                ]
            },
            {
                "id": -5,
                "name": "dell-per630-13",
                "type": "host",
                "type_id": 1,
                "items": [
                    {
                        "id": 2,
                        "name": "osd.2",
                        "type": "osd",
                        "type_id": 0,
                        "crush_weight": 0.449997,
                        "depth": 2
                    },
                    {
                        "id": 5,
                        "name": "osd.5",
                        "type": "osd",
                        "type_id": 0,
                        "crush_weight": 0.289993,
                        "depth": 2
                    }
                ]
            }
        ]
    }
]
注意

在 RHCS 3 和更高版本中,OSD 对象也将具有 device_class 属性。

2.3.2. 将 OSD 添加到 CRUSH

将 OSD 添加到 CRUSH 层次结构中是最后一步,然后您启动 OSD( 在 中进行渲染),Ceph 将 PG 分配到 OSD。

注意

在 RHCS 3 中,您可能还会添加一个设备类。

您必须先准备 OSD,然后才能将它添加到 CRUSH 层次结构中。部署实用程序(如 Ansible 自动化应用)为您执行这一步。如需了解更多详细信息,请参阅添加/删除 OSD。

CRUSH 层次结构是概念性的,因此 ceph osd crush add 命令允许您在您希望的任何位置添加 OSD 到 CRUSH 层次结构。您指定的位置 应反映 其实际位置。如果至少指定了一个 bucket,命令会将 OSD 放置到您指定的最具体的 bucket 中,它会 将 bucket 移到您指定的任何其他 bucket 的下方。

将 OSD 添加到 CRUSH 层次结构中:

ceph osd crush add {id-or-name} {weight}  [{bucket-type}={bucket-name} ...]
重要

如果您仅指定根 bucket,命令会将 OSD 直接附加到 root。但是,CRUSH 规则预期 OSD 在主机或机箱内,主机或机箱 应当 位于反映集群拓扑的其他 bucket 中。

以下示例在层次结构中添加 osd.0

ceph osd crush add osd.0 1.0 root=default datacenter=dc1 room=room1 row=foo rack=bar host=foo-bar-1
注意

您还可以使用 ceph osd crush set 或 ceph osd crush create-or-move 将 OSD 添加到 CRUSH 层次结构。

2.3.3. 在 CRUSH 层次结构中移动 OSD

如果部署实用程序(如 Ansible 自动化应用在更优的 CRUSH 位置添加了 OSD 到 CRUSH map),或者集群拓扑发生变化,则可以移动 CRUSH 层次结构中的 OSD 以反映其实际位置。

重要

在 CRUSH 层次结构中移动 OSD 意味着 Ceph 将重新计算将哪些 PG 分配到 OSD,可能会产生大量数据重新分发。

在 CRUSH 层次结构中移动 OSD:

ceph osd crush set {id-or-name} {weight} root={pool-name}  [{bucket-type}={bucket-name} ...]
注意

您还可以使用 ceph osd crush create-or-move 在 CRUSH 层次结构中移动 OSD。

2.3.4. 从 CRUSH 层次结构中删除 OSD

在您要从集群中删除 OSD 时,从 CRUSH 层次结构中删除 OSD 是第一步。当您从 CRUSH map 移除 OSD 时,CRUSH 会重新计算哪些 OSD 获取 PG,并相应地重新平衡数据。如需了解更多详细信息,请参阅添加/删除 OSD。

要从正在运行的集群的 CRUSH map 移除 OSD,请执行以下操作:

ceph osd crush remove {name}

2.4. 设备类

Ceph 的 CRUSH map 在控制数据放置方面提供了非凡的灵活性。这是 Ceph 的最大优势之一。早期 Ceph 部署使用硬盘几乎专用。如今,Ceph 集群经常使用多种类型的存储设备构建:HDD、SSD、NVMe,甚至各种级别的存储设备。例如,Ceph 对象网关部署中通常具有存储策略,客户端可在较慢的 HDD 和其他存储策略中存储数据,从而将数据存储在快速 SSD 上。Ceph 对象网关部署甚至可能具有由用于 bucket 索引快速 SSD 支持的池。此外,OSD 节点通常还会专门用于不显示在 CRUSH map 中的日志或 write-ahead 日志。过去,这些复杂的硬件方案需要手动编辑 CRUSH map,这可能十分耗时且繁琐。在 RHCS 3 中,红帽添加了一个新的"设备类",这大大简化了创建 CRUSH 层次结构,在 RHCS 3 及更高版本中,不再需要对不同类型的存储设备具有不同的 CRUSH 层次结构。

CRUSH 规则在 CRUSH 层次结构方面起作用。但是,如果同一主机上存在不同类别的存储设备,则流程变得更加复杂 - 需要用户为每一类设备创建多个 CRUSH 层次结构,然后在 启动选项时禁用 osd crush update,以 自动化大部分 CRUSH 层次结构管理。设备类通过告知 CRUSH 规则要使用的设备类别来消除这种繁琐问题,从而大大简化了 CRUSH 管理任务。

注意

在 RHCS 3 及更高版本中,ceph osd tree 命令有一个列来反映设备类。

以下小节详细介绍了设备类使用情况。如需更多 示例,请参阅 在 RHCS 3、terter 和 CRUSH 存储策略 示例中使用不同的设备类

2.4.1. 设置设备类

要为 OSD 设置设备类,请执行以下操作:

# ceph osd crush set-device-class <class> <osdId> [<osdId>...]

例如:

# ceph osd crush set-device-class hdd osd.0 osd.1
# ceph osd crush set-device-class ssd osd.2 osd.3
# ceph osd crush set-device-class bucket-index osd.4
注意

Ceph 可能会自动将类分配给设备。但是,类名称只是任意字符串。不要求遵循 hddssd 或 nvme。在 foregoing 示例中,名为 bucket-index 的设备类可能表示 Ceph Object Gatway 池使用唯一的存储桶索引工作负载的 SSD 设备。若要更改已设置的设备类,请先使用 ceph osd crush rm-device-class

2.4.2. 删除设备类

要删除 OSD 的设备类,请执行以下操作:

# ceph osd crush rm-device-class <class> <osdId> [<osdId>...]

例如:

# ceph osd crush rm-device-class hdd osd.0 osd.1
# ceph osd crush rm-device-class ssd osd.2 osd.3
# ceph osd crush rm-device-class bucket-index osd.4

2.4.3. 重命名设备类

要为所有使用该类的 OSD 重命名设备类,请执行以下操作:

# ceph osd crush class rename <oldName> <newName>

例如:

# ceph osd crush class rename hdd sas15k

2.4.4. 列出设备类

要列出 CRUSH map 中的设备类,请执行以下操作:

# ceph osd crush class ls

输出将类似如下:

[
    "hdd",
    "ssd",
    "bucket-index"
]

2.4.5. 列出设备类的 OSD

要列出属于特定类的所有 OSD,请执行以下操作:

# ceph osd crush class ls-osd <class>

例如:

# ceph osd crush class ls-osd hdd

输出只是 OSD 编号的列表。例如:

0
1
2
3
4
5
6

2.4.6. 按类列出 CRUSH 规则

要列出所有引用同一类的规则,请执行以下操作:

# ceph osd crush rule ls-by-class <class>

例如:

# ceph osd crush rule ls-by-class hdd

2.5. CRUSH Weights

CRUSH 算法为每个 OSD 设备分配一个以 TB 为单位的权重值,用于将新数据对象分配到 PG 和 PG 的写入请求的均匀几率分布到 OSD。因此,作为最佳实践,我们建议使用相同类型和大小的设备创建 CRUSH 层次结构,并分配相同的权重。我们还建议使用具有相同 I/O 和吞吐量特征的设备,以便您也在 CRUSH 层次结构中具有统一的性能特征,即使性能特征不会影响数据分布。

由于使用统一硬件并非始终可行,您可以将 OSD 设备包含不同大小,并使用相对权重,以便 Ceph 会将更多数据分发到更大的设备,减少数据到较小的设备。

2.5.1. 在 Terabytes 中设置 OSD 的 Weight

要在 CRUSH map 内以 Terabytes 为单位设置 OSD CRUSH 权重,请执行以下命令

ceph osd crush reweight {name} {weight}

其中:

name
描述
OSD 的全名。
类型
字符串
必填
示例
osd.0
weight
描述
OSD 的 CRUSH 权重。这应当是以 Terabytes 为单位的 OSD 的大小,其中 1.0 是 1 TB。
类型
必填
示例
2.0

此设置在创建 OSD 时使用,或者在添加 OSD 后立即调整 CRUSH 权重。它通常不会在 OSD 的生命周期内更改。

2.5.2. 设置 Bucket 的 OSD Weights

使用 ceph osd crush reweight 可能会非常耗时。您可以通过执行以下命令在 bucket 下设置(或重置)所有 Ceph OSD 权重(row、rack 和 node 等):

osd crush reweight-subtree <name>

其中,

name 是 CRUSH bucket 的名称。

2.5.3. 在 Weight 中设置 OSD

出于 ceph osd inceph osd out 的目的 OSD 在集群中或集群 。这是监控器记录 OSD 状态的方式。但是,即使 OSD 集群中存在,但可能会遇到故障问题,因此您可能希望在修复前完全依赖它(例如,替换存储驱动器,更改控制器等等)。

您可以通过执行以下命令来增加或减小特定 OSD 的权重 (即,不更改其以 Terabytes 为单位的权重):

ceph osd reweight {id} {weight}

其中:

  • ID 是 OSD 编号。
  • weight 是 0.0-1.0 的范围,其中 0在集群中 (即,它没有任何 PG 分配给它),1.0 则 在集群中 (即,OSD 接收的 PG 数量与其他 OSD 相同)。

2.5.4. 设置 OSD 的 Weight by Utilization

CRUSH 设计为用于写入请求的近似平均度分布,从而将新数据对象 PG 和 PG 分配到 OSD。但是,集群可能会变得不平衡。这样做的原因有很多。例如:

  • 多个池: 您可以将多个池分配到 CRUSH 层次结构,但池可能具有不同的放置组数量、大小(要存储副本数)和对象大小特征。
  • 自定义客户端: Ceph 客户端(如块设备、对象网关和来自其客户端的文件系统分片数据),将数据作为对象分条在集群中,作为统一大小较小的 RADOS 对象。因此,除了上述情景外,CRUSH 通常可实现自己的目标。但是,在另一种情形中,集群可能会变得冲突:即,使用 librados 在不规范对象大小的情况下存储数据。这种情境可能会导致集群的平衡(例如,存储 100 1 MB 对象和 10 4 MB 对象,使得一些 OSD 具有比其他 OSD 更多的数据。
  • 概率: 均匀分布将导致某些 OSD 数量更多,PG 数量较少。对于具有大量 OSD 的集群,统计外围器将进一步展开。

您可以通过执行以下内容来重新加权 OSD:

ceph osd reweight-by-utilization [threshold]  [weight_change_amount] [number_of_OSDs] [--no-increasing]

例如:

ceph osd test-reweight-by-utilization 110 .5 4 --no-increasing

其中:

  • 阈值 是利用率百分比,使得面临更大数据存储负载的 OSD 将获得较低的权重,从而减少分配给它们的 PG。默认值为 120,反映 120%。100+ 中的任何值都是有效的阈值。可选。
  • weight_change_amount 是用于更改权重的数量。有效值大于 0.0 - 1.0。默认值为 0.05。可选。
  • number_of_OSDs 是重新加权 OSD 的最大数量。对于大型集群,将 OSD 数量限制为重新加权可防止大量重新平衡。可选。
  • 默认情况下 不会出现任何增长 。使用 reweight-by-utilization 或 test-reweight-by -utilization 命令时,允许增大 osd 权重。如果将此选项与这些命令搭配使用,它将防止增加 OSD 权重,即使 OSD 利用率不足也是如此。可选。
重要

建议 逐个使用,对于大型集群来说,有时不可避免。随着集群的大小或硬件改变,利用率率可能会随时间而变化,可能需要更新权重来反映变化的利用率。如果选择按利用率重新加权,您可能需要以利用率、硬件或集群大小更改来重新运行该命令。

执行此或其他分配权重的权重命令将覆盖此命令分配的权重(例如,osd reweight-by-utilization、os d crush weight、os d weight、in out)。

2.5.5. 设置 OSD 的 Weight by PG Distribution

在具有数量较少 OSD 的 CRUSH 层次结构中,一些 OSD 可能获得比其他 OSD 更多的 PG,从而导致负载更高。您可以通过执行以下内容,按 PG 分布重新加权 OSD 来解决这种情况:

osd reweight-by-pg <poolname>

其中:

  • poolname 是池的名称。Ceph 将检查池如何分配 PG 到 OSD,并根据这个池的 PG 分布重新加权 OSD。请注意,多个池可以分配到相同的 CRUSH 层次结构。根据一个池的分发重新加权 OSD 可能会对分配到同一 CRUSH 层次结构的其他池产生意外的影响,只要它们的大小(副本数)和 PG 没有相同大小(副本数)和 PG。

2.5.6. 重新计算 CRUSH Tree 的 Weights

CRUSH 树 bucket 应当是其 leaf 权重的总和。如果手动编辑 CRUSH map 权重,您应该执行下列命令,以确保 CRUSH bucket 树准确反映 bucket 下的 leaf OSD 的总和。

osd crush reweight-all

2.6. 主关联性

当 Ceph 客户端读取或写入数据时,它会始终联系操作集中的 Primary OSD。对于设置 [2、3、4]osd.2 是主要.有时,与其他 OSD 相比,OSD 不太适合充当主设备(例如,它具有较慢的磁盘或较慢的控制器)。为防止性能瓶颈(特别是读取操作),同时最大限度地提高硬件利用率,您可以设置 Ceph OSD 的 primary affinity,这样 CRUSH 不太可能将该 OSD 用作操作集合中的 primary。

ceph osd primary-affinity <osd-id> <weight>

默认情况下,primary affinity为 1(即, OSD 可能会充当主要)。您可以将 OSD 主要范围设置为 0-1,其中 0 表示该 OSD 可能不用作 Primary 和 1,意味着 OSD 可能被用作主要 OSD。当权重为 <1 时,CRUSH 不太可能选择 Ceph OSD 守护进程以充当主要设备。

2.7. CRUSH 规则

CRUSH 规则定义 Ceph 客户端如何选择存储桶和它们中的 Primary OSD 来存储对象,以及 Primary OSD 如何选择 bucket 和次要 OSD 来存储副本或编码区块。例如,您可以创建一条规则,为两个对象副本选择由 SSD 支持的一对目标 OSD,另一条规则则为三个副本选择由 SAS 驱动器支持的三个目标 OSD。

规则采用以下形式:

rule <rulename> {

    ruleset <ruleset>
    type [ replicated | raid4 ]
    min_size <min-size>
    max_size <max-size>
    step take <bucket-type> [class <class-name>]
    step [choose|chooseleaf] [firstn|indep] <N> <bucket-type>
    step emit
}
ruleset
描述
(已弃用)将规则归类为属于一组规则的方法。通过设置池中的规则集激活。RHCS 2 及更早版本支持.RHCS 3 及更新的版本不支持。
用途
规则掩码的一个组件。
类型
整数
必填
默认
0
type
描述
描述存储驱动器(复制)或 RAID 的规则。
用途
规则掩码的一个组件。
类型
字符串
必填
默认
复制
有效值
目前仅 复制
min_size
描述
如果池形成的副本数少于这个数目,CRUSH 不会选择这一规则。
类型
整数
用途
规则掩码的一个组件。
必填
默认
1
max_size
描述
如果池形成的副本数超过这个数目,CRUSH 不会选择这一规则。
类型
整数
用途
规则掩码的一个组件。
必填
默认
10
步骤取 <bucket-name> [class <class-name>]
描述
取 bucket 名称,然后开始往下迭代树。可能会在 RHCS 3 及更高版本中使用设备名称。
用途
规则的一个组件。
必填
示例
step take datastep take data class ssd
步骤选择 firstn <num> type <bucket-type>
描述

选择所给类型的 bucket 数量。这个数字通常是池中的副本数(即池大小)。

  • 如果 <num> == 0,请选择 pool-num-replicas bucket(所有可用)。
  • 如果 <num> > 0 && <pool-num-replicas,请选择这个数量的存储桶。
  • 如果 <num> <0,则表示 pool-num-replicas - {num}
用途
规则的一个组件。
前提条件
按照 步骤或 步骤选择.
示例
步骤选择 firstn 1 类型行
step selectleaf firstn <num> type <bucket-type>
描述

选择 {bucket-type} 的 bucket 集合,并从存储桶集合中的每个存储桶的子树中选择一个 leaf 节点。集合中的 bucket 数量通常是池中的副本数(即池大小)。

  • 如果 <num> == 0,请选择 pool-num-replicas bucket(所有可用)。
  • 如果 <num> > 0 && <pool-num-replicas,请选择这个数量的存储桶。
  • 如果 <num> <0,则表示 pool-num-replicas - <num>
用途
规则的一个组件。使用方法不需要通过两个步骤选择设备。
前提条件
按照 步骤或 步骤选择.
示例
步骤选择leaf firstn 0 类型行
步骤发出
描述
输出当前值并清空堆栈。通常在规则末尾使用,但也可以用来从同一规则的不同树中进行选择。
用途
规则的一个组件。
前提条件
按照 步骤选择.
示例
步骤发出
firstn 和 indep
描述
控制 CRUSH 当 OSD 在 CRUSH map 中标记为 down 时所使用的替换策略。如果要将此规则与复制池搭配使用,它应当为 firstn,并且用于纠删代码池,它应当为 indep
示例
您有一个 PG 存储在 OSD 1、2、3、4、5 上,其中 3 出现故障。在第一种场景中,使用 firstn 模式,CRUSH 会调整其计算,以选择 1 和 2,然后选择 3,但发现它已经停机,因此它将重试并选择 4 和 5,然后继续选择新的 OSD 6。最终 CRUSH 映射从 1、2、3、4、5 更改为 1、24、5、6。在第二个场景中,使用纠删代码池的 indep 模式,CRUSH 会尝试选择故障 OSD 3,再次尝试选择 6,以便最终从 1、2、4、5 转换到 1、2、6、4、5
重要

给定 CRUSH 规则可以分配到多个池,但单个池不可能有多个 CRUSH 规则。

2.7.1. 列出规则

要从命令行列出 CRUSH 规则,请执行以下操作:

ceph osd crush rule list
ceph osd crush rule ls

2.7.2. 转储规则

要转储特定 CRUSH 规则的内容,请执行以下操作:

ceph osd crush rule dump {name}

2.7.3. 添加简单规则

要添加 CRUSH 规则,您必须指定规则名称、要使用的层次结构的根节点、您要复制到的存储桶类型(例如,'rack'、'row' 等),以及选择存储桶的模式。

ceph osd crush rule create-simple {rulename} {root} {bucket-type} {firstn|indep}

Ceph 将创建一个包含您指定类型的 select leaf 和 1 bucket 的规则。

例如:

ceph osd crush rule create-simple deleteme default host firstn

创建以下规则:

{ "rule_id": 1,
  "rule_name": "deleteme",
  "ruleset": 1,
  "type": 1,
  "min_size": 1,
  "max_size": 10,
  "steps": [
        { "op": "take",
          "item": -1,
          "item_name": "default"},
        { "op": "chooseleaf_firstn",
          "num": 0,
          "type": "host"},
        { "op": "emit"}]}
注意

RHCS 3 及更新的版本不支持该规则集。它仅用于向后兼容 RHCS 2 及较早版本的 Ceph。

2.7.4. 添加复制的规则

要为复制池创建 CRUSH 规则,请执行以下操作:

# ceph osd crush rule create-replicated <name> <root> <failure-domain> <class>

其中:

  • <name> :规则的名称。
  • <root> :CRUSH 层次结构的根目录。
  • <failure-domain> :故障域。例如: hostrack
  • <class> :存储设备类别。例如: hddssd。仅 RHCS 3 及更高版本.

例如:

# ceph osd crush rule create-replicated fast default host ssd

2.7.5. 添加纠删代码规则

要添加用于纠删代码池的 CRUSH 规则,您可以指定规则名称和纠删代码 profile。

ceph osd crush rule create-erasure {rulename} {profilename}

2.7.6. 删除规则

要移除规则,请执行下列命令并指定 CRUSH 规则名称:

ceph osd crush rule rm {name}

2.8. CRUSH 可调项

Ceph 项目呈指数级增长,带来了许多变化和多项新功能。Ceph 从第一个商业支持的主要版本 v0.48(Argonaut)开始,提供调整 CRUSH 算法某些参数的功能,即,这些设置没有在源代码中强制执行。

需要考虑以下几点:

  • 调整 CRUSH 值可能会导致在存储节点之间切换一些 PG。如果 Ceph 集群已存储大量数据,则需要为要移动的一小部分数据做好准备。
  • ceph-osdceph-mon 守护进程将在新连接收到更新的 map 后立即启动,要求它们具有功能位。但是,已连接的客户端实际上处于伪装中,如果客户端不支持新功能,它们就会行为错误。确保升级 Ceph 存储集群守护进程时,您也会更新 Ceph 客户端。
  • 如果 CRUSH 可调项设置为非传统值,然后随后改回到旧值,则不需要 ceph-osd 守护进程来支持该功能。不过,OSD 对等进程需要检查和了解旧 map。因此,如果集群之前使用非传统 CRUSH 值,则不应运行旧版本的 ceph-osd 守护进程,即使最新版本的 map 已切回到使用旧默认值。

2.8.1. CRUSH 可调项的演变

0.48 之前的 Ceph 客户端和守护进程无法检测到可调项,且与版本 0.48 及更高版本不兼容,您必须升级。调整可调 CRUSH 值的功能也随着主要 Ceph 发行版而得到演进。

传统值

使用 CRUSH Tunables 在较新集群中部署的传统值可能不正确。问题包括:

  • 在 leaf bucket 中含有少量设备的层次结构中,一些 PG 映射到少于所需副本数。对于"主机"节点,每个 OSD 嵌套在下面,通常会发生这种情况。
  • 对于大型集群,一些少量 PG map 到比所需的 OSD 数量更少的 map。当层次结构的多个层面存在时,这更加常见。例如,行、rack、host、osd。
  • 当某些 OSD 标出后,数据往往会重新分发到附近 OSD,而非整个层次结构中。
重要

红帽强烈建议将 Ceph 客户端和 Ceph 守护进程升级到主要的受支持版本,以利用 CRUSH 可调项。红帽建议所有集群守护进程和客户端使用相同的发行版本。

argonaut(Legacy)

这是第一个受商业支持的 Ceph 版本。

  • 版本要求:

    • Ceph 0.48、0.49 及更新的版本
    • Linux 内核 3.6 或更高版本,包括 RBD 内核客户端
  • 支持的 CRUSH 可调项:

    • select_local_tries :本地重试次数。传统值为 2,最佳值为 0。
    • select_local_fallback_tries:Le gacy 值为 5,优化值为 0。
    • select_total_tries: 尝试选择一个项目的总次数。传统值为 19,后续测试表明值 50 更适合典型的集群。对于非常大的集群,可能需要一个更大的值。

Bobtail

  • 版本要求:

    • Ceph 0.55、0.56.x 及更新的版本
    • Linux 内核 3.9 或更高版本,包括 RBD 内核客户端
  • 支持的 CRUSH 可调项:

    • selectleaf_descend_once :无论递归选手尝试是重试还是仅尝试一次,并且仅允许原始放置重试。传统默认值为 0,优化值为 1。

Firefly

这是第一个红帽支持的 Ceph 版本。

  • 版本要求:

    • Red Hat Ceph Storage 1.2.3 及更新的版本
    • Red Hat Enterprise Linux 7.1 或更高版本,包括 RBD 内核客户端
  • 支持的 CRUSH 可调项:

    • selectleaf_vary_r :是否递归选择leaf 尝试以 r 的非零值开头,具体取决于父进程已经进行的尝试数。传统默认值为 0,但使用这个值时 CRUSH 有时无法找到映射。就计算成本和正确性而言,最佳价值是 1。但是,对于具有大量现有数据的传统群集,从 0 更改为 1 将导致大量数据移动;值 4 或 5 将允许 CRUSH 查找有效的映射,但移动较少的数据。
    • straw_calc_version :在 straw bucket 的 CRUSH map 中计算并存储了内部权重存在一些问题。具体来说,当有 CRUSH 权重为 0 或两者兼有权重的项目时,CRUSH 会将数据分发错误,即不与权重成比例。0 的值保留旧的、损坏的内部权重计算;值 1 修复行为。将 straw_calc_version 设置为 1,然后调整 straw bucket,方法是添加、删除、重新加权项目,或者通过使用 reweight-all 命令,如果集群遇到问题条件之一,则可以触发少量到中等数量的数据移动。此可调项选项很特殊,因为它对客户端所需的内核版本绝对没有影响。

hammer

hammer 可调项配置文件仅通过更改可调配置文件来影响现有 CRUSH map 的映射,但现在支持新 bucket 类型 straw2

  • 版本要求:

    • Red Hat Ceph Storage 1.3 及更新的版本
    • Red Hat Enterprise Linux 7.1 或更高版本,包括 RBD 内核客户端
  • 新 Bucket 类型:

    • 新的 straw2 bucket 类型修复了原始 straw bucket 中的几个限制。具体来说,旧的 straw bucket 会更改调整权重时应更改的一些映射,而 straw2 bucket 的原始目标则是仅更改与权重已更改的 bucket 项的映射或更改。straw2 bucket 是任何新创建的 bucket 的默认 bucket。将 bucket 类型从 straw 改为 straw2 将导致数量相对少的数据移动量,具体取决于 bucket 项权重之间的不同程度。当权重相同时,不会移动任何数据,当项目权重有显著变化时,移动度也会更多。

jewel

Red Hat Ceph Storage 2 在 Red Hat Enterprise Linux 7.2 或更高版本上被支持,但只有 Red Hat Enterprise Linux 7.3 或更高版本支持 jewel 可调项配置集。jewel 可调项配置文件改进了 CRUSH 的整体行为,因此当 OSD 签出集群时,它会显著减少映射更改。

  • 版本要求:

    • Red Hat Ceph Storage 2 及更新的版本
    • 红帽企业 Linux 7.3 或更高版本,包括 RBD 内核客户端和 CephFS 内核客户端
  • 支持的 CRUSH 可调项:

    • selectleaf_stable :递归选择leaf 尝试是否将对内环使用更好的值,从而在 OSD 标出时显著减少映射更改数量。传统值为 0,而 1 的新值则使用新方法。在现有集群上更改此值将导致大量数据移动,因为几乎所有 PG map 都可能会改变。

2.8.2. 调优 CRUSH

在您调优 CRUSH 之前,您应该确保所有 Ceph 客户端和所有 Ceph 守护进程都使用相同的版本。如果您最近升级了,请确保已重启守护进程并重新连接了客户端。

调整 CRUSH 可调项的最简单方法是更改为已知的配置文件。这些是:

  • 传统 :来自 v0.47(Argonaut 前)和更早版本的旧行为。
  • Argonaut: v0.48(Argonaut)版本支持的旧值。
  • Bob tail :v0.56(Bobtail)版本支持的值。
  • Firefly :v0.80(Firefly)版本支持的值。
  • hammer :v0.94(Hammer)发行版本所支持的值。
  • jewel :v10.0.2(Jewel)发行版本支持的值。
  • Best :当前的最佳值。
  • 默认值 :新集群的当前默认值。

您可以使用以下命令在正在运行的集群中选择配置集:

# ceph osd crush tunables <profile>
注意

这可能导致某些数据移动。

通常,您应该在升级后或者收到警告时设置 CRUSH 可调项。从版本 v0.74 开始,如果 CRUSH 可调项未设置为其最佳值,Ceph 将发出健康警告,优化值是 v0.73 的默认值。要使此警告消失,有两个选项:

  1. 调整现有群集上的 可调项。请注意,这将导致一些数据移动(可能多达 10%)。这是首选的路由,但在数据移动可能会影响性能的生产集群上应小心。您可以通过以下方法启用最佳可调项:

    # ceph osd crush tunables optimal

    如果事情进展较差(例如,负载过大),或者出现了客户端兼容性问题(旧的内核 cephfs 或 rbd 客户端,或预 Bbtail librados 客户端),您可以切回到较早的配置集:

    # ceph osd crush tunables <profile>

    例如,要恢复 pre-v0.48(Argonaut)值,请执行:

    # ceph osd crush tunables legacy
  2. 您可以通过向 ceph.conf 文件的 [mon] 部分添加以下选项,使警告退出而不对 CRUSH 进行任何更改:

    mon warn on legacy crush tunables = false

    要使更改生效,重启 monitor,或者应用 选项来运行 monitor:

    # ceph tell mon.\* injectargs --no-mon-warn-on-legacy-crush-tunables

2.8.3. 调优 CRUSH,硬方式

如果可以确保所有客户端都运行最新的代码,您可以通过提取 CRUSH map、修改值并将它重新注入到集群中来调整可调项。

  • 提取最新的 CRUSH map:

    ceph osd getcrushmap -o /tmp/crush
  • 调整可调项.这些值似乎为我们测试的大型和小型集群提供最佳行为。您还需要为 crushtool 指定 --enable-unsafe-tunables 参数才能 执行此操作。请谨慎使用这个选项:

    crushtool -i /tmp/crush --set-choose-local-tries 0 --set-choose-local-fallback-tries 0 --set-choose-total-tries 50 -o /tmp/crush.new
  • 重新注入修改的映射:

    ceph osd setcrushmap -i /tmp/crush.new

2.8.4. 传统值

为便于参考,可使用以下方法设置 CRUSH 可调项的旧值:

crushtool -i /tmp/crush --set-choose-local-tries 2 --set-choose-local-fallback-tries 5 --set-choose-total-tries 19 --set-chooseleaf-descend-once 0 --set-chooseleaf-vary-r 0 -o /tmp/crush.legacy

再强调一下,需要使用特殊的 --enable-unsafe-tunables 选项。此外,如上所述,在还原旧值后,请小心运行 ceph-osd 守护进程的旧版本,因为功能位没有被完全强制实施。

2.9. 编辑 CRUSH map

通常,使用 Ceph CLI 在运行时修改 CRUSH map 比手动编辑 CRUSH map 更加方便。但是,在有些情况下,您可能会选择对其进行编辑,如更改默认 bucket 类型,或使用 straw 以外的存储桶算法。

编辑现有的 CRUSH map:

  1. 获取 CRUSH map
  2. 解译 CRUSH map。
  3. 编辑至少一个设备和 Buckets 和规则。
  4. 重新编译 CRUSH map。
  5. 设置 CRUSH map

若要激活特定池的 CRUSH map 规则,可识别常见规则编号,并在创建池时指定池的规则编号。

2.9.1. 获取 CRUSH map

要获取集群的 CRUSH map,请执行以下操作:

ceph osd getcrushmap -o {compiled-crushmap-filename}

Ceph 将输出(-o)编译的 CRUSH map 到您指定的文件名。由于 CRUSH map 采用编译的形式,您必须先解译它,然后才能编辑它。

2.9.2. 解译 CRUSH map

要解译 CRUSH map,请执行以下操作:

crushtool -d {compiled-crushmap-filename} -o {decompiled-crushmap-filename}

Ceph 会将编译后的 CRUSH map 和输出(-o)解译为您指定的文件名。

2.9.3. 编译 CRUSH map

要编译 CRUSH map,请执行以下操作:

crushtool -c {decompiled-crush-map-filename} -o {compiled-crush-map-filename}

Ceph 将存储编译后的 CRUSH map 到您指定的文件名。

2.9.4. 设置 CRUSH map

要为您的集群设置 CRUSH map,请执行以下操作:

ceph osd setcrushmap -i  {compiled-crushmap-filename}

Ceph 将输入您指定为集群 CRUSH map 的文件名编译的 CRUSH map。

2.10. CRUSH 存储策略示例

假设您想要大部分池默认为由大型硬盘驱动器支持的 OSD,但某些池映射到由快速固态驱动器(SSD)支持的 OSD。CRUSH 可以轻松地处理这些场景。

RHCS 2 和 Earlier

在 RHCS 2 和更早的版本中,同一 CRUSH map 中可能存在多个独立的 CRUSH 层次结构,以反映不同的性能域。定义两个包含两个不同根节点的层次结构(例如:"root platter"),另一个用于 SSD(如"root ssd"),如下所示:

device 0 osd.0
device 1 osd.1
device 2 osd.2
device 3 osd.3
device 4 osd.4
device 5 osd.5
device 6 osd.6
device 7 osd.7

  host ceph-osd-ssd-server-1 {
      id -1
      alg straw
      hash 0
      item osd.0 weight 1.00
      item osd.1 weight 1.00
  }

  host ceph-osd-ssd-server-2 {
      id -2
      alg straw
      hash 0
      item osd.2 weight 1.00
      item osd.3 weight 1.00
  }

  host ceph-osd-platter-server-1 {
      id -3
      alg straw
      hash 0
      item osd.4 weight 1.00
      item osd.5 weight 1.00
  }

  host ceph-osd-platter-server-2 {
      id -4
      alg straw
      hash 0
      item osd.6 weight 1.00
      item osd.7 weight 1.00
  }

  root platter {
      id -5
      alg straw
      hash 0
      item ceph-osd-platter-server-1 weight 2.00
      item ceph-osd-platter-server-2 weight 2.00
  }

  root ssd {
      id -6
      alg straw
      hash 0
      item ceph-osd-ssd-server-1 weight 2.00
      item ceph-osd-ssd-server-2 weight 2.00
  }

  rule data {
      ruleset 0
      type replicated
      min_size 2
      max_size 2
      step take platter
      step chooseleaf firstn 0 type host
      step emit
  }

  rule metadata {
      ruleset 1
      type replicated
      min_size 0
      max_size 10
      step take platter
      step chooseleaf firstn 0 type host
      step emit
  }

  rule rbd {
      ruleset 2
      type replicated
      min_size 0
      max_size 10
      step take platter
      step chooseleaf firstn 0 type host
      step emit
  }

  rule platter {
      ruleset 3
      type replicated
      min_size 0
      max_size 10
      step take platter
      step chooseleaf firstn 0 type host
      step emit
  }

  rule ssd {
      ruleset 4
      type replicated
      min_size 0
      max_size 4
      step take ssd
      step chooseleaf firstn 0 type host
      step emit
  }

  rule ssd-primary {
      ruleset 5
      type replicated
      min_size 5
      max_size 10
      step take ssd
      step chooseleaf firstn 1 type host
      step emit
      step take platter
      step chooseleaf firstn -1 type host
      step emit
  }

然后,您可以通过执行以下命令将池设置为使用 SSD 规则:

ceph osd pool set <poolname> crush_ruleset 4
备注
红帽不支持 RHCS 3 及更新版本中 的规则集crush_ruleset 设置。

您的 SSD 池可以充当快速存储池。类似地,您可以使用 ssd-primary 规则将池中的每个 PG 放置为副本,并将 SSD 作为主和副本。

RHCS 3 和 Later

在 RHCS 3 及更高版本中,请使用设备类。这个过程要简单得多:将类添加到每个设备中。例如:

# ceph osd crush set-device-class <class> <osdId> [<osdId>]
# ceph osd crush set-device-class hdd osd.0 osd.1 osd.4 osd.5
# ceph osd crush set-device-class ssd osd.2 osd.3 osd.6 osd.7

然后,创建规则来使用该设备。

# ceph osd crush rule create-replicated <rule-name> <root> <failure-domain-type> <device-class>:
# ceph osd crush rule create-replicated cold default host hdd
# ceph osd crush rule create-replicated hot default host ssd

最后,将池设置为使用 规则。

ceph osd pool set <poolname> crush_rule <rule-name>
ceph osd pool set cold crush_rule hdd
ceph osd pool set hot crush_rule ssd

无需手动编辑 CRUSH map,因为一个层次结构可以提供多类设备。与 RHCS 2 的示例相比,在使用设备类时,CRUSH 映射对于 RHCS 3 来说更加简单。

device 0 osd.0 class hdd
device 1 osd.1 class hdd
device 2 osd.2 class ssd
device 3 osd.3 class ssd
device 4 osd.4 class hdd
device 5 osd.5 class hdd
device 6 osd.6 class ssd
device 7 osd.7 class ssd

  host ceph-osd-server-1 {
      id -1
      alg straw
      hash 0
      item osd.0 weight 1.00
      item osd.1 weight 1.00
      item osd.2 weight 1.00
      item osd.3 weight 1.00
  }

  host ceph-osd-server-2 {
      id -2
      alg straw
      hash 0
      item osd.4 weight 1.00
      item osd.5 weight 1.00
      item osd.6 weight 1.00
      item osd.7 weight 1.00
  }

  root default {
      id -3
      alg straw
      hash 0
      item ceph-osd-server-1 weight 4.00
      item ceph-osd-server-2 weight 4.00
  }


  rule cold {
      ruleset 0
      type replicated
      min_size 2
      max_size 11
      step take default class hdd
      step chooseleaf firstn 0 type host
      step emit
  }


  rule hot {
      ruleset 1
      type replicated
      min_size 2
      max_size 11
      step take default class ssd
      step chooseleaf firstn 0 type host
      step emit
  }

第 3 章 放置组(PG)

放置组(PG)对 Ceph 客户端不可见,但它们在 Ceph 存储群集中扮演着重要的角色。

Ceph 存储集群可能需要数以千计的 OSD 才能达到字节级别的存储容量。Ceph 客户端将对象存储在池中,这是整个集群的逻辑子集。存储在池中的对象数量可能会轻松地进入数百万个和以后。拥有数百万对象或更多对象的系统无法实际地逐个对象地跟踪放置,并且仍然运行良好。Ceph 将对象分配到 PG,并将 PG 分配给 OSD,从而实现动态和效率的重新平衡。

 

计算机科学中的所有问题都可通过另一种级别的间接寻址来解决,当然,对于太多间接子问题除外。

 
 -- David Wheeler

3.1. 关于 PG

以每个对象为基础在池中跟踪对象放置在大规模计算成本上比较昂贵。为了提高大规模性能,Ceph 将池细分为放置组,将每个对象分配到放置组,再将 PG 分配到 Primary OSD。如果 OSD 出现故障或集群重新平衡,Ceph 可以移动或复制整个放置组,即放置组中的所有对象 -​ 不需要单独处理每个对象。这使得 Ceph 集群能够有效地重新平衡或恢复。

关于 PG

当 CRUSH 将 PG 分配给 OSD 时,它会计算一系列 OSD-​ 的第一个 OSD。osd_pool_default_size 设置 minus 1 用于复制池,而纠删代码池 编码区块数则决定存储 PG 的 OSD 数量,该 OSD 在不永久丢失数据的情况下失败。主 OSD 使用 CRUSH 来标识次要 OSD,并将 PG 的内容复制到次要 OSD。例如,如果 CRUSH 将对象分配到 PG,并且 PG 分配至 OSD 5 作为 Primary OSD,如果 CRUSH 计算 OSD 1 和 OSD 8 是 PG 的次要 OSD,Primary OSD 5 会将数据复制到 OSD 1 和 8。Ceph 代表客户端复制数据,从而简化客户端接口并减少客户端工作负载。同一流程允许 Ceph 集群动态恢复和重新平衡。

CRUSH 层次结构

当Primary OSD 出现故障并签出集群时,CRUSH 会将 PG 分配给另一个 OSD,后者接收 PG 中的对象副本。就绪 集合中 的另一个 OSD 将承担Primary OSD 的角色。

根据需要,当增加对象副本或编码区块的数量时,CRUSH 会将每个 PG 分配到额外的 OSD。

注意

PG 不拥有 OSD。CRUSH 将许多 PG 分配给每个 OSD 伪随机,以确保数据在集群中均匀分布。

3.2. 放置组交换

所有 OSD 的数据持久性和数据分布要求更多的放置组,但为了节省 CPU 和内存资源,其数量应降至最低要求。

3.2.1. 数据持续时间

Ceph 努力防止数据永久丢失。但是,在 OSD 出现故障后,永久数据丢失的风险会增加,直到其包含的数据被完全恢复。永久数据丢失虽然很少,但仍可能发生。以下场景描述了 Ceph 如何在具有三个数据副本的单个放置组中永久丢失数据:

  • OSD 出现故障,并且其包含的对象的所有副本都将丢失。对于 OSD 上存储的 PG 中的所有对象,副本数突然从三降至二。
  • Ceph 通过选择新 OSD 来为每个放置组重新创建所有对象的第三个副本,开始恢复存储在故障 OSD 上的每个 PG。
  • 包含同一 PG 副本的第二个 OSD 在新 OSD 完全填充第三个副本之前失败。然后,某些对象将只有一个存活的副本。
  • Ceph 挑选另一个 OSD,并保留复制对象来恢复所需的副本数。
  • 包含同一 PG 的副本的第三个 OSD 在恢复完成之前失败。如果此 OSD 包含对象的唯一剩余副本,则该对象将永久丢失。

硬件故障并非例外,而是预期的结果。为防止这种情况,理想情况下的恢复过程应尽可能快。集群的大小、您的硬件配置和放置组在总恢复时间中扮演着重要角色。

小型集群无法尽快恢复。

在含有 10 个 OSD 的群集中,三个副本池中具有 512 个 PG,CRUSH 将为每个 PG 提供三个 OSD。每个 OSD 结束托管 (512 * 3)/ 10 = ~150 个 PG。当第一个 OSD 出现故障时,集群将同时开始恢复所有 150 个 PG。

Ceph 可能会在剩余的 9 个 OSD 中随机存储剩余的 150 个 PG。因此,每个剩余的 OSD 可能会发送对象副本到所有其他 OSD,并且接收一些新的对象,因为剩余的 OSD 不再负责现在分配给它们的部分 150 个 PG。

恢复时间总量取决于支持池的硬件。例如,在一个 10 个 OSD 集群中,如果一个主机包含一个具有 1 TB SSD 的 OSD,并且 10 GB/s 交换机连接每个 10 个主机,恢复时间将花费 M 分钟。相反,如果主机包含两个 SATA OSD,并且 1 GB/s 交换机连接了五个主机,恢复将花费大量时间。有趣的是,在这个规模的群集中,放置组的数量几乎对数据持久性没有影响。放置组数可以是 128 或 8192,恢复速度不会慢或较快。

不过,将同一 Ceph 集群扩展到 20 个 OSD 而非 10 个 OSD 可能会加快恢复速度,从而显著提高数据持久性。为什么?每个 OSD 现在仅参与 75 个放置组,而非 150。20 OSD 集群仍然需要所有 19 个 OSD 执行相同数量的副本操作才能恢复。在 10 个 OSD 集群中,每个 OSD 必须复制约 100 GB。在 20 OSD 集群中,每个 OSD 只需要每个 OSD 复制到 50 GB。如果网络成为瓶颈,恢复会以最快的速度进行两次。换句话说,随着 OSD 数量的增加,恢复时间会减少。

在大型集群中,PG 计数很重要!

如果示例集群增加到 40 个 OSD,每个 OSD 将仅托管 35 个 PG。如果 OSD 死机,恢复时间会减少,除非出现另一个瓶颈而导致问题改善。不过,如果此集群增加到 200 个 OSD,每个 OSD 将仅托管大约 7 个 PG。如果 OSD 死机,则这些 PG 中的最多 21 (7 * 3) OSD 之间会发生恢复:恢复时间将超过 40 个 OSD,这意味着应增加 PG 的数量!

重要

无论恢复时间有多短,存储 PG 的另一个 OSD 在恢复过程中都会失败。

在上述 10 OSD 集群中,如果任何 OSD 失败,则大约 8 个 PG(即 75 pgs / 9 osds / 9 osds)将只有一个存活副本。如果任何 8 个剩余的 OSD 失败,一个 PG 的最后一个对象可能会丢失(即 8 pgs / 8 osds,只有一个剩余的副本被恢复)。这就是为什么从一些较大的集群开始,最好使用 50 个 OSD。

当集群大小增加到 20 个 OSD 时,丢失三个 OSD 的 PG 数量会下降。第二个 OSD 丢失大约 2(即 35 pgs / 19 osds,而不是 8 个),而第三个 OSD 只有在包含 surviving copy 的两个 OSD 中的一个时,才会丢失数据。换而言之,如果恢复时间范围内丢失一个 OSD 的可能性为 0.0001%,则它从具有 10 个 OSD 的集群中的 8 * 0.0001% 到具有 20 个 OSD 的集群中 2 * 0.0001%。就数据持久性而言,在少于 50 个 OSD 的集群中,拥有 512 或 4096 个 PG 大致相等。

提示

简而言之,更多 OSD 意味着加快恢复速度,降低级联故障风险,从而导致 PG 及其对象永久丢失。

将 OSD 添加到集群中时,可能需要很长时间来填充具有放置组和对象的新 OSD。不过,任何对象都不会降级,添加 OSD 不会影响数据持久性。

3.2.2. 数据分发

Ceph 力图避免热点,即,一些 OSD 获得的流量比其他 OSD 更多。理想情况下,CRUSH 将对象均匀分配给放置组,使得放置组分配到 OSD 时(也是随机的),Primary OSD 存储对象,使得它们均匀分布在群集、热点和网络超额订阅问题中。

由于 CRUSH 计算各个对象的 PG,但实际上不知道此放置组内各个 OSD 中存储多少数据,而 PG 数量和 OSD 的数量可能会显著影响数据的分布。

例如,如果三个副本池中只有一个 PG,Ceph 将仅使用三个 OSD 来存储数据,因为 CRUSH 没有其他选择。当有更多放置组可用时,CRUSH 更有可能在 OSD 之间均匀分布对象。CRUSH 也均匀分配 PG 到 OSD。

只要 PG 比 OSD 高一或两个数量级,分布就应该是均匀的。例如,32 个 PG 用于 3 个 OSD,512 或 1024 个 PG 用于 10 个 OSD,以此类推。

OSD 和 PG 之间的比例通常解决了实施对象分条等高级功能的 Ceph 客户端的数据分布不均匀的问题。例如,一个 4 TB 块设备可能会分片到 4MB 对象中。

在其他情形中,OSD 和 PG 之间的比率不会解决数据分布不均匀的问题,因为 CRUSH 不考虑对象大小。使用 librados 接口存储一些相对较小的对象,一些非常大的对象可能会导致数据分布不均匀。例如,总共 4 GB 的 100万个 4K 对象均匀分布在 10 个 OSD 上的 1000 个放置组中。它们将在每个 OSD 上使用 4 GB / 10 = 400 MB。如果一个 400 MB 的对象添加到池中,则支持放置对象的 PG 的三个 OSD 将会填充 400 MB + 400 MB = 800 MB,而其他七个 OSD 仍然仅被占据 400MB。

3.2.3. 资源使用情况

对于每个放置组,OSD 和 Ceph 监视器始终需要内存、网络和 CPU,在恢复期间则需要更多。在放置组中通过集群对象共享此开销是放置组存在的主要原因之一。

最大程度减少 PG 数量可节省大量资源。

3.3. PG Count

池中 PG 的数量在集群对等、分发数据和重新平衡方面扮演着重要角色。与大型集群相比,小型集群无法通过增加放置组的数量来看到性能增强。但是,访问同一 OSD 的集群可能需要仔细考虑 PG 数量,以便 Ceph OSD 高效地使用资源。

提示

红帽建议每个 OSD 100 到 200 个 PG。

3.3.1. PG Calculator

PG 计算器为您计算 PG 数量,并解决特定的用例。当使用 Ceph 客户端(如 Ceph 对象网关)时,PG 计算器特别有用,因为有许多池通常使用相同的规则(CRUSH 层次结构)。您可能仍然使用 PG Count for Small ClustersCalculating PG Count 来手动计算 PG。不过,PG 计算器是计算 PG 的首选方法。

详情请参阅 红帽客户门户 上的每个池 PG(PG )。

3.3.2. 配置默认 PG 数

在创建池时,您还会为池创建多个 PG。如果不指定放置组的数量,Ceph 将使用默认值 32,对于某些池而言 比较低。您可以为池增加 PG 数量,但我们也建议在 Ceph 配置文件中设置合理的默认值。

注意

为了避免健康警告 POOL_PG_NUM_NOT_POWER_OF_TWO 消息,将两个值用于 PG。

osd pool default pg num = 1024
osd pool default pgp num = 1024

您需要设置 PG 数量(完整),以及用于对象的 PG 数量(用于 PG 拆分)。它们应该是相等的。

3.3.3. 小型集群的 PG Count

小型集群不会从大量放置组中受益。随着 OSD 数量增加,pg_numpgp_num 的正确值变得更为重要,因为它对集群的行为有显著影响,并在出现问题时对数据的持久性(严重事件事件导致数据丢失)。务必要将 PG 计算器 用于小型集群。

3.3.4. 计算 PG 数

如果您有 50 多个 OSD,我们建议每个 OSD 大约 50-100 个 PG,以平衡资源使用量、数据持久性和分布。如果您没有 50 个 OSD,理想的做法是在 PG Count 中选择 Small Clusters。对于单个对象池,您可以使用以下公式来获取基准:

                (OSDs * 100)
   Total PGs =  ------------
                 pool size

其中,池大小 是复制池的副本数量,或者是纠删代码池的 K+M 和(由 ceph osd erasure-code-profile get返回)。

然后,您应该检查结果是否与 Ceph 集群的设计方式有关,以最大程度提高数据的持久性、数据分布并最大程度减少资源使用量。

结果应 四舍五入至 2 个最接近的力量。向上取整是可选的,但建议 CRUSH 在放置组之间均匀平衡对象数量。

对于具有 200 个 OSD 且池大小为 3 个副本的集群,您可以估算 PG 数量,如下所示:

   (200 * 100)
   ----------- = 6667. Nearest power of 2: 8192
        3

放置组分布在 200 个 OSD 的 8192 个 PG 中,它评估到每个 OSD 大约 41 个 PG。您还需要考虑您可能在集群中使用的池数量,因为每个池也会创建 PG。确保您有合理的 最大 PG 数

3.3.5. 最大 PG 数

在使用多个数据池来存储对象时,您需要确保平衡每个池的 PG 数量和每个 OSD 的 PG 数量,以便达到合理的 PG 总数。目标是在不耗费系统资源或使 peering 进程变得太慢的情况下,实现每个 OSD 的相对差异。

在由 10 个池组成的实例式 Ceph 存储群集中,每个池在 10 个 OSD 上具有 512 个 PG,每个 OSD 共有 5,120 个 PG,分散在 10 个 OSD 或 512 个 PG 上。这可能不会根据您的硬件配置使用太多的资源。相比之下,如果您创建 1,000 个池,各自具有 512 个 PG,OSD 将分别处理大约 50,000 个 PG,并且需要的资源明显多得多。每个 OSD 使用太多 PG 运行可能会显著降低性能,特别是在重新平衡或恢复期间。

Ceph 存储集群每个 OSD 的默认值最大为 300 个 PG。您可以在 Ceph 配置文件中设置不同的最大值。

mon_max_pg_per_osd
提示

Ceph 对象网关部署有 10-15 个池,因此您可能会考虑每个 OSD 使用 100 个 PG 以达到合理的上限。

3.4. 自动扩展 PG

池中的 PG 数量在集群对等点、分发数据和重新平衡方面扮演着重要角色。

自动扩展 PG 数量可以使管理集群变得更加轻松。The pg-autoscaling 命令为扩展 PG 提供建议,或者根据集群使用情况自动缩放 PG。

3.4.1. 放置组自动扩展

自动缩放器的工作方式

自动扩展器会分析池,并根据每个子树进行调整。由于每个池可以映射到不同的 CRUSH 规则,并且每一规则可以在不同的设备之间分发数据,因此 Ceph 会分别考虑层次结构中各个子树的利用率。例如,map 到类 ssd 的 OSD 的池,以及映射到类 hdd 的 OSD 的池,各自具有依赖于这些对应设备类型的最优 PG 计数。

3.4.2. 放置组分割和合并

splitting

红帽 Ceph 存储可以将现有的 PG 分成较小的 PG,这会增加给定池的 PG 总数。拆分现有放置组(PG)使小型红帽 Ceph 存储集群能够在存储要求增加时随着时间而扩展。PG 自动扩展功能可以增加 the pg_num 值,这将导致现有 PG 在存储集群扩展时被分割。如果 PG 自动扩展功能已被禁用,您可以手动提高 pg_num 值,这会触发 PG 分割过程开始。例如,将 the pg_num 值从 4 增加到 16 将分为四个部分:增加 the pg_num 值也会增加 pgp_num 值,但 pgp_num 值会逐步增加。这种逐步增长是为了最大程度降低对存储集群性能和客户端工作负载的影响,因为迁移对象数据会对系统造成大量负载。默认情况下,Ceph 队列且不超过"misplaced"状态的对象数据的 5%。可以使用 target_max_misplaced_ratio 选项调整此默认百分比。

149 Ceph Auto scalling 0321 splitting

合并

红帽 Ceph 存储还可以将两个现有的 PG 合并到一个较大的 PG 中,这会减少 PG 的总数。将两个 PG 合并到一起可能会很有用,特别是池中对象的相对数量减少或初始选择的 PG 数量过大时。虽然合并 PG 非常有用,但它也是一个复杂的进程。在进行合并时,暂停 I/O 到 PG 时,一次仅合并一个 PG,以最大程度降低对存储集群性能的影响。Ceph 在合并对象数据时缓慢工作,直到达到 new pg_num 值为止。

149 Ceph Auto scalling 0321 合并

3.4.3. 设置放置组自动扩展模式

红帽 Ceph 存储集群中的每个池都有 PG 的 a pg_autoscale_mode 属性,您可以设置为 offonwarn

  • off :禁用池的自动扩展。管理员应当要为每个池选择适当的 PG 编号。如需更多信息,请参阅 PG count 部分。
  • on on :启用对给定池的 PG 计数自动调整。
  • War n:当 PG 计数需要调整时,发出健康警报。

pg_autoscale_mode 的默认值为 warn 模式。

流程

  1. set pg_autoscaling_mode

    1. 对于现有池:

      ceph osd pool set pool-name pg_autoscale_mode mode

      例如,要在池 testpool 上启用自动扩展:

      $ ceph osd pool set testpool pg_autoscale_mode on
    2. 作为新创建的池的默认值:

      # ceph config set global osd_pool_default_pg_autoscale_mode <mode>

3.4.4. 查看放置组自动扩展建议

流程

  1. 您可以使用以下方法查看每个池、其相对利用率以及对 PG 计数的任何推荐更改:

    ceph osd pool autoscale-status

    输出结果类似如下:

    POOL                        SIZE TARGET SIZE RATE RAW CAPACITY  RATIO TARGET RATIO EFFECTIVE RATIO BIAS PG_NUM NEW PG_NUM AUTOSCALE
    cephfs_data                  65               3.0       449.9G 0.0000                               1.0     32            warn
    cephfs_metadata           78724               3.0       449.9G 0.0000                               1.0      8            warn
    .rgw.root                  3062               3.0       449.9G 0.0000                               1.0     32            warn
    default.rgw.control           0               3.0       449.9G 0.0000                               1.0     32            warn
    default.rgw.meta           1304               3.0       449.9G 0.0000                               1.0     32            warn
    default.rgw.log            6761               3.0       449.9G 0.0000                               1.0     32            warn
    default.rgw.buckets.index     0               3.0       449.9G 0.0000                               1.0     32            warn
    default.rgw.buckets.data   4910               3.0       449.9G 0.0000                               1.0     32            warn
    ocs-ext                   119.2M              3.0       449.9G 0.0008                               1.0     32            warn

SIZE 是池中存储的数据量。TARGET SIZE (如果存在)是管理员所指定的数据量,它们最终预计存储在这个池中。系统将较大的值用于计算。

RATE 是池的倍数,它决定了池使用的原始存储容量。例如,3 个副本池的比例为 3.0,而 k=4,m=2 纠删代码池则比率为 1.5

RAW CAPACITY 是 OSD 上原始存储容量的总量,它们负责存储池的数据。RATIO 是池消耗的总容量的比例,即比率 = 大小 * 速率/原始容量。

TARGET RATIO (若存在)是管理员指定的存储比率,他们希望池相对于设置了目标比率的其他池使用。如果同时指定了目标大小字节和比率,则比率优先。

EFFECTIVE RATIO 是调整后通过两种方式调整后的目标比率:1. 减去由设置了目标大小的池预期使用的任何容量。2. 规范设置了目标比率的池之间的目标比率,以便它们共同将剩余空间作为目标。例如,4 个 目标比率为 1.0 的池将 有效比率为 0.25。系统使用较大的实际比率和计算的有效比率。

BIAS 是池属性,PG 自动扩展器以 PG 数量比其他池更快地扩展。它基本上是一个倍数,用于向池提供比默认 PG 数量更多的 PG。此属性特别用于元数据池,它们的大小可能很小,但具有大量对象,因此更快地扩展它们对于更好的性能至关重要。BIAS 的默认值为 1.0。您可以通过运行 ceph osd pool set pool-name pg_autoscale_bias 4 命令来设置这个值。接受的值介于 0 到 1000 之间。但是,建议默认为 CephFS 元数据池和 Ceph 对象网关索引池将 BIAS 的值设置为 4.0。

PG_NUM 是池的当前 PG 数量,或者池正在工作的 PG 数量(如果 a pg_num 正在进行更改)。新 PG_NUM (若存在)是推荐的 PG 数量(pg_num)。它始终是 2 的幂,且只有建议的值与当前值相差时超过 3 倍。

AUTOSCALE 是 pool pg_autoscale_mode,是 onoffwarn

3.4.5. 设置放置组自动扩展

允许集群根据集群使用情况自动扩展 PG 是扩展 PG 最简单的方法。红帽 Ceph 存储提取整个系统的可用存储总数和目标 PG 数量,比较每个池中存储的数据量,并相应地调整 PG。命令仅对当前数量 PG(pg_num)超过计算或建议的 PG 编号的池进行更改。

每个 OSD 的 PG 的目标数量基于可配置的 mon_target_pg_per_osd。默认值为 100

流程

  1. 调整 mon_target_pg_per_osd:

    ceph config set global mon_target_pg_per_osd number

    例如:

    $ ceph config set global mon_target_pg_per_osd 150

3.4.6. 指定目标池大小

新创建的池消耗集群总容量的一小部分,显示在系统中需要少量 PG。然而,在大多数情况下,集群管理员知道哪些池会随着时间推移消耗大多数系统容量。如果您提供此信息(称为红帽 Ceph 存储 的目标大小 ),则这些池可以从开始便使用更合适的 PG 数量(pg_num)。这种方法可以防止后续的 change pg_num 以及那些调整时移动数据相关的开销。

您可以通过以下方法指定池 的目标大小

3.4.6.1. 使用池的绝对大小指定目标大小

流程

  1. 使用池的绝对 大小(以字节为单位)设置目标 大小:

    ceph osd pool set pool-name target_size_bytes value

    例如,指示 mypool 应该 消耗 100T 空间的系统:

    $ ceph osd pool set mypool target_size_bytes 100T

您还可以通过在 ceph osd pool create 命令中添加可选 --target-size-bytes <bytes> 参数来设置池在创建时的目标大小。

3.4.6.2. 使用集群总容量指定目标大小

流程

  1. 使用集群总容量比率设置 目标大小

    ceph osd pool set pool-name target_size_ratio ratio

    例如:

    $ ceph osd pool set mypool target_size_ratio 1.0

    告知系统,池 mypool 应该相对于设置了 target_size_ratio 的其他池使用 1.0。如果 mypool 是集群中唯一的池,这意味着预期使用总容量的 100%。如果存在 target_size_ratio 为 1.0 的第二个池,则两个池都将使用 50% 的群集容量。

您还可以通过在 ceph osd pool create 命令中添加可选 --target-size-ratio <ratio> 参数来设置池在创建时的目标大小。

注意

如果您指定无法达到的目标大小值,例如大于集群总数的容量,或者总和大于 1.0 的比率,集群会引发 POOL_TARGET_SIZE_RATIO_OVERCOMMITTEDPOOL_TARGET_SIZE_BYTES_OVERCOMMITTED 健康警告。

如果您为池指定了 target_size_ratiotarget_size_bytes,集群只考虑这个比例,并引发 POOL_HAS_TARGET_SIZE_BYTES_AND_RATIO 健康警告。

3.5. PG 命令行参考

通过 ceph CLI,您可以设置池的 PG 数量并获取其数量,查看 PG map 并检索 PG 统计信息。

3.5.1. 设置 PG 数

要在池中设置 PG 数量,您必须在创建池时指定 PG 数量。详情请参阅 创建池。要在创建池后更改 PG 数量,请执行以下操作:

ceph osd pool set {pool-name} pg_num {pg_num}

旦增加了 PG 的数量,还必须增加放置的 PG 数量(pgp_num),然后才能重新平衡集群。The pgp_num 应当等于 the pg_num。The pgp_num 将是由 CRUSH 算法考虑放置的 PG 数量。Increasing pg_num 可分割 PG,但不会将数据迁移到较新的 PG,直到放置的 PG 被增加,即 pgp_num。要增加放置的 PG 数量,请执行以下操作:

ceph osd pool set {pool-name} pgp_num {pgp_num}

在减少 PG 数量时,pgp_num 会自动调整。

3.5.2. 获取 PG 数量

要获取池中 PG 的数量,请执行以下操作:

ceph osd pool get {pool-name} pg_num

3.5.3. 获取 Cluster PG Statistics

要获取集群中 PG 的统计信息,请执行以下操作:

ceph pg dump [--format {format}]

有效格式为 纯文本 (默认)和 json

3.5.4. 获取 Stuck PG 的统计信息

要获取处于指定状态的所有放置组的统计信息,请执行以下操作:

ceph pg dump_stuck {inactive|unclean|stale|undersized|degraded [inactive|unclean|stale|undersized|degraded...]} {<int>}

活跃的 PG 无法处理读取和写入,因为它们正在等待具有最新数据的 OSD 出现并进入。

unclean 放置组包含没有复制所需次数的对象。它们应该正在恢复。

stale Placement 组处于未知状态 - 托管它们的 OSD 暂时尚未报告到 monitor 集群( mon_osd_report_timeout配置)。

有效格式为 纯文本 (默认)和 json。该阈值定义 PG 在将 PG 包含在返回统计信息(默认值 300 秒)之前卡住的最少秒数。

3.5.5. 获取 PG map

要获取特定 PG 的 PG map,请执行以下操作:

ceph pg map {pg-id}

例如:

ceph pg map 1.6c

Ceph 将返回 PG map、PG 和 OSD 状态:

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

3.5.6. 获取 PG 统计信息

要检索特定放置组的统计信息,请执行以下操作:

ceph pg {pg-id} query

3.5.7. 清理 PG

要清理 PG,请执行以下操作:

ceph pg scrub {pg-id}

Ceph 检查主节点和任何副本节点,生成放置组中所有对象的目录,并将它们进行比较,以确保没有对象缺失或不匹配,并且其内容一致。假设副本全部匹配,则最终语义深度可确保与快照相关的所有对象元数据保持一致。错误通过日志中报告。

3.5.8. 恢复失败

如果集群丢失了一个或多个对象,并且您决定放弃搜索丢失的数据,您必须将未找到的对象标记为 丢失

如果查询了所有可能的位置,并且对象仍丢失,您可能必须放弃丢失的对象。这可能是因为异常故障组合允许集群了解在恢复写入本身前执行的写入操作。

目前唯一支持的选项是"恢复",该选项将回滚到对象的以前版本,或者(如果它是一个新对象)完全忘记该对象。要将 "unfound" 对象标记为 "lost",请执行以下操作:

ceph pg {pg-id} mark_unfound_lost revert|delete
重要

请谨慎使用此功能,因为它可能会让对象存在混淆。

第 4 章 池

Ceph 客户端在池中存储数据。在创建池时,您将为客户端创建 I/O 接口以存储数据。从 Ceph 客户端(即块设备、网关和其他)与 Ceph 存储集群交互的视角来说比较简单:创建集群处理和连接到集群;然后创建一个 I/O 上下文,用于读取和编写对象及其扩展属性。

创建集群 Handle 和连接到集群

若要连接 Ceph 存储集群,Ceph 客户端需要集群名称(默认为 ceph )和初始监控地址。Ceph 客户端通常使用 Ceph 配置文件的默认路径来检索这些参数,然后从 文件读取,但用户也可能会在命令行中指定参数。Ceph 客户端也提供用户名和密码密钥( 默认为 身份验证 )。然后,客户端联系 Ceph 监控集群,并检索 cluster map 的最新副本,包括其监视器、OSD 和池。

创建流程

创建池 I/O 上下文

为了读取和写入数据,Ceph 客户端为 Ceph 存储集群中的特定池创建 i/o 上下文。如果指定用户对池具有权限,Ceph 客户端可以从指定的池读取和写入。

I/O 上下文

Ceph 的架构使存储集群能够向 Ceph 客户端提供这一显著简单接口,以便客户端可以通过指定池名称并创建 I/O 上下文即可选择您定义的一个复杂的存储策略。除了容量和性能外,存储策略都对 Ceph 客户端不可见。类似地,Ceph 客户端的复杂性(将对象映射到块设备表示法,提供 S3/Swift RESTful 服务)对 Ceph 存储集群不可见。

池为您提供:

  • 弹性 :您可以设置允许多少 OSD 失败而不丢失数据。对于复制池,这是对象的所需副本/副本数。典型的配置存储一个对象及一个额外副本(即 size = 2),但您可以确定副本/副本的数量。对于纠删代码池,它是编码区块数(即 纠删代码 profile中的 m=2
  • 放置组 :您可以为池设置 PG 数量。典型的配置为每个 OSD 使用大约 50-100 的放置组来提供最佳平衡,而不占用过多的计算资源。在设置多个池时,请小心确保为池和整个集群设置合理的放置组数量。
  • CRUSH 规则 :在池中存储数据时,映射到池的 CRUSH 规则可以让 CRUSH 识别集群中各个对象的放置规则及其副本(或纠删代码池的块)。您可以为您的池创建自定义 CRUSH 规则。
  • 快照 :使用 ceph osd 池 mksnap 创建快照时,您实际上会对特定的池执行快照。
  • 配额 :当您在具有 ceph osd pool set-quota 的池中设置配额时,可能会限制在指定池中存储的最大字节数或最大字节数。

4.1. 池和存储策略

若要管理池,您可以列出、创建和删除池。您还可以查看每个池的利用率统计信息。

4.2. 列出池

要列出集群的池,请执行:

ceph osd lspools

4.3. 创建池

在创建池之前,请参阅《红帽 Ceph 存储 4 配置 指南》中的池、PG 和 CRUSH 配置 参考 一章。

注意

在红帽 Ceph 存储 3 及更高版本中,系统管理员必须明确使池能够从 Ceph 客户端接收 I/O 操作。详情请参阅 启用应用程序。如果无法启用池,则会导致 HEALTH_WARN 状态

最好在 Ceph 配置文件中调整 PG 数量的默认值,因为默认值不必满足您的需要。例如:

osd pool default pg num = 100
osd pool default pgp num = 100

要创建复制池,请执行:

ceph osd pool create <pool-name> <pg-num> <pgp-num> [replicated] \
         [crush-rule-name] [expected-num-objects]

要创建纠删代码池,请执行:

ceph osd pool create <pool-name> <pg-num> <pgp-num> erasure \
         [erasure-code-profile] [crush-rule-name] [expected-num-objects]

其中:

pool-name
描述
池的名称。它必须是唯一的。
类型
字符串
必填
可以。如果未指定,它将设置为 Ceph 配置文件中列出的值或默认值。
默认
Ceph
pg_num
描述
池的 PG 总数。有关计算适当编号的详细信息 请参阅 每个池计算器的 PG 和 Ceph 放置组(PG )。默认值为 8 不适用于大多数系统。
类型
整数
必填
默认
8
pgp_num
描述
用于放置的 PG 的总数。这个值必须等于放置组总数,但放置组分割场景除外。
类型
整数
必填
可以。如果没有指定,它将设置为 Ceph 配置文件中列出的值或默认值。
默认
8
复制或纠删
描述
池类型,可以通过保留多个对象副本或 纠删 来从丢失的 OSD 中恢复,也可以被 复制 以获取一种通用的 RAID5 功能。复制池需要更多原始存储,但实施所有 Ceph 操作。纠删代码池需要较少的原始存储,但仅实施可用操作的子集。
类型
字符串
必填
默认
复制
crush-rule-name
描述
池的 crush 规则的名称。规则 MUST 存在。对于复制池,其名称是由 osd_pool_default_crush_rule 配置设置指定的规则。对于纠删代码池,如果另外指定默认纠删代码 profile 或 {pool-name},则名称为 erasure- code。如果规则尚不存在,Ceph 会以隐式方式创建此规则,其名称为指定的名称。
类型
字符串
必填
默认
erasure-code 用于纠删代码池。对于复制池,它使用 Ceph 配置中的 osd_pool_default_crush_rule 变量的值。
expected-num-objects
描述
池的预期对象数量。通过将此值与负 filestore_merge_threshold 变量一起设置,Ceph 在创建池时分割 PG,以避免延迟影响,从而执行运行时目录分割。
类型
整数
必填
默认
0,在创建池时没有分割
erasure-code-profile
描述
仅用于纠删代码池。使用纠删代码 profile。它必须是现有 profile,如 Ceph 配置文件中的 osd erasure-code-profile set 变量所定义。如需更多信息,请参阅 Erasure Code Profiles 部分。
类型
字符串
必填

创建池时,将 PG 数量设置为合理的值(例如 100)。也请考虑每个 OSD 的 PG 总数。放置组的计算成本很高,因此当有多个 PG 的池(例如,每个 PG 拥有 50 个池)时,性能会降低。递减返回的点取决于 OSD 主机的电源。

如需有关为您的 池计算适当数量的 PG 的详细信息,请参阅每个池的 PG 部分 和 Ceph 放置组(PG )。

4.4. 设置池配额

您可以为每个池或这两个池的最大字节数或对象的最大数量设置池配额。

ceph osd pool set-quota <pool-name> [max_objects <obj-count>] [max_bytes <bytes>]

例如:

ceph osd pool set-quota data max_objects 10000

若要删除配额,可将其值设为 0

注意

在 Ceph 在集群中传播池使用量前,会短时间内超过池配额。这是正常行为。在机后写操作中强制实施池配额会严重影响性能。

4.5. 删除池

要删除池,请执行:

ceph osd pool delete <pool-name> [<pool-name> --yes-i-really-really-mean-it]
重要

为保护数据,在 RHCS 3 及更高版本中,管理员默认无法删除池。在删除池之前,设置 mon_allow_pool_delete 配置选项。

重要

如果 Ceph 对象网关使用这个池,请在删除池后重新启动 RGW 进程。

如果池有自己的规则,请考虑在删除池后将其删除。如果池有严格的用户供其自身使用,请考虑在删除池后删除这些用户。

4.6. 重命名池

要重命名池,请执行:

ceph osd pool rename <current-pool-name> <new-pool-name>

如果您重命名了池,并且具有经过身份验证的用户的每池功能,则必须使用新的池名称更新用户的功能(即 caps)。

4.7. 显示池统计信息

要显示池的使用情况统计数据,请执行:

rados df

4.8. 设置池值

要将值设置为池,请执行以下命令:

ceph osd pool set <pool-name> <key> <value>

Pool Values 部分列出了您可以设置的所有键值对。

4.9. 获取池值

要从池中获取值,请执行以下命令:

ceph osd pool get <pool-name> <key>

Pool Values 部分列出了您可以获取的所有键值对。

4.10. 启用应用程序

RHCS 3 及更新的版本为池提供了额外的保护,以防止未授权类型的客户端将数据写入池。这意味着,系统管理员必须明确使池能够从 Ceph 块设备、Ceph 对象网关、Ceph 文件系统或自定义应用程序接收 I/O 操作。

要让客户端应用程序对池执行 I/O 操作,请执行以下操作:

[root@host ~]# ceph osd pool application enable <poolname> <app> {--yes-i-really-mean-it}

其中 <app> 是:

  • 用于 Ceph 文件系统的 CephFS.
  • RBD 用于 Ceph 块设备
  • rgw 用于 Ceph 对象网关
注意

为自定义应用程序指定不同的 <app> 值

重要

未启用的池将生成 HEALTH_WARN 状态。在该场景中,ceph 运行状况详情 -f json-pretty 的输出将输出以下内容:

{
    "checks": {
        "POOL_APP_NOT_ENABLED": {
            "severity": "HEALTH_WARN",
            "summary": {
                "message": "application not enabled on 1 pool(s)"
            },
            "detail": [
                {
                    "message": "application not enabled on pool '<pool-name>'"
                },
                {
                    "message": "use 'ceph osd pool application enable <pool-name> <app-name>', where <app-name> is 'cephfs', 'rbd', 'rgw', or freeform for custom applications."
                }
            ]
        }
    },
    "status": "HEALTH_WARN",
    "overall_status": "HEALTH_WARN",
    "detail": [
        "'ceph health' JSON format has changed in luminous. If you see this your monitoring system is scraping the wrong fields. Disable this with 'mon health preluminous compat warning = false'"
    ]
}
备注
使用 rbd pool init <pool-name> 为 Ceph 块设备初始化池。

4.11. 禁用应用程序

要禁用客户端应用程序对池执行 I/O 操作,请执行以下操作:

[root@host ~]# ceph osd pool application disable <poolname> <app> {--yes-i-really-mean-it}

其中 <app> 是:

  • 用于 Ceph 文件系统的 CephFS.
  • RBD 用于 Ceph 块设备
  • rgw 用于 Ceph 对象网关
注意

为自定义应用程序指定不同的 <app> 值

4.12. 设置应用程序元数据

RHCS 3 及更新的版本提供了设置描述客户端应用属性的键值对的功能。

要在池中设置客户端应用程序元数据,请执行以下操作:

[root@host ~]# ceph osd pool application set <poolname> <app> <key> <value>

其中 <app> 是:

  • 用于 Ceph 文件系统的 CephFS.
  • RBD 用于 Ceph 块设备
  • rgw 用于 Ceph 对象网关
注意

为自定义应用程序指定不同的 <app> 值

4.13. 删除应用程序元数据

要删除池中的客户端应用程序元数据,请执行以下操作:

[root@host ~]# ceph osd pool application set <poolname> <app> <key>

其中 <app> 是:

  • 用于 Ceph 文件系统的 CephFS.
  • RBD 用于 Ceph 块设备
  • rgw 用于 Ceph 对象网关
注意

为自定义应用程序指定不同的 <app> 值

4.14. 设置对象副本数

要在复制池中设置对象副本数量,请执行以下命令:

ceph osd pool set <poolname> size <num-replicas>
重要

<num-replicas> 参数包含对象本身。如果要为对象总计三个实例包含对象的对象和两个副本,请指定 3

例如:

ceph osd pool set data size 3

您可以对每个池执行此命令。

注意

对象可能会接受降级模式中的 I/O 操作,其副本数比 池大小 设置所指定少。要为 I/O 设置最小副本数,请使用 min_size 设置。例如:

ceph osd pool set data min_size 2

这样可确保数据池中没有对象接收的副本数少于 min_size 设置所指定数量的 I/O。

4.15. 获取对象副本数

要获取对象副本的数量,请执行以下命令:

ceph osd dump | grep 'replicated size'

Ceph 将列出池,并且突出显示 复制大小 属性。默认情况下,Ceph 创建一个对象的两个副本,共三个副本,大小为 3

4.16. 池值

以下列表包含您可以设置或获得的键值对。如需更多信息,请参阅 设置池值 和获取 池值 部分。

Size
描述
指定池中对象的副本数。详情请查看 设置对象副本的数量 部分。仅适用于复制池。
类型
整数
min_size
描述
指定 I/O 所需的最少副本数。详情请查看 设置对象副本的数量 部分。仅适用于复制池。
类型
整数
crash_replay_interval
描述
指定允许客户端重播已确认但未提交的请求的秒数。
类型
整数
pg-num
描述
池的 PG 总数。如需了解有关计算适当数量的详细信息,请参阅《红帽 Ceph 存储 4 配置指南》 中的 池、PG 和 CRUSH 配置参考 部分。默认值为 8 不适用于大多数系统。
类型
整数
必填
可以。
默认
8
pgp-num
描述
用于放置的 PG 的总数。这应当等于 PG 的总数,但放置组分割场景除外
类型
整数
必填
可以。如果未指定,则选取 default 或 Ceph 配置值。
默认
8
有效范围
等于或小于 pg_num 变量所指定的内容。
crush_rule
描述
用于在集群中映射对象放置的规则。
类型
字符串
hashpspool
描述
在给定池中启用或禁用 HASHPSPOOL 标志。启用此选项后,池散列和放置组映射更改为改进池和放置组的重叠方式。
类型
整数
有效范围
1 可启用该标志,0 可禁用该标志。
重要

不要在有大量 OSD 和数据的集群的生产池上启用此选项。必须重新映射池中的所有放置组,从而导致数据移动过多。

fast_read
描述
在使用纠删代码的池中,如果启用了此标志,读取请求会后续对所有分片读取,并等待它接收到足够分片以解码来为客户端服务。对于 jerasure 和 is a 纠删 插件,一旦第一个 K 回复返回,客户端的请求将立即使用这些回复中解码的数据提供。这有助于分配一些资源以提高性能。目前,这个标志只支持纠删代码池。
类型
布尔值
默认值
0
allow_ec_overwrites
描述
写入纠删代码池是否可以更新对象的一部分,以便 Ceph 文件系统和 Ceph 块设备可以使用它。
类型
布尔值
Version
RHCS 3 及更高版本.
compression_algorithm
描述
设置要与 BlueStore 存储后端一起使用的内联压缩算法。此设置覆盖 bluestore_compression_algorithm 配置设置。
类型
字符串
有效设置
lz4,snappy, zlib,zstd
compression_mode
描述
为 BlueStore 存储后端的内联压缩算法设置策略。此设置覆盖 bluestore_compression_mode 配置设置。
类型
字符串
有效设置
被动积极强制
compression_min_blob_size
描述
BlueStore 不会压缩小于这个大小的块。此设置覆盖 bluestore_compression_min_blob_size 配置设置。
类型
未签名的 Integer
compression_max_blob_size
描述
BlueStore 会在压缩数据前将大于这个大小的块分成较小的 blob of of compression_max_blob_size
类型
未签名的 Integer
nodelete
描述
在给定池上设置或取消设置 NODELETE 标志。
类型
整数
有效范围
1 设置标志.0 未设置标记。
nopgchange
描述
在给定池中设置或取消设置 NOPGCHANGE 标志。
类型
整数
有效范围
1 可设置 标志.0 取消设置标志。
nosizechange
描述
在给定池中设置或取消设置 NOSIZECHANGE 标志。
类型
整数
有效范围
1 可设置 标志.0 取消设置标志。
write_fadvise_dontneed
描述
在给定池中设置或取消设置 WRITE_FADVISE_DONTNEED 标志。
类型
整数
有效范围
1 可设置 标志.0 取消设置标志。
noscrub
描述
在给定池上设置或取消设置 NOSCRUB 标志。
类型
整数
有效范围
1 可设置 标志.0 取消设置标志。

nodeep-scrub

描述
在给定池上设置或取消设置 NODEEP_SCRUB 标志。
类型
整数
有效范围

1 可设置 标志.0 取消设置标志。

scrub_min_interval
描述
负载较低时池清理的最小间隔(以秒为单位)。如果是 0,Ceph 将使用 osd_scrub_min_interval 配置设置。
类型
默认

0

scrub_max_interval
描述
无论集群负载如何,池清理的最大间隔(以秒为单位)。如果是 0,Ceph 将使用 osd_scrub_max_interval 配置设置。
类型
默认

0

deep_scrub_interval
描述
池"deep"清理的时间间隔(以秒为单位)。如果是 0,Ceph 将使用 osd_deep_scrub_interval 配置设置。
类型
默认
0

第 5 章 纠删代码池

Ceph 存储策略涉及定义数据持久性要求。数据持久性意味着能够在不丢失数据的情况下持续丢失一个或多个 OSD。

Ceph 将数据存储在池中,池中有两种类型的池:

  • 复制
  • erasure-coded

Ceph 默认使用复制池,即 Ceph 将Primary OSD 节点的每个对象复制到一个或多个次要 OSD。

纠删代码池减少了确保数据持久性所需的磁盘空间量,但在计算上比复制成本高一些。

纠删代码是一种在 Ceph 存储群集中持久存储对象的方法,其中纠删代码算法会将对象分解为数据区块(k)和编码区块(m),并将这些区块存储在不同的 OSD 中。

如果 OSD 出现故障,Ceph 会从其他 OSD 检索剩余的数据(k)和编码(m)区块,并且纠删代码算法从这些区块中恢复对象。

注意

红帽建议使用 min_size 使纠删代码池为 K+2 或更多,以防止丢失写入和数据。

纠删代码比复制更高效地使用存储容量。n 复制方法维护对象的 n 副本(Ceph 中默认为 3x),而纠删代码仅维护 k + m 块。例如: 4 数据和 2 编码区块使用原始对象的存储空间 1.5x。

虽然纠删代码使用的存储开销比复制少,但纠删代码算法在访问或恢复对象时所用的 RAM 和 CPU 数量要多于复制。当数据存储必须具有持久性和容错能力但不需要快速读取性能(如冷存储和历史记录等)时,纠删代码具有优势。

有关 Ceph 中纠删代码如何工作的数学和详细说明,请参见 《红帽 Ceph 存储 4 架构指南 》中的纠删代码 I/O 部分。

在初始化具有 k=2m=1 的群集时,Ceph 会创建一个 默认的 纠删代码 profile。这意味着 Ceph 会将对象数据分散到三个 OSD(k+m == 3),Ceph 可以在不丢失数据的情况下丢失其中一个 OSD。要了解更多有关纠删代码性能分析的信息,请参阅 Erasure Code Profiles 部分。

重要

仅将 .rgw.buckets 池配置为纠删代码池和所有其他 Ceph 对象网关池复制,否则尝试创建新存储桶会失败并显示以下错误:

set_req_state_err err_no=95 resorting to 500

其原因在于纠删代码池不支持 omap 操作,而某些 Ceph 对象网关元数据池需要支持 omap

5.1. 创建示例纠删代码池

最简单的纠删代码池等同于 RAID5,至少需要三个主机:

$ ceph osd pool create ecpool 50 50 erasure
pool 'ecpool' created
$ echo ABCDEFGHI | rados --pool ecpool put NYAN -
$ rados --pool ecpool get NYAN -
ABCDEFGHI
注意

池 create 中的 50 代表 PG 的数量。

5.2. 纠删代码配置集

Ceph 定义带有 profile 的纠删代码池。Ceph 在创建纠删代码池和关联的 CRUSH 规则时使用 profile。

Ceph 在初始化集群时会创建一个默认的纠删代码 profile,它提供与复制池中两个副本相同的冗余级别。但是,它使用的存储容量要少 25%。默认配置文件定义 k=2m=1,这意味着 Ceph 会将对象数据分散到三个 OSD(k+m=3),Ceph 可能会丢失其中一个 OSD,而不丢失数据。

默认纠删代码 profile 可以持续丢失单个 OSD。它等同于大小为 2 的复制池,但需要 1.5 TB 而不是 2 TB 来存储 1 TB 数据。要显示默认配置集,请使用以下命令:

$ ceph osd erasure-code-profile get default
directory=.libs
k=2
m=1
plugin=jerasure
crush-failure-domain=host
technique=reed_sol_van

您可以创建新配置集来提高冗余性,而不增加原始存储要求。例如,具有 k=8 和 m= 4 的配置集可以通过在12(k+m=12)OSD 上分布对象来维持 4(m=4)OSD 丢失。Ceph 将对象划分为 8 个 区块,并计算 4 个 编码区块以进行恢复。例如,如果对象大小为 8 MB,则每个数据区块的大小为 1 MB,每个编码区块的大小与数据区块大小相同,这也是 1 MB。即使四个 OSD 同时出现故障,对象也不会丢失。

配置集最重要的参数是 kmcrush-failure-domain,因为它们定义存储开销和数据持久性。

重要

选择正确的配置集非常重要,因为您创建池后无法更改配置集。若要修改配置文件,您必须创建一个具有不同配置文件的新池,并将对象从旧池中迁移到新池中。

例如,如果所需构架必须维持两个机架的丢失,存储开销为 50%,则可定义以下配置集:

$ ceph osd erasure-code-profile set myprofile \
   k=4 \
   m=2 \
   crush-failure-domain=rack
$ ceph osd pool create ecpool 12 12 erasure *myprofile*
$ echo ABCDEFGHIJKL | rados --pool ecpool put NYAN -
$ rados --pool ecpool get NYAN -
ABCDEFGHIJKL

Primary OSD 将 NYAN 对象划分为四个(k=4)数据区块,再创建两个额外的区块(m=2)。m 的值定义可以同时丢失多少个 OSD,而不丢失任何数据。crush-failure-domain=rack 将创建一个 CRUSH 规则,确保同一机架中不存储任何两个区块。

纠删代码
重要

红帽支持 km 的以下纠删代码值:

  • k=8 m=3
  • k=8 m=4
  • k=4 m=2
重要

如果丢失的 OSD 数量等于编码区块数(m),纠删代码池中的一些放置组将进入不完整状态。如果丢失的 OSD 数量小于 m,则任何 PG 都不会进入不完整的状态。在这两种情况下,不会发生数据丢失。如果 PG 处于不完整状态,则临时减少纠删代码池的 min_size 将允许恢复。

5.2.1. OSD erasure-code-profile 设置

创建新纠删代码 profile:

ceph osd erasure-code-profile set <name> \
         [<directory=directory>] \
         [<plugin=plugin>] \
         [<stripe_unit=stripe_unit>] \
         [<crush-device-class>]\
         [<crush-failure-domain>]\
         [<key=value> ...] \
         [--force]

其中:

目录
描述
设置从其中加载纠删代码插件 的目录 名称。
类型
字符串
必填
否.
默认
/usr/lib/ceph/erasure-code
plugin
描述
使用纠删代码插件计算编码区块并恢复缺少的区块。详情请查看 纠删代码插件 部分。
类型
字符串
必填
否.
默认
jerasure
stripe_unit
描述
数据区块中的数据量,每个分条.例如:带有 2 个数据块和 stripe_unit=4K 的配置集会将 0-4K 范围放在块 0 中,4K-8K 放在块 1 中,然后再次以块 0 为 8K-12K。为了获得最佳性能,这应该是 4K 的倍数。创建池时,从 monitor config 选项 osd_pool_erasure_code_stripe_unit 获取默认值。使用此配置集的池的 stripe_width 将是此 stripe_unit 乘以的数据区块数。
类型
字符串
必填
否.
默认
4K
crush-device-class
描述
设备类,如 hdd 或 ssd。仅适用于 RHCS 3 及更高版本.
类型
字符串
必填
默认
,这意味着 CRUSH 都使用所有设备,无论类如何.
crush-failure-domain
描述
故障域,如 host 或 rack
类型
字符串
必填
默认
host
key
描述
剩余的键值对的语义由纠删代码插件定义。
类型
字符串
必填
否.
--force
描述
通过相同名称覆盖现有配置集。
类型
字符串
必填
否.

5.2.2. OSD erasure-code-profile Remove

删除纠删代码 profile:

ceph osd erasure-code-profile rm <name>

如果配置集被池引用,则删除会失败。

5.2.3. OSD erasure-code-profile Get

显示纠删代码 profile:

ceph osd erasure-code-profile get <name>

5.2.4. OSD erasure-code-profile List

列出所有纠删代码配置集的名称:

ceph osd erasure-code-profile ls

5.3. 使用覆盖擦除编码

默认情况下,纠删代码池仅可用于 Ceph 对象网关,后者执行完整的对象写入和附加。自红帽 Ceph 存储 3.x 起,可以逐个池启用纠删代码池的部分写入功能。

将纠删代码池与覆盖结合使用可让 Ceph 块设备和 CephFS 将其数据存储在纠删代码池中:

语法

ceph osd pool set <erasure_coded_pool_name> allow_ec_overwrites true

示例

$ ceph osd pool set ec_pool allow_ec_overwrites true

启用覆盖的纠删代码池只能驻留在使用 BlueStore OSD 的池中。由于 BlueStore 的校验和用于在深度清理过程中检测位或其他损坏。将 FileStore 与纠删代码覆盖结合使用不安全,与 BlueStore 相比会获得较低的性能。

纠删代码池不支持 omap。若要将纠删代码池与 Ceph 块设备和 CephFS 搭配使用,可将数据存储在纠删代码池中,并将元数据存储在复制池中。

对于 Ceph 块设备,在镜像创建过程中使用 --data-pool 选项:

语法

rbd create --size <image_size>M|G|T --data-pool <erasure_coded_pool_name> <replicated_pool_name>/<image_name>

示例

$ rbd create --size 1G --data-pool ec_pool rep_pool/image01

如果将纠删代码池用于 CephFS,则必须通过文件布局设置覆盖。

5.4. 纠删代码插件

Ceph 支持使用插件架构进行纠删代码,这意味着您可以使用不同类型的算法创建纠删代码池。Ceph 支持:

  • Jerasure(默认)
  • Local Repairable
  • ISA(仅限 Intel)

以下小节更详细地描述了这些插件。

5.4.1. Jerasure Erasure Code 插件

jerasure 插件是最通用且最灵活的插件。它也是 Ceph 纠删代码池的默认方法。

jerasure 插件封装 JerasureH 库。有关参数的详情,请查看 jerasure 文档。

要使用 jerasure 插件创建新的纠删代码 profile,请运行以下命令:

ceph osd erasure-code-profile set <name> \
     plugin=jerasure \
     k=<data-chunks> \
     m=<coding-chunks> \
     technique=<reed_sol_van|reed_sol_r6_op|cauchy_orig|cauchy_good|liberation|blaum_roth|liber8tion> \
     [crush-root=<root>] \
     [crush-failure-domain=<bucket-type>] \
     [directory=<directory>] \
     [--force]

其中:

k
描述
每个对象分割成 数据区块,每个部分 存储在不同的 OSD 上。
类型
整数
必填
可以。
示例
4
m
描述
为每个对象计算 编码区块,并将它们存储在不同的 OSD 上。编码区块的数量也是可以在不丢失数据的情况下停止的 OSD 数量。
类型
整数
必填
可以。
示例
2
技术
描述
更灵活的技术是 reed_sol_van ;只要设置 km 就足够了。cauchy_good 技术可以更快,但您需要仔细选择 数据包化。所有 reed_sol_r6_opliberation、 blaum_rothliber8tion 都是等效的 RAID6,它们只能配置 m=2
类型
字符串
必填
否.
有效设置
reed_sol_vanreed_sol_r6_opcauchy_origcauchy_goodliberationblaum_rothliber8tion
默认
reed_sol_van
packetsize
描述
一次将对 字节 大小的数据包进行编码。很难选择正确的数据包大小。jerasure 文档包含有关此主题的广泛信息。
类型
整数
必填
否.
默认
2048
crush-root
描述
用于规则第一步的 CRUSH bucket 的名称。例如,使用默认步骤
类型
字符串
必填
否.
默认
default
crush-failure-domain
描述
确保 bucket 中没有两个块,且具有相同的故障realm。例如,如果故障域是 主机,则同一主机上不会存储两个区块。它用于创建规则步骤,如 step selectleaf host
类型
字符串
必填
否.
默认
host
目录
描述
设置从其中加载纠删代码插件 的目录 名称。
类型
字符串
必填
否.
默认
/usr/lib/ceph/erasure-code
--force
描述
通过相同名称覆盖现有配置集。
类型
字符串
必填
否.

5.4.2. Local Repairable Erasure Code(LRC)插件

利用 jerasure 插件,Ceph 将纠删代码对象存储在多个 OSD 上时,从丢失的 OSD 中恢复需要从所有其他 OSD 读取。例如,如果您使用 k=8 和 m= 4 配置 jerasure,则丢失一个 OSD 需要从 10 个 OSD 中读取才能修复。

lrc 纠删代码插件创建本地奇偶校验区块,以便能够使用更少的 OSD 恢复。例如,如果您使用 k=8、m= 4 和 l=4 配置 l rc,它将为每四个 OSD 创建一个额外的奇偶校验块。当 Ceph 丢失单个 OSD 时,它可以仅使用四个 OSD 而不是十个 OSD 恢复对象数据。

虽然当所有主机都连接到同一交换机时,可能不是有趣的用例,但实际上您可以在使用 lrc 纠删代码插件时看到机架之间的带宽使用量降低。

$ ceph osd erasure-code-profile set LRCprofile \
     plugin=lrc \
     k=4 m=2 l=3 \
     crush-failure-domain=host
$ ceph osd pool create lrcpool 12 12 erasure LRCprofile

在 1.2 版本中,只有Primary OSD 与丢失的块处于相同的机架时,您才能看到带宽降低。

$ ceph osd erasure-code-profile set LRCprofile \
     plugin=lrc \
     k=4 m=2 l=3 \
     crush-locality=rack \
     crush-failure-domain=host
$ ceph osd pool create lrcpool 12 12 erasure LRCprofile

5.4.2.1. 创建 LRC 配置文件

要创建新的 LRC 纠删代码 profile,请运行以下命令:

ceph osd erasure-code-profile set <name> \
     plugin=lrc \
     k=<data-chunks> \
     m=<coding-chunks> \
     l=<locality> \
     [crush-root=<root>] \
     [crush-locality=<bucket-type>] \
     [crush-failure-domain=<bucket-type>] \
     [directory=<directory>] \
     [--force]

其中:

k
描述
每个对象分割成 数据区块,每个部分 存储在不同的 OSD 上。
类型
整数
必填
可以。
示例
4
m
描述
为每个对象计算 编码区块,并将它们存储在不同的 OSD 上。编码区块的数量也是可以在不丢失数据的情况下停止的 OSD 数量。
类型
整数
必填
可以。
示例
2
l
描述
将代码和数据区块分组为大小本地化 的集合。例如,对于 k=4m=2,当创建 locality=3 两个组时。每个集合都可以恢复,无需从另一个集合中读取区块。
类型
整数
必填
可以。
示例
3
crush-root
描述
用于规则第一步的 crush bucket 的名称。例如,使用默认步骤
类型
字符串
必填
否.
默认
default
crush-locality
描述
crush bucket 的类型,其中将存储 l 定义的每一组区块。例如,如果设置为 rack,则每个 l 区块将放置在不同的机架中。它用于创建规则步骤,如 步骤选择机架。如果未设置,则不进行此类分组。
类型
字符串
必填
否.
crush-failure-domain
描述
确保 bucket 中没有两个块,且具有相同的故障realm。例如,如果故障域是 主机,则同一主机上不会存储两个区块。它用于创建规则步骤,如 step selectleaf host
类型
字符串
必填
否.
默认
host
目录
描述
设置从其中加载纠删代码插件 的目录 名称。
类型
字符串
必填
否.
默认
/usr/lib/ceph/erasure-code
--force
描述
通过相同名称覆盖现有配置集。
类型
字符串
必填
否.

5.4.2.2. 创建低级 LRC 配置集

km 的总和必须是 l 参数的倍数。低级别配置参数不会实施这样的限制,它可能会更方便用于特定目的。例如,可以定义两个组,一个有 4 个区块,另一个为 3 个区块。也可以递归定义位置集,如数据中心和机架到数据中心。k/m/l 通过生成低级配置来实现。

lrc 纠删代码插件以递归方式应用纠删代码技术,以便从丢失部分块中恢复仅需要部分可用区块(大部分时间)。

例如,当三个编码步骤描述为:

chunk nr    01234567
step 1      _cDD_cDD
step 2      cDDD____
step 3      ____cDDD

其中 c 是从数据区块 D 计算出的编码区块,则块丢失 7 可使用后四个区块恢复。而且丢失的 chun 2 块可以使用前四个区块来恢复。

MIminal 测试方案严格相当于使用默认的纠删代码 profile。DD 暗示 K=2c 表示 M=1,并且默认使用 jerasure 插件。

$ ceph osd erasure-code-profile set LRCprofile \
     plugin=lrc \
     mapping=DD_ \
     layers='[ [ "DDc", "" ] ]'
$ ceph osd pool create lrcpool 12 12 erasure LRCprofile

lrc 插件对于减少机架间带宽使用量特别有用。虽然当所有主机都连接到同一交换机时,可能不是有趣的用例,但实际上可以观察降低带宽使用量。它等同于 k=4m=2l=3,但块布局不同:

$ ceph osd erasure-code-profile set LRCprofile \
     plugin=lrc \
     mapping=__DD__DD \
     layers='[
               [ "_cDD_cDD", "" ],
               [ "cDDD____", "" ],
               [ "____cDDD", "" ],
             ]'
$ ceph osd pool create lrcpool 12 12 erasure LRCprofile

在 Firefly 中,只有Primary OSD 与丢失的块处于相同的机架时,才会看到降低的带宽:

$ ceph osd erasure-code-profile set LRCprofile \
     plugin=lrc \
     mapping=__DD__DD \
     layers='[
               [ "_cDD_cDD", "" ],
               [ "cDDD____", "" ],
               [ "____cDDD", "" ],
             ]' \
     crush-steps='[
                     [ "choose", "rack", 2 ],
                     [ "chooseleaf", "host", 4 ],
                    ]'
$ ceph osd pool create lrcpool 12 12 erasure LRCprofile

LRC 现在使用 jerasure 作为默认的 EC 后端。可以使用低级配置逐个层指定 EC 后端和算法。tier='[ [ "DDc", "" ] ]' 中的第二个参数实际上是用于此级别的纠删代码 profile。以下示例使用 lrcpool 中要使用的 Cauchy 技术指定 ISA 后端:

$ ceph osd erasure-code-profile set LRCprofile \
     plugin=lrc \
     mapping=DD_ \
     layers='[ [ "DDc", "plugin=isa technique=cauchy" ] ]'
$ ceph osd pool create lrcpool 12 12 erasure LRCprofile

您还可以为每个层使用不同的纠删代码 profile:

$ ceph osd erasure-code-profile set LRCprofile \
     plugin=lrc \
     mapping=__DD__DD \
     layers='[
               [ "_cDD_cDD", "plugin=isa technique=cauchy" ],
               [ "cDDD____", "plugin=isa" ],
               [ "____cDDD", "plugin=jerasure" ],
             ]'
$ ceph osd pool create lrcpool 12 12 erasure LRCprofile

5.4.3. 控制 CRUSH 放置

默认 CRUSH 规则提供位于不同主机上的 OSD。例如:

chunk nr    01234567

step 1      _cDD_cDD
step 2      cDDD____
step 3      ____cDDD

需要正好 8 个 OSD,每个区块一个。如果主机位于两个相邻的机架中,则前四个区块可以放在第一个机架中,然后在第二架中排在最后四块中。恢复单一 OSD 丢失不需要在两个机架之间使用带宽。

例如:

crush-steps='[ [ "choose", "rack", 2 ], [ "chooseleaf", "host", 4 ] ]'

将创建一条规则,以选择两个类型为 rack 的 crush bucket,并且各自选择四个 OSD,分别位于 主机 类型不同的 bucket 中。

也可以手动创建该规则以进行更精细的控制。

5.5. ISA Erasure Code 插件

isa 插件封装 ISA 库。它仅在 Intel 处理器上运行。

要使用 isa 插件创建新纠删代码 profile,请运行以下命令:

ceph osd erasure-code-profile set <name> \
     plugin=isa \
     technique=<reed_sol_van|cauchy> \
     [k=<data-chunks>] \
     [m=<coding-chunks>] \
     [crush-root=<root>] \
     [crush-failure-domain=<bucket-type>] \
     [directory=<directory>] \
     [--force]

其中:

技术
描述
ISA 插件有两种形式。如果设置了 reed_sol_van,则为 Vandermonde,如果设置了 cauchy,则为 Cauchy。
类型
字符串
必填
否.
有效设置
reed_sol_vancauchy
默认
reed_sol_van
k
描述
每个对象分割成 数据区块,每个部分 存储在不同的 OSD 上。
类型
整数
必填
否.
默认
7
m
描述
为每个对象计算 编码区块,并将它们存储在不同的 OSD 上。编码区块的数量也是可以在不丢失数据的情况下停止的 OSD 数量。
类型
整数
必填
否.
默认
3
crush-root
描述
用于规则第一步的 crush bucket 的名称。对于 intance 步骤,默认为
类型
字符串
必填
否.
默认
default
crush-failure-domain
描述
确保 bucket 中没有两个块,且具有相同的故障realm。例如,如果故障域是 主机,则同一主机上不会存储两个区块。它用于创建规则步骤,如 step selectleaf host
类型
字符串
必填
否.
默认
host
目录
描述
设置从其中加载纠删代码插件 的目录 名称。
类型
字符串
必填
否.
默认
/usr/lib/ceph/erasure-code
--force
描述
通过相同名称覆盖现有配置集。
类型
字符串
必填
否.

5.6. pyramid Erasure Code

pyramid 纠删代码基本上是一种基于原始纠删代码算法的改进算法,可改善数据的访问和恢复。对于任何给定(n、k)的给定(n, k),其中 k 是原始数据区块数,n , n 是编码过程后的数据区块总数,它是 Reed-Solomon 之类的任何现有 MDS(主解析)代码。由于 Pyramid 代码基于标准 MDS 代码,因此具有相同的编码/编码方法。pyramid 编码的数据池具有相同的写入开销和类似普通纠删代码池等任意故障的恢复能力。pyramid 代码的唯一优势在于,与普通纠删代码相比,它可显著降低读取开销。

我们来举一个(11, 8)纠删代码池的示例,并在其中应用 pyramid 代码方法。我们将(11, 8)纠删代码池转换为(12、8) Pyramid 代码池。纠删代码池有 8 个 数据区块,11 - 8 = 3 个 冗余块。Pyramid Code 将 8 个数据区块划分为两个相等的大小组,如 P1 = {a1、a2、a3、a4} 和 P2 = {a5、a6、a7、a8}。它使其中两个冗余区块保持不变(say b2 和 b3)。这两个块现在被称为全局冗余区块,因为它们覆盖了所有 8 个数据区块。接下来,为组 P1 计算一个新的冗余块,它表示为组(或本地)冗余块 b1,1。计算方式与原始纠删代码中的计算 b1 相同,但将 P2 中的所有数据区块设置为 0 除外。类似地,为 P2 计算组冗余块 b1,2。组冗余区块仅受到相应组中的数据区块的影响,而不会受到其他组的影响。组冗余区块可以解释为纠删代码中原始冗余区块的投射到每个组,如 b1,1 + b1,2 = b1。因此,在这种情况下,当一个数据区块出现故障时,对于普通纠删代码池,可以使用 4 的读取开销而不是 8 来恢复它。例如,如果 P1 中的 a3 失败,并且 a1 是负责清理的 Primary OSD,它可以使用 a1、a2a4b1,1 来恢复 a3,而不是从 P2 读取。仅当同一组中缺少多个块时,才需要读取所有块。

此 Pyramid 代码的写入开销与原始纠删代码相同。每当更新数据区块时,Pyramid 代码需要更新 3 个冗余区块(b2、b3 加上 b1、b1 或 b1,2),而纠删代码也需要更新 3 个冗余区块(b1、b2 和 b3)。此外,它可以恢复 3 个与普通纠删代码相同的任意纠删代码。如前文所述,唯一好处是阅读开销更少,其代价是使用一个额外的冗余区块。因此,Pyramid 代码交易存储空间以提高访问效率。

下图显示了构建的 pyramid 代码:

pyramid Erasure Code

法律通告

Copyright © 2023 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.