存储策略指南
为 Red Hat Ceph Storage 集群创建存储策略
摘要
第 1 章 概述
从 Ceph 客户端的角度来看,与 Ceph 存储集群交互非常简单:
- 连接到集群
- 创建池 I/O 上下文
这种简单接口是 Ceph 客户端如何选择您定义的存储策略之一。存储策略对 Ceph 客户端不可见,但存储容量和性能。
下图显示了从客户端开始到 Red Hat Ceph Storage 集群的逻辑数据流。
1.1. 存储策略是什么?
存储策略是一种存储服务特定用例的数据的方法。例如,如果您需要为 OpenStack 等云平台存储卷和镜像,您可以选择使用基于 SSD 的日志以合理性能的 SAS 驱动器存储数据。相反,如果您需要为与 S3 或 Swift 兼容的网关存储对象数据,您可以选择使用更经济的设备,例如 SATA 驱动器等。Ceph 可以在同一 Ceph 集群中同时容纳这两个场景,但您需要为云平台(如 OpenStack 中的 Glance 和 Cinder)提供 SAS/SSD 存储策略,以及为您的对象存储提供 SATA 存储的方法。
存储策略包括存储介质(硬驱动器、SSD 和 rest), CRUSH 映射为存储介质设置性能和故障域、放置组数量和池接口。Ceph 支持多种存储策略。用例、成本/受益性和数据持久性是驱动存储策略的主要考虑因素。
- 使用案例: Ceph 提供大量存储容量,并且支持多种用例。例如,Ceph 块设备客户端是 OpenStack 等云平台的领先存储后端,为具有高性能功能(如 copy-on-write 克隆)的卷和镜像提供无限存储。同样,Ceph 可以为 OpenShift 环境提供基于容器的存储。相反,Ceph 对象网关客户端是云平台的领先存储后端,为音频、位映射、视频和其他数据等对象提供 RESTful S3 兼容和 Swift 兼容对象存储。
- 成本/好处性能: 更迅速。越大越好。越耐用越好。但是,每种出色的质量、相应的成本与收益权衡都有价格。从性能角度考虑以下用例:SSD 可以为相对较小的数据和日志量提供非常快速的存储。存储数据库或对象索引可能会受益于非常快的 SSD 池,但对其他数据而言过于昂贵。带有 SSD 日志的 SAS 驱动器以经济的价格为卷和图像提供快速性能。没有 SSD 日志地 SATA 驱动器可提供低成本存储,同时整体性能也较低。在创建 OSD 的 CRUSH 层次结构时,您需要考虑用例和可接受的成本/性能权衡。
-
持久性:在大规模集群中,硬件故障是期望的,而不是例外。但是,数据丢失和服务中断仍然不可接受。因此,数据的持久性非常重要。Ceph 通过对象的多个深度副本解决数据持久性问题,或使用纠删代码和多个编码区块来解决数据持久性。多个副本或多个编码区块会带来额外的成本与好处权衡:存储更少的副本或编码区块会更便宜,但可能会导致在降级状态中为写入请求提供服务。通常,一个具有两个额外副本的对象(即
size = 3
)或两个编码区块可能允许集群在集群恢复期间服务降级状态的服务写入。CRUSH 算法通过确保 Ceph 将额外的副本或编码区块存储在集群中的不同位置来协助这个过程。这样可确保,在单个存储设备或节点出现故障时,不会丢失为了防止数据丢失所需的所有副本或编码区块。
您可以规划一个存储策略来实现用例、性能成本/收益的平衡,以及数据的持久性,然后将它作为存储池呈现给 Ceph 客户端。
Ceph 的对象副本或编码区块使 RAID 过时。不要使用 RAID,因为 Ceph 已经处理数据持久性,降级的 RAID 对性能有负面影响,并且使用 RAID 恢复数据比使用深度副本或纠删代码区块要慢得多。
1.2. 配置存储策略
配置存储策略代表将 Ceph OSD 分配给 CRUSH 层次结构,定义池的放置组数量,以及创建池。一般步骤是:
- 定义存储策略: 存储策略需要您分析您的用例、性能的成本/收益以及数据持久性。然后,您要创建适合该用例的 OSD。例如,您可以为高性能池创建由 SSD 支持的 OSD;使用 SAS 驱动器/SSD 日志支持的 OSD 用于高性能块设备卷和镜像;或者使用由 SATA 支持的 OSD 用于低成本存储。理想情况下,用例的每个 OSD 应该具有相同的硬件配置,以便您具有一致的性能配置集。
-
定义 CRUSH 层次结构: Ceph 规则在 CRUSH 层次结构中选择节点(通常是
root
),并确定用于存储放置组及其包含对象的相应 OSD。您必须为存储策略创建 CRUSH 层次结构和 CRUSH 规则。CRUSH 层次结构由 CRUSH 规则设置直接分配给池。 - 计算放置组: Ceph 将池分片到放置组中。您不必为池手动设置放置组数量。当您将多个池分配到同一 CRUSH 规则时,PG 自动缩放器为您的池设置适当的放置组数量。
-
创建池: 最后,您需要创建一个池,并确定它是否使用复制或擦除存储。您必须为池设置放置组数量、池的规则以及持久性,如 size 或
K+M
编码区块。
请记住,池是 Ceph 客户端到存储集群的接口,但存储策略对 Ceph 客户端完全透明,但容量和性能除外。
第 2 章 CRUSH 管理员概述
可扩展哈希下的受控复制(CRUSH)算法决定如何通过计算数据存储位置存储和检索数据。
任何足够高级的技术都与数字相比是不可区别的。 | ||
-- Arthur C. Clarke |
2.1. CRUSH 简介
存储集群的 CRUSH 映射描述了 CRUSH 层次结构中的设备位置,以及确定 Ceph 如何存储数据的层次结构的规则。
CRUSH map 至少包含一个节点层次结构并保留。Ceph 中的层次结构的节点称为"buckets",是其类型定义的任何存储位置聚合。例如,行、机架、机箱、主机和设备。层次结构的每个叶基本上由存储设备列表中的一个存储设备组成。leaf 始终包含在一个节点或 "bucket"。CRUSH map 也具有确定 CRUSH 存储和检索数据的规则列表。
将 OSD 添加到集群时,存储设备会添加到 CRUSH map。
CRUSH 算法根据每个设备的权重值将数据对象分布到存储设备中,从而达到统一性分布。CRUSH 根据管理员定义的层次结构集群映射,分发对象及其副本或纠删代码区块。CRUSH 映射代表可用的存储设备以及包含该规则的逻辑存储桶,并扩展使用该规则的每个池。
要将放置组映射到 OSD 跨故障域或性能域,CRUSH 映射定义了 bucket 类型的层次结构列表;即,在生成的 CRUSH 映射中的 类型
下。创建存储桶层次结构的目的是,通过其故障域或性能域来隔离叶节点。故障域包括主机、机箱、机架、电源分配单元、pod、行、房间和数据中心。安全域包括特定配置的故障域和 OSD。例如: SSD、SAS 驱动器以及 SSD 日志、SATA 驱动器等。设备具有 类
的概念,如 hdd
、ssd
和 nvme
,以更快速地构建具有类别设备的 CRUSH 层次结构。
除了代表 OSD 的叶节点外,层次结构的其余部分是任意的,如果默认类型不适合您的要求,您可以根据您自己的需求进行定义。我们推荐将您的 CRUSH 映射 bucket 类型调整为组织的硬件命名约定,并使用反映物理硬件名称的实例名称。通过良好的命名规则,您可以更轻松地管理集群,并在 OSD 或其他硬件故障时方便排除问题,并方便管理员远程或物理访问主机或其他硬件。
在以下示例中,bucket 层次结构有四个页存储桶(osd 1-4
)、两个节点存储桶(主机 1-2
)和一个机架节点(rack 1
)。
由于叶节点反映 CRUSH 映射开头的 devices
列表下声明的存储设备,因此不需要将它们声明为 bucket 实例。层次结构中第二个最低存储桶类型通常会聚合设备;即,通常是包含存储介质的计算机,并使用管理员喜欢描述它的任何术语,如 "node"、"computer"、"host"、"host"、"machine"等。在高密度的环境中,每个卡和每个机箱查看多个主机/节点越来越常见。确保考虑卡和机箱失败的情况,例如,如果在一个节点失败时需要拔出相关的卡或机箱时,可能会导致大量主机/节点及其 OSD 无法使用。
在声明存储桶实例时,指定其类型作为字符串的唯一名称,请为它分配一个可选的唯一 ID,以负整数表示,指定相对于其项目的总容量或能力的权重,指定存储桶算法,如 straw2
,以及哈希算法,它通常为 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. CRUSH 故障域
有多个对象副本或 M
纠删代码区块有助于防止数据丢失,但无法解决高可用性。通过反映 Ceph Storage 集群的底层物理组织,CRUSH 可以建模,从而造成关联设备故障的潜在来源。通过将集群的拓扑编码到集群映射中,CRUSH 放置策略可在不同的故障域间分离对象副本或纠删代码区块,同时仍维护所需的伪随机分布。例如,为了解决并发故障的可能性,可能需要确保数据副本或纠删代码区块位于使用不同的 shelves、机架、电源、控制器或物理位置的设备上。这有助于防止数据丢失并允许集群以降级状态运行。
2.1.3. CRUSH 性能域
Ceph 可以支持多种层次结构,将一种类型的硬件性能配置集与其他类型的硬件性能配置集分隔开。例如,CRUSH 可以为硬盘和 SSD 的另一个层次结构创建一个层次结构。使用性能域 (考虑到底层硬件的性能特性的分级结构)变得非常流行 ,因此通常会需要满足不同的性能要求。在操作上,只有 CRUSH 映射具有多个 根
类型 bucket。用例示例包括:
- 对象存储: 用作 S3 和 Swift 接口的对象存储后端的 Ceph 主机可能会使用廉价的存储介质,如 SATA 驱动器,它们可能不适用于虚拟机,但对于对象存储可以降低增加额外 GB 存储空间的成本。这样,可以将廉价的存储主机与需要高性能的系统(例如用于在云平台中存储卷和镜像的系统)分离。HTTP 往往是对象存储系统中的瓶颈。
- 冷存储 :为冷存储设计的系统 - 经常访问数据,或使用放宽的性能要求实现数据检索 - 充分利用成本较低的存储介质和纠删代码。但是,擦除编码可能需要一些额外的 RAM 和 CPU,因此与用于对象存储或虚拟机的主机的 RAM 和 CPU 要求有所不同。
-
SSD 支持的池: SSD 非常昂贵,但它们比硬盘提供显著优势。SSD 没有查看时间,它们提供较高的吞吐量。除了使用 SSD 进行日志外,集群还可以支持由 SSD 支持的池。常见用例包括高性能 SSD 池。例如,可以将 Ceph 对象网关的
.rgw.buckets.index
池映射到 SSD,而不是 SATA 驱动器。
CRUSH map 支持 设备类
的概念。Ceph 可以发现存储设备的各个方面,并自动分配类,如 hdd
、ssd
或 nvme
。但是,CRUSH 不仅限于这些默认值。例如,CRUSH 层次结构还可用于分隔不同类型的工作负载。例如,SSD 可以用于日志或直写日志,bucket 索引或原始对象存储。CRUSH 可以支持不同的设备类,如 ssd-bucket-index
或 ssd-object-storage
,因此 Ceph 不会对不同的工作负载使用相同的存储介质 - 提高了性能的可预测性和一致性。
在后台后,Ceph 为各个设备类生成 CRUSH root。这些根应仅通过设置或更改 OSD 上的设备类来修改。您可以使用以下命令查看生成的 roots:
示例
[ceph: root@host01 /]# ceph osd crush tree --show-shadow ID CLASS WEIGHT TYPE NAME -24 ssd 4.54849 root default~ssd -19 ssd 0.90970 host ceph01~ssd 8 ssd 0.90970 osd.8 -20 ssd 0.90970 host ceph02~ssd 7 ssd 0.90970 osd.7 -21 ssd 0.90970 host ceph03~ssd 3 ssd 0.90970 osd.3 -22 ssd 0.90970 host ceph04~ssd 5 ssd 0.90970 osd.5 -23 ssd 0.90970 host ceph05~ssd 6 ssd 0.90970 osd.6 -2 hdd 50.94173 root default~hdd -4 hdd 7.27739 host ceph01~hdd 10 hdd 7.27739 osd.10 -12 hdd 14.55478 host ceph02~hdd 0 hdd 7.27739 osd.0 12 hdd 7.27739 osd.12 -6 hdd 14.55478 host ceph03~hdd 4 hdd 7.27739 osd.4 11 hdd 7.27739 osd.11 -10 hdd 7.27739 host ceph04~hdd 1 hdd 7.27739 osd.1 -8 hdd 7.27739 host ceph05~hdd 2 hdd 7.27739 osd.2 -1 55.49022 root default -3 8.18709 host ceph01 10 hdd 7.27739 osd.10 8 ssd 0.90970 osd.8 -11 15.46448 host ceph02 0 hdd 7.27739 osd.0 12 hdd 7.27739 osd.12 7 ssd 0.90970 osd.7 -5 15.46448 host ceph03 4 hdd 7.27739 osd.4 11 hdd 7.27739 osd.11 3 ssd 0.90970 osd.3 -9 8.18709 host ceph04 1 hdd 7.27739 osd.1 5 ssd 0.90970 osd.5 -7 8.18709 host ceph05 2 hdd 7.27739 osd.2 6 ssd 0.90970 osd.6
2.2. CRUSH 层次结构
CRUSH map 是一个圆环图,因此它可以容纳多个层次结构,如性能域。创建和修改 CRUSH 层次结构的最简单方式是使用 Ceph CLI,但您也可以编译 CRUSH map、对其进行编辑、重新编译并激活它。
使用 Ceph CLI 声明 bucket 实例时,您必须指定其类型并为其提供唯一的字符串名称。Ceph 自动分配 bucket ID,将算法设置为 straw2
,将哈希设置为 0,
反映 rjenkins1
,并设置权重。当修改 decompiled CRUSH map 时,将 bucket 分配为负整数的唯一 ID(可选),指定相对于其项目的总容量/大写性的权重,请指定存储桶算法(通常是 straw2
),以及 hash(通常为 0
,代表哈希算法 rjenkins1
)。
bucket 可以有一个或多个项目。这些项目可由节点存储桶(如 racks、rows、hosts)或 leaves(如 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 | straw2 ] hash [the hash type: 0 by default] item [item-name] weight [weight] }
例如,使用上图,我们将定义两个主机存储桶和一个机架 bucket。OSD 在主机存储桶中声明为项目:
host node1 { id -1 alg straw2 hash 0 item osd.0 weight 1.00 item osd.1 weight 1.00 } host node2 { id -2 alg straw2 hash 0 item osd.2 weight 1.00 item osd.3 weight 1.00 } rack rack1 { id -3 alg straw2 hash 0 item node1 weight 2.00 item node2 weight 2.00 }
在示例中,请注意机架 bucket 不包含任何 OSD。它包含较低级别的主机存储桶,并在项目条目中包含其权重的总和。
2.2.1. CRUSH 位置
CRUSH 位置是 OSD 在 CRUSH map 的层次结构中的位置。在命令行界面中表达 CRUSH 位置时,CRUSH 位置指定符采用描述 OSD 位置的名称/值对列表。例如,如果 OSD 位于特定的行、机架、机箱和主机中,并且是 默认
CRUSH 树的一部分,其 CRUSH 位置可能描述如下:
root=default row=a rack=a2 chassis=a2a host=a2a1
备注:
- 键的顺序无关紧要。
-
密钥名称(属于
=
)必须是有效的 CRUSH类型
。默认情况下,包括root
,datacenter
,room
,row
,pod
,pdu
,rack
,chassis
和host
.您可以编辑 CRUSH 映射,以更改类型以满足您的需求。 -
您不需要指定所有存储桶/密钥。例如,Ceph 默认自动将
ceph-osd
守护进程的位置设置为root=default host={HOSTNAME}
(基于主机名 -s
的输出)。
2.2.2. 添加存储桶
要将存储桶实例添加到 CRUSH 层次结构中,请指定存储桶名称及其类型。bucket 名称在 CRUSH map 中必须是唯一的。
ceph osd crush add-bucket {name} {type}
如果您计划使用多个层次结构,例如,对于不同的硬件性能配置集,请考虑基于硬件类型或用例命名存储桶。
例如,您可以为固态驱动器创建一个层次结构(ssd
)、带有 SSD 日志的 SAS 磁盘的层次结构(hdd-journal
),以及 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
不支持在存储桶名称中使用冒号(:)。
为层次结构所需的每个存储桶类型添加一个实例。以下示例演示了为 SSD 主机机架和对象存储的主机机架添加行的 bucket。
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
完成这些步骤后,查看您的树。
ceph osd tree
请注意,层次结构仍为 flat。在将存储桶添加到 CRUSH map 后,您必须将存储桶移到分级位置。
2.2.3. 移动存储桶
在创建初始集群时,Ceph 具有默认的 CRUSH map,其根存储桶为 default
,您的初始 OSD 主机会显示在 默认
存储桶下。将存储桶实例添加到 CRUSH map 时,它将显示在 CRUSH 层次结构中,但它不一定出现在特定的 bucket 中。
要将存储桶实例移到 CRUSH 层次结构中的特定位置,请指定存储桶名称及其类型。例如:
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. 删除存储桶
要从 CRUSH 层次结构中删除存储桶实例,请指定存储桶名称。例如:
ceph osd crush remove {bucket-name}
或者:
ceph osd crush rm {bucket-name}
bucket 必须为空,才能将其删除。
如果您要删除更高级别的存储桶(例如,一个 root 用户(如 default
)),请检查池是否使用了选择该 bucket 的 CRUSH 规则。如果是这样,您需要修改 CRUSH 规则;否则,对等失败。
2.2.5. CRUSH Bucket 算法
在使用 Ceph CLI 创建存储桶时,Ceph 默认将算法设置为 straw2
。Ceph 支持四种 bucket 算法,各自代表性能和重新组织效率之间的权衡。如果您不确定要使用的存储桶类型,我们建议使用 straw2
存储桶。bucket 算法有:
-
统一: 统一 bucket 聚合设备,其权重 完全相同。例如,当公司委托或停用硬件时,它们通常对具有相同物理配置(例如批量购买)的多台计算机执行此操作。当存储设备完全相同的权重时,您可以使用
统一
存储桶类型,这允许 CRUSH 将副本映射到统一的 bucket 中。使用非统一权重时,您应该使用另一个存储桶算法。 - 列表 :将存储桶作为链接列表来聚合。基于 RUSH (Replication Under Scalable Hashing) P 算法,对于一个扩展集群,列表是一种自然而直观的选择:一个对象会被重新定位到具有一些适当的概率的新设备上,或者仍保留在旧的设备上。当项目添加到存储桶时,结果是最佳的数据迁移。但是,从列表的中间或尾部删除项目可能导致大量不必要的移动,因此列表存储桶最适用于永不或很少被缩小的情况。
- Tree :树形 bucket 使用二进制搜索树。当存储桶包含大量项目时,它们比列表存储桶更高效。基于 RUSH (Replication Under Scalable Hashing) R 算法,树形存储桶可将放置时间缩短为零(log n),使它们适合管理大型设备或嵌套的存储桶。
-
Straw2(默认):类别和树存储桶以某种方式划分和排序策略,例如,在列表开始时提供某些项目优先级;例如,列表开头或组合需要考虑整个项目的整个子树。这提高了副本放置过程的性能,但也可以因为项目的添加、删除或重新加权更改存储桶内容时引入不够优化的重新组织行为。
straw2
bucket 类型允许所有项目通过与 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 所在的层次结构或树的根存储桶的名称。
- 类型
- 键-值对。
- 必填
- 是
- 示例
-
root=default
,root=replicated_rule
, 等
- bucket-type
- 描述
- 一个或多个 name-value 对,其中 name 是存储桶类型,值是存储桶的名称。您可以在 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 tree
。
要返回附加详情,请执行以下操作:
# 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 } ] } ] } ]
2.3.2. 将 OSD 添加到 CRUSH
在可以启动一个 OSD(为 up
和 in
)且 Ceph 为 OSD 分配放置组前,将一个 Ceph OSD 添加到 CRUSH 层次结构中是最终的步骤。
您必须将 Ceph OSD 添加到 CRUSH 层次结构前,您必须准备 Ceph OSD。部署实用程序(如 Ceph 编排器)可以为您执行此步骤。例如,在单个节点上创建 Ceph OSD:
语法
ceph orch daemon add osd HOST:_DEVICE_,[DEVICE]
CRUSH 层次结构不同,因此 ceph osd crush add
命令允许您在您想要的 CRUSH 层次结构中添加 OSD。您指定的位置应反映其实际位置。如果您至少指定了一个存储桶,命令会将 OSD 放置到您指定的最特定的存储桶中,并将该 存储桶移到您指定的任何其他存储桶下。
将 OSD 添加到 CRUSH 层次结构:
语法
ceph osd crush add ID_OR_NAME WEIGHT [BUCKET_TYPE=BUCKET_NAME ...]
如果您只指定 root 存储桶,命令会将 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
如果存储集群拓扑发生变化,您可以移动 CRUSH 层次结构中的 OSD 来反映其实际位置。
在 CRUSH 层次结构中移动 OSD 意味着 Ceph 将重新计算哪些放置组分配给 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 获取放置组和数据相应地重新平衡。如需了解更多详细信息,请参阅添加/删除 OSD。
要从正在运行的集群的 CRUSH 映射中删除 OSD,请执行以下操作:
语法
ceph osd crush remove NAME
2.4. 设备类
Ceph 的 CRUSH map 在控制数据放置时提供了额外的灵活性。这是 Ceph 的最大优势之一。早期 Ceph 部署使用硬盘几乎独占。现在,Ceph 集群经常会使用多种类型的存储设备构建: HDD、SSD、NVMe 甚至各种更旧的类型。例如,在 Ceph 对象网关部署中通常会有存储策略,以供客户端在较慢的 HDD 中保存数据和其他存储策略,用于将数据存储到快 SSD 上。Ceph 对象网关部署可能甚至具有由快速 SSD 支持用于 bucket 索引的池。此外,OSD 节点通常具有专门用于日志或 write-ahead 日志的 SSD,它们没有出现在 CRUSH map 中。之前,这些复杂的硬件方案需要手动编辑 CRUSH map,这可能会非常耗时且非常繁琐。对于不同的存储设备类别,并不需要不同的 CRUSH 层次结构。
CRUSH 规则在 CRUSH 层次结构方面工作。但是,如果不同类别存储设备驻留在同一主机上,该过程会变得更为复杂 - 询问用户为每个类设备创建多个 CRUSH 层次结构,然后禁用 osd crush update on start
选项,以自动执行大部分 CRUSH 层次结构管理。设备类通过告诉 CRUSH 规则要使用的设备类,大大简化了 CRUSH 管理任务,从而消除了这种明显性。
ceph osd tree
命令具有反映设备类的列。
2.4.1. 设置设备类
要为 OSD 设置设备类,请执行以下操作:
语法
ceph osd crush set-device-class CLASS OSD_ID [OSD_ID..]
示例
[ceph: root@host01 /]# ceph osd crush set-device-class hdd osd.0 osd.1 [ceph: root@host01 /]# ceph osd crush set-device-class ssd osd.2 osd.3 [ceph: root@host01 /]# ceph osd crush set-device-class bucket-index osd.4
Ceph 可能会自动为设备分配类。但是,类名称只是任意字符串。不需要遵循 hdd
、ssd
或 nvme
。在示例中,名为 bucket-index
的设备类可能表示 Ceph 对象网关池使用独占 bucket 索引工作负载的 SSD 设备。要更改已经设置的设备类,请首先使用 ceph osd crush rm-device-class
。
2.4.2. 删除设备类
要为 OSD 删除设备类,请执行以下操作:
语法
ceph osd crush rm-device-class CLASS OSD_ID [OSD_ID..]
示例
[ceph: root@host01 /]# ceph osd crush rm-device-class hdd osd.0 osd.1 [ceph: root@host01 /]# ceph osd crush rm-device-class ssd osd.2 osd.3 [ceph: root@host01 /]# ceph osd crush rm-device-class bucket-index osd.4
2.4.3. 重命名设备类
要为使用该类的所有 OSD 重命名设备类,请执行以下操作:
语法
ceph osd crush class rename OLD_NAME NEW_NAME
示例
[ceph: root@host01 /]# ceph osd crush class rename hdd sas15k
2.4.4. 列出设备类
要列出 CRUSH 映射中的设备类,请执行以下操作:
语法
ceph osd crush class ls
输出将类似如下:
示例
[ "hdd", "ssd", "bucket-index" ]
2.4.5. 列出设备类的 OSD
要列出属于特定类的所有 OSD,请执行以下操作:
语法
ceph osd crush class ls-osd CLASS
示例
[ceph: root@host01 /]# ceph osd crush class ls-osd hdd
输出是一个 OSD 号列表。例如:
0 1 2 3 4 5 6
2.4.6. 按类列出 CRUSH 规则
要列出引用同一类的所有 CRUSH 规则,请执行以下操作:
语法
ceph osd crush rule ls-by-class CLASS
示例
[ceph: root@host01 /]# ceph osd crush rule ls-by-class hdd
2.5. CRUSH 权重
CRUSH 算法为每个 OSD 设备分配一个 太字节(按惯例)的权重值,旨在为写入请求分配新数据对象到 PG 和 PG 到 OSD 的写入请求。因此,作为最佳实践,我们建议使用相同类型和大小的设备创建 CRUSH 层次结构,并分配相同的权重。我们还建议使用具有相同 I/O 和吞吐量的设备,这样您也会在 CRUSH 层次结构中具有统一的性能特征,即使性能特性不会影响数据分发。
由于使用统一硬件并不现实,因此您可以纳入不同大小的 OSD 设备并使用相对权重,以便 Ceph 将更多数据分发到较大的设备,并将数据更小到较小的设备。
2.5.1. 设置 OSD 的 CRUSH 权重
要在 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
可能非常耗时。您可以通过执行以下内容来设置(或重置)存储桶下的所有 Ceph OSD 权重(row、rack 和 node 等):
语法
osd crush reweight-subtree NAME
其中,
name
是 CRUSH bucket 的名称。
2.5.3. 设置 OSD 的 in
权重
对于 ceph osd in
和 ceph osd out
,一个 OSD 为 in
集群,或 out
集群。这是 monitor 如何记录 OSD 的状态。但是,尽管一个 OSD 为 in
集群,它可能遇到了一个故障情况,在出现这种情况下,您不应该完全依赖它,直到相关的问题被解决(例如,替换存储驱动器、更改控制器等)。
您可以通过执行以下操作为为一个特定的 OSD 增加或减少 in
权重(无需改变它在 Terabytes 中的权重):
语法
ceph osd reweight ID WEIGHT
其中:
-
ID
是 OSD 号。 -
weight
是 0.0-1.0 的一个范围,其中0
代表不是in
集群(也就是说,没有分配给它的 PG),1.0 代表为in
集群(即OSD 接收与其他 OSD 相同的 PG 数量)。
2.5.4. 根据使用率设置 OSD 权重
CRUSH 的设计旨在对将新数据对象 PG 和 PG 分配给 OSD 的写入请求大约一种统一的概率分布。但是,集群可能会变为不平衡。这样做的原因有很多。例如:
- 多个池: 您可以将多个池分配给 CRUSH 层次结构,但池可能具有不同的放置组数量、大小(用于存储的副本数)和对象大小特征。
-
自定义客户端: Ceph 客户端(如块设备、对象网关和文件系统)共享来自其客户端的数据,并将数据作为对象条带化,就像统一较小的 RADOS 对象一样。因此,除了忘记的场景外,CRUSH 通常达到其目标。但是,还有另一个情况,集群可能会变为 imbalanced:即,使用
librados
存储数据而无需规范化对象大小。这种情境可能会导致集群不平衡(例如,存储 100 1 MB 对象和 10 4 MB 对象),使得一些 OSD 的数据比其他 OSD 更多的数据。 - Probability: 统一分布将导致一些 OSD 带有更多 PG,一些 OSD 有更少的 PG。对于有大量 OSD 的集群,统计外部会进一步推出。
您可以通过执行以下命令来重新加权 OSD:
语法
ceph osd reweight-by-utilization [THRESHOLD_] [WEIGHT_CHANGE_AMOUNT] [NUMBER_OF_OSDS] [--no-increasing]
示例
[ceph: root@host01 /]# 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 数量限制为重新加权可防止大量重新平衡。可选。 -
no-increasing
默认为 off。在使用reweight-by-utilization
或test-reweight-utilization
命令时允许增加 osd 权重。如果此选项与这些命令搭配使用,它会防止 OSD 权重增加,即使 OSD 未被充分利用。可选。
建议使用 重新加权使用
,对于大型集群来说,最好有可能性。利用率可能会随时间变化,随着集群大小或硬件的变化,可能需要更新权重来反映更改的利用率。如果您选择通过使用率重新加权,则可能需要在利用率、硬件或集群大小发生变化时重新运行该命令。
执行这个命令或其他权重命令会覆盖由这个命令分配的权重(例如,osd reweight-by-utilization
, osd crush weight
, osd weight
, in
或 out
)。
2.5.5. 根据 PG 分发设置 OSD 的 Weight
在具有较少 OSD 的 CRUSH 层次结构中,一些 OSD 可能会获得比其他 OSD 更多的 PG,从而导致负载更高。您可以通过执行以下操作来重新加权 OSD 来应对这种情况:
语法
osd reweight-by-pg POOL_NAME
其中:
-
POOLNAME
是池的名称。Ceph 将检查池如何为 OSD 分配 PG 以及根据这个池的 PG 分发来重新加权 OSD。请注意,可以将多个池分配到相同的 CRUSH 层次结构。根据一个池的分发,重新加权 OSD 可能会对分配给同一 CRUSH 层次结构的其他池具有意外的影响(如果它们没有相同的大小(副本数)和 PG。
2.5.6. 重新计算 CRUSH Tree 的权重
CRUSH 树 bucket 应当是其叶权重的总和。如果手动编辑 CRUSH map 权重,您应该执行下列命令,以确保 CRUSH bucket 树准确反映 bucket 下叶 OSD 的总和。
语法
osd crush reweight-all
2.6. 主要关联性
当 Ceph 客户端读取或写入数据时,它始终联系操作集合中的 Primary OSD。对于 set [2, 3, 4]
, osd.2
是主的。有时,OSD 并不适合于作为与其他 OSD 之间的主要操作(例如,它具有慢的磁盘或较慢的控制器)。要在最大化硬件利用率时防止性能瓶颈(特别是读操作),您可以设置 Ceph OSD 的主关联性,以便 CRUSH 不太可能将 OSD 用作活跃集合中的主要状态。
语法
ceph osd primary-affinity OSD_ID WEIGHT
主关联默认为 1
(这代表,一个 OSD 可以作为一个 primary)。您可以在 0-1
之间设置 OSD 主要范围,其中 0
表示 OSD 可能没有用作主,1
则表示 OSD 可能被用作主。当 weight 为 < 1
时,CRUSH 会选择要充当主的 Ceph OSD 守护进程。
2.7. CRUSH 规则
CRUSH 规则定义 Ceph 客户端如何在其中选择 bucket 和 Primary OSD 以存储对象,以及 Primary OSD 如何选择存储桶和次要 OSD 来存储副本或编码区块。例如,您可以创建一个规则,为两个对象副本选择由 SSD 支持的一对目标 OSD,以及另一规则为三个副本选择由 SAS 驱动器支持的三个目标 OSD。
规则采用以下格式:
rule <rulename> { id <unique number> type [replicated | erasure] 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 }
- id
- 描述
- 用于标识规则的唯一整数。
- 用途
- 规则掩码的组件。
- 类型
- 整数
- 必填
- 是
- 默认
-
0
- type
- 描述
- 描述存储驱动器复制或退出代码的规则。
- 用途
- 规则掩码的组件。
- 类型
- 字符串
- 必需
- 是
- 默认
-
复制
- 有效值
-
目前仅能为
replicated
- min_size
- 描述
- 如果池制作的副本数少于这个数字,CRUSH 不会选择此规则。
- 类型
- 整数
- 用途
- 规则掩码的组件。
- 必填
- 是
- 默认
-
1
- max_size
- 描述
- 如果池制作的副本数多于这个数字,CRUSH 不会选择此规则。
- 类型
- 整数
- 用途
- 规则掩码的组件。
- 必填
- 是
- 默认
-
10
- step take <bucket-name> [class <class-name>]
- 描述
- 使用存储桶名称,并开始迭代树。
- 用途
- 规则的一个组件。
- 必填
- 是
- 示例
-
step take data
step take data class ssd
- step select firstn <num> type <bucket-type>
- 描述
选择给定类型的 bucket 数量。数字通常是池中副本数量(即池大小)。
-
如果
<num> == 0
,选择pool-num-replicas
bucket(所有可用的)。 -
如果 <
num> > 0 && < pool-num-replicas
,请选择这个数量的存储桶。 -
如果
<num> < 0
,这表示pool-num-replicas - {num}
。
-
如果
- 用途
- 规则的一个组件。
- 前提条件
-
根据
step take
或step choose
。 - 示例
-
步骤选择第 1 类型行
- step chooseleaf firstn <num> type <bucket-type>
- 描述
选择一组
{bucket-type}
,从 bucket 集合中的每个 bucket 的子树中选择叶节点。集合中的 bucket 数量通常是池中副本数量(即池大小)。-
如果
<num> == 0
,选择pool-num-replicas
bucket(所有可用的)。 -
如果 <
num> > 0 && < pool-num-replicas
,请选择这个数量的存储桶。 -
如果 &
lt;num> < 0
,这表示pool-num-replicas - <num>
。
-
如果
- 用途
- 规则的一个组件。使用方法不再需要选择使用两个步骤的设备。
- 前提条件
-
跟随
step take
或step select
。 - 示例
-
step chooseleaf firstn 0 type row
- step emit
- 描述
- 输出当前值并清除堆栈。通常在规则末尾使用,但也可能用于从同一规则中的不同树提取。
- 用途
- 规则的一个组件。
- 前提条件
-
跟随
step choose
。 - 示例
-
step emit
- firstn 和 indep
- 描述
-
控制 CRUSH 在 CRUSH map 中标记 OSD 时使用的替代策略。如果此规则要与复制池一起使用,则应
首先使用这个规则
,如果用于纠删代码池,则它应该独立使用
。 - 示例
-
您有 PG 存储在 OSD 1、2、3、4、5 上,其中 3 个出现故障。在第一种场景中,使用
firstn
模式,CRUSH 会将其计算调整为选择 1 和 2,然后选择 3,但发现它已关闭,因此它重试并选择 4 和 5,然后进入 以选择新的 OSD 6。最后的 CRUSH 映射更改为从 1, 2, 3, 4, 5 到 1, 2, 4, 5, 6。在第二个情景中,在一个纠删代码池中使用indep
模式,CRUSH 会尝试选择失败的 OSD 3,再次尝试并选择 6 用于从 1, 2, 3, 4, 5 到 1, 2, 6, 4, 5 的最终转换。
给定 CRUSH 规则可以分配给多个池,但单个池无法具有多个 CRUSH 规则。
2.7.1. 列出 CRUSH 规则
要从命令行列出 CRUSH 规则,请执行以下操作:
语法
ceph osd crush rule list ceph osd crush rule ls
2.7.2. 转储 CRUSH 规则
要转储特定 CRUSH 规则的内容,请执行以下操作:
语法
ceph osd crush rule dump NAME
2.7.3. 添加 CRUSH 规则
要添加 CRUSH 规则,您必须指定规则名称、要使用的层次结构的根节点、您要复制到的存储桶类型(例如:"rack'、'row' 等等),以及选择存储桶的模式。
语法
ceph osd crush rule create-simple RUENAME ROOT BUCKET_NAME FIRSTN_OR_INDEP
Ceph 创建一个规则,它带有 chooseleaf
,以及您指定的类型的一个存储桶。
示例
[ceph: root@host01 /]# ceph osd crush rule create-simple deleteme default host firstn
创建以下规则:
{ "id": 1, "rule_name": "deleteme", "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"}]}
2.7.4. 为复制池创建 CRUSH 规则
要为复制池创建 CRUSH 规则,请执行以下操作:
语法
ceph osd crush rule create-replicated NAME ROOT FAILURE_DOMAIN CLASS
其中:
-
<name
> : 规则的名称。 -
<root
> : CRUSH 层次结构的根目录。 -
<failure-domain>
: 故障域。例如:host
或rack
。 -
<class
> : 存储设备类。例如:hdd
或ssd
。
示例
[ceph: root@host01 /]# ceph osd crush rule create-replicated fast default host ssd
2.7.5. 为纠删代码池创建 CRUSH 规则
要添加与纠删代码池一起使用的 CRUSH 规则,您可以指定规则名称和纠删代码 profile。
语法
ceph osd crush rule create-erasure RULE_NAME PROFILE_NAME
示例
[ceph: root@host01 /]# ceph osd crush rule create-erasure default default
其它资源
- 如需了解更多详细信息,请参阅 Erasure code profile。
2.7.6. 删除 CRUSH 规则
要删除规则,请执行以下内容并指定 CRUSH 规则名称:
语法
ceph osd crush rule rm NAME
2.8. CRUSH 可调项概述
Ceph 项目随着许多变化和新功能呈指数级增长。从 Ceph 的第一个商业支持主要版本 v0.48(Argonaut)开始,Ceph 提供了调整 CRUSH 算法的某些参数,即设置不在源代码中。
需要考虑以下几个重要点:
- 调整 CRUSH 值可能会导致在存储节点之间移动一些 PG。如果 Ceph 集群已经存储了大量大量数据,准备进行一些要移动的数据。
-
ceph-osd
和ceph-mon
守护进程将在收到更新映射后立即启动新连接的功能位。但是,已经连接的客户端实际上会获得,如果它们不支持新功能,则这些客户端会变得不正确。当您升级 Ceph Storage Cluster 守护进程时,请确定您更新 Ceph 客户端。 -
如果将 CRUSH 可调项设置为非传统值,之后再更改回旧值,则不需要
ceph-osd
守护进程来支持该功能。但是,OSD 对等过程需要检查和了解旧映射。因此,如果集群之前已使用了非传统 CRUSH 值,则不应运行ceph-osd
守护进程的旧版本,即使映射的最新版本已切换回使用传统默认值。
2.8.1. CRUSH 调整
在调优 CRUSH 之前,您应该确保所有 Ceph 客户端和所有 Ceph 守护进程都使用相同的版本。如果您最近升级,请确保您已重启守护进程并重新连接客户端。
调整 CRUSH 可调项的最简单方法是通过更改到已知配置文件。这些是:
-
legacy
:v0.47(pre-Argonaut)和更早版本中的传统行为。 -
argonaut
: v0.48(Argonaut)发行版本支持的旧值。 -
bobtail
:v0.56(Bobtail)发行版本支持的值。 -
firefly
:v0.80(Firefly)发行版本支持的值。 -
hammer
:v0.94(Hammer)发行版本支持的值。 -
Jewel : v10.0.2 (Jewel)发行版本支持的值。
-
optimal
: 当前最佳值。 -
default
:新集群的当前默认值。
您可以使用以下命令在正在运行的集群中选择一个配置集:
语法
# ceph osd crush tunables PROFILE
这可能会导致一些数据移动。
通常,您应该在升级后设置 CRUSH 可调项,或者收到警告。从 v0.74 开始,如果 CRUSH 可调项没有设置为其最佳值,Ceph 会发出警告,则最佳值是 v0.73 的默认值。
您可以通过调整现有集群上的 可调项来删除警告。请注意,这将导致一些数据移动(可能有 10%)。这是首选的路由,但应该小心谨慎,数据移动可能会影响性能。您可以使用以下方法启用最佳可调项:
ceph osd crush tunables optimal
如果事情变得不佳(例如,负载过大)且不进行大量进展,或者有客户端兼容性问题(旧内核 cephfs 或 rbd 客户端,或者预bobtail librados 客户端),您可以切回到以前的配置集:
语法
ceph osd crush tunables PROFILE
例如,要恢复 pre-v0.48(Argonaut)值,请执行:
示例
[ceph: root@host01 /]# ceph osd crush tunables legacy
2.8.2. CRUSH 调优,以硬方式进行
如果确保所有客户端都在运行最新的代码,可以通过提取 CRUSH 映射、修改值并将其注入集群中来调整可调项。
提取最新的 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.3. CRUSH 传统值
为了方便参考,可以使用以下内容设置 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 更方便。但是,有些时候可能会选择编辑它,如更改默认存储桶类型,或使用 straw2
以外的存储桶算法。
要编辑现有的 CRUSH map:
- 获取 CRUSH map.
- 解译 CRUSH map.
- 至少编辑其中一个设备,以及存储桶和规则。
- 编译 CRUSH map
- 设置 CRUSH map.
若要激活特定池的 CRUSH map 规则,可识别常见的规则编号,并在创建池时为池指定规则编号。
2.9.1. 获取 CRUSH map
要获取集群的 CRUSH 映射,请执行以下操作:
语法
ceph osd getcrushmap -o COMPILED_CRUSHMAP_FILENAME
Ceph 会将已编译的 CRUSH map 输出(-o)到您指定的文件名。由于 CRUSH map 采用编译的形式,您必须先解译它,然后才能编辑它。
2.9.2. 解编译 CRUSH map
要解译 CRUSH map,请执行以下操作:
语法
crushtool -d COMPILED_CRUSHMAP_FILENAME -o DECOMPILED_CRUSHMAP_FILENAME
Ceph 解译(-d)编译的 CRUSH map,并将输出(-o)发送到您指定的文件名。
2.9.3. 设置 CRUSH map
要为集群设置 CRUSH 映射,请执行以下操作:
语法
ceph osd setcrushmap -i COMPILED_CRUSHMAP_FILENAME
Ceph 输入您指定为集群的 CRUSH map 的文件名的已编译 CRUSH map。
2.9.4. 编译 CRUSH map
要编译 CRUSH map,请执行以下操作:
语法
crushtool -c DECOMPILED_CRUSHMAP_FILENAME -o COMPILED_CRUSHMAP_FILENAME
Ceph 会将编译的 CRUSH map 存储到您指定的文件名。
2.10. CRUSH 存储策略示例
如果您希望大多数池默认为由大型硬盘支持的 OSD,但有一些池映射到由快速固态驱动器(SSD)支持的 OSD。CRUSH 可以轻松地处理这些场景。
使用设备类。这个过程很简单,可向每个设备添加一个类。
语法
ceph osd crush set-device-class CLASS OSD_ID [OSD_ID]
示例
[ceph:root@host01 /]# ceph osd crush set-device-class hdd osd.0 osd.1 osd.4 osd.5 [ceph:root@host01 /]# ceph osd crush set-device-class ssd osd.2 osd.3 osd.6 osd.7
然后,创建规则以使用设备。
语法
ceph osd crush rule create-replicated RULENAME ROOT FAILURE_DOMAIN_TYPE DEVICE_CLASS
示例
[ceph:root@host01 /]# ceph osd crush rule create-replicated cold default host hdd [ceph:root@host01 /]# ceph osd crush rule create-replicated hot default host ssd
最后,将池设置为使用规则。
语法
ceph osd pool set POOL_NAME crush_rule RULENAME
示例
[ceph:root@host01 /]# ceph osd pool set cold crush_rule hdd [ceph:root@host01 /]# ceph osd pool set hot crush_rule ssd
不需要手动编辑 CRUSH map,因为一个层次结构可以服务于多个类设备。
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 straw2 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 straw2 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 straw2 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)不适用于 Ceph 客户端,但它们在 Ceph Storage 集群中发挥重要角色。
Ceph 存储集群可能需要数以千计的 OSD 才能达到超字节级别的存储容量。Ceph 客户端将对象存储在池中,这是整个集群的逻辑子集。存储在池中的对象数量可能容易在数百万和以后运行。具有数以百万计的对象或更无法现实地跟踪每个对象上的放置的系统,仍然表现良好。Ceph 将对象分配到放置组,并将放置组分配给 OSD,以重新平衡动态和效率。
计算机科学中的所有问题均可由另一级间接处理,除非有太多间接的问题除外。 | ||
-- David Wheeler |
3.1. 关于放置组
根据池中的每个对象跟踪对象放置,以大规模计算代价。为了大规模实现高性能,Ceph 将池划分为放置组,将每个对象分配到 PG,并将放置组分配到 Primary OSD。如果 OSD 失败或集群重新平衡,Ceph 可以移动或复制整个放置组,即,PG 中的所有对象都不需要单独解析各个对象。这使得 Ceph 集群能够有效地重新平衡或恢复。
当 CRUSH 将 PG 分配给 OSD 时,它会计算一系列 OSD- 第一个是主要的。osd_pool_default_size
设置减 1
用于复制池,而用于纠删代码池的编码区块 M
数量决定了存储放置组的 OSD 的数量,而不会永久丢失数据。Primary OSD 使用 CRUSH 来识别次要 OSD,并将 PG 的内容复制到次要 OSD。例如,如果 CRUSH 将对象分配给放置组,并且放置组分配到 OSD 5 作为 Primary OSD,如果 CRUSH 计算 OSD 1 和 OSD 8 是放置组的次要 OSD,则主要 OSD 5 会将数据复制到 OSD 1 和 8。通过代表客户端复制数据,Ceph 简化了客户端接口并减少客户端工作负载。同样的过程允许 Ceph 集群动态恢复和重新平衡。
当 Primary OSD 出现故障并标记为 out 集群时,CRUSH 会将放置组分配到另一个 OSD,后者接收 PG 中的对象副本。Up Set
中的另一个 OSD 将假定主 OSD 的角色。
当您增加对象副本或编码区块的数量时,CRUSH 将根据需要将每个放置组分配到额外的 OSD。
PG 本身没有 OSD。CRUSH 将许多放置组分配到每个 OSD 伪随机,以确保数据在集群中平均分布。
3.2. 放置组状态
当您使用 ceph -s
或 ceph -w
命令检查存储集群的状态时,Ceph 将报告放置组(PG)的状态。PG 具有一个或多个状态。PG 映射中的 PG 的 optimum 状态为 active + clean
状态。
- 激活
- PG 为 peered,但还没有激活。
- active
- Ceph 处理对 PG 的请求。
- backfill_toofull
- 回填操作正在等待,因为目标 OSD 处于回填 full 比率。
- backfill_unfound
- 回填因为 unfound 对象而停止。
- backfill_wait
- PG 正在等待行开始回填。
- 回填
- Ceph 正在扫描并同步 PG 的整个内容,而不是推断内容需要从最近的操作日志同步。backfill 是恢复的特殊情况。
- 清理
- Ceph 准确复制 PG 中的所有对象。
- 创建
- Ceph 仍然在创建 PG。
- deep
- Ceph 正在根据存储的校验和检查 PG 数据。
- degraded
- Ceph 尚未准确复制 PG 中的一些对象。
- down
-
具有必要数据的副本已停机,因此 PG 离线。副本数小于
min_size
的 PG 标记为 down。使用ceph health detail
了解后备 OSD 状态。 - forced_backfill
- 用户强制执行该 PG 的高回填优先级。
- forced_recovery
- 用户强制执行该 PG 的高恢复优先级。
- incomplete
-
Ceph 检测到 PG 缺少有关可能发生的写入的信息,或者没有任何健康的副本。如果您看到此状态,请尝试启动可能包含所需信息的任何故障 OSD。对于纠删代码池,暂时减少
min_size
可能允许恢复。 - 不一致
- Ceph 在 PG 中检测一个或多个对象副本的不一致,如对象是错误的大小,在恢复完成后从一个副本中缺少对象。
- peering
- PG 正在进入 peering 过程。对等进程应该清除没有延迟,但如果它保留,且处于 peering 状态的 PG 数量不会减少数字,对等进程可能会卡住。
- peered
-
PG 有对等的,但由于没有足够的副本来访问池的
min_size
参数,因此无法提供客户端 IO。恢复可能在此状态发生,因此 PG 可能会最终修复min_size
。 - recovering
- Ceph 正在迁移或同步对象及其副本。
- recovery_toofull
- 恢复操作正在等待,因为目标 OSD 超过了其全满比率。
- recovery_unfound
- 恢复因为 unfound 对象而停止。
- recovery_wait
- PG 正在等待行开始恢复。
- remapped
- PG 从指定的 CRUSH 暂时映射到一组不同的 OSD。
- repair
- Ceph 正在检查 PG,并在可能的情况下修复发现的任何不一致。
- replay
- PG 正在等待客户端在 OSD 崩溃后重新执行操作。
- snaptrim
- 修剪快照。
- snaptrim_error
- 错误停止修剪快照。
- snaptrim_wait
- 排队以修建快照。
- 清理
- Ceph 正在检查 PG 元数据是否不一致。
- 分割
- Ceph 将 PG 拆分为多个 PG。
- stale
- PG 处于未知状态;监视器尚未收到更新,因为 PG 映射发生了变化。
- undersized
- PG 的副本数量比配置的池复制级别少。
- unknown
-
自 Ceph 管理器启动以来,
ceph-mgr
尚未从 OSD 收到有关 PG 状态的任何信息。
其他资源
- 如需更多信息 ,请参阅 Ceph 集群中可能 使用的放置组状态。
3.3. 放置组权衡
所有 OSD 中的数据持久性和数据分布调用更多的放置组,但为了节省 CPU 和内存资源,其数量应减小到满足要求的最小值。
3.3.1. 数据持久性
Ceph 可以通过防止永久丢失数据获得好处。但是,在 OSD 失败后,永久数据丢失的风险会增加,直到其数据被完全恢复为止。仍然有可能造成持久性数据丢失。以下场景描述了如何在带有三个数据副本的单个放置组中永久丢失数据:
- OSD 失败,其中包含的对象的所有副本都会丢失。对于存储在 OSD 上的放置组内的所有对象,副本的数量会从三个减少到两个。
- Ceph 通过选择新 OSD 为故障 OSD 重新创建所有对象的第三个副本,从而开始恢复故障 OSD。
- 在新 OSD 完全填充了第三个副本之前,第二个包含相同放置组副本的 OSD 会失败。然后,一些对象将只有一个存活副本。
- Ceph 还需要选择另一个 OSD,并保留复制对象来恢复所需的副本数。
- 在恢复完成前,包含同一放置组副本的第三个 OSD 会失败。如果此 OSD 仅包含对象的唯一剩余副本,则对象会永久丢失。
硬件故障不是例外,而是预计中的情况。为防止这种情况,理想的恢复过程应尽可能快。集群的大小、您的硬件配置和放置组的数量在总恢复时扮演重要角色。
小集群无法快速恢复。
在三个副本池中包含有 512 个放置组的 10 个 OSD 的集群中,OSD 将为每个放置组提供三个 OSD。每个 OSD 将最终托管 (512 * 3)/ 10 = ~150
放置组。当第一个 OSD 出现故障时,集群将同时开始恢复所有 150 个放置组。
Ceph 可能会在 9 个剩余的 OSD 之间随机存储剩余的 150 个放置组。因此,每个剩余的 OSD 可能会向所有其他 OSD 发送副本,并接收一些新的对象,因为剩余的 OSD 现在已负责分配给它们的一些 150 个放置组。
总恢复时间取决于支持池的硬件。例如,在一个 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 个 PG。20 个 OSD 集群仍然需要所有剩余的 19 个 OSD 执行相同副本操作,以便恢复。在 10 OSD 集群中,每个 OSD 必须复制大约 100 GB。在 20 个 OSD 集群中,每个 OSD 只需要复制 50 GB。如果网络瓶颈,恢复将快速出现两次。换句话说,当 OSD 数量增加时,恢复时间会减少。
在大型集群中,PG 数非常重要!
如果 exemplary 集群增长到 40 个 OSD,每个 OSD 只会托管 35 个放置组。如果 OSD 出现问题,恢复时间会减少,除非出现另一个瓶颈影响。但是,如果此集群增大到 200 个 OSD,每个 OSD 只会托管大约 7 个放置组。如果 OSD 崩溃,恢复将在这些放置组中的大多数 21 (7 * 3)
OSD 之间发生: 恢复的时间比存在 40 个 OSD 时要比存在 40 个 OSD 所需的时间要长,这意味着应增加放置组的数量!
无论恢复时间有多短,在恢复过程中都会存在存储放置组的另一个 OSD 出现故障的情况。
在上述 10 OSD 集群中,如果任何 OSD 失败,则大约 8 个放置组(即 75 pgs / 9 osds
被恢复)将只有一个存活副本。如果其中任何 8 个剩余的 OSD 失败,则一个放置组的最后对象可能会丢失(即 8 pgs / 8 osds
,只有一个剩余副本被恢复)。这是为什么首选从一些大型集群开始(例如 50 个 OSD)。
当集群大小增加到 20 个 OSD 时,放置组的数量会因为三个 OSD 丢失而损坏。第二个 OSD 大约会降级 2(即 35 pgs / 19 osds
被恢复)而不是 8,而第三个 OSD 仅在含有存活副本的两个 OSD 之一时丢失数据。换句话说,如果在恢复时间范围内丢失一个 OSD 的概率为 0.0001%
,它在 10 个 OSD 的集群中为 8 * 0.0001%
,在 20 个 OSD 的集群中为 2 * 0.0001%
。随着数据持久性,具有 512 或 4096 个放置组在低于 50 个 OSD 的集群中大致相等。
概括讲,更多的 OSD 意味着快速恢复速度,降低因为级联故障导致放置组和其的向永久丢失的风险。
将 OSD 添加到集群时,可能需要很长时间才能为新的 OSD 填充放置组和对象。但是,任何对象都没有降级,而添加 OSD 不会影响数据持久性。
3.3.2. 数据分发
Ceph 寻求避免热点(一些 OSD 接收比其他 OSD 更多的流量)。理想情况下,CRUSH 将对象分配到放置组,以便在放置组被分配给 OSD(也可以随机)时,主 OSD 存储对象会均匀分布在群集和热点上,以及因为数据分发而造成的网络超额订阅问题。
由于 CRUSH 计算每个对象的放置组,但实际上不知道该放置组中各个 OSD 中存储的数据量,因此 放置组数量和 OSD 数量之间的比率可能会大大影响数据的分布。
例如,如果三个副本池中只有一个放置组具有十个 OSD,Ceph 将仅使用三个 OSD 来存储数据,因为 CRUSH 不会有其他选择。当更多放置组可用时,CRUSH 更有可能在 OSD 之间均匀分布对象。CRUSH 也平均分配 PG 到 OSD。
只要有一个或两个 magnitude 多个放置组,分布应该为偶数。例如,3 个 OSD 256 个放置组,10 个 OSD 512 或 1024 个放置组,以此类推。
OSD 和放置组之间的比率通常会解决实施对象条带等高级功能的 Ceph 客户端的数据分布问题。例如,4TB 块设备可能会分片为 4 MB 对象。
OSD 和放置组之间的比率不会在其他情况下解决不均匀的数据分布,因为 CRUSH 不考虑对象大小。使用 librados
接口存储一些相对较小的对象,有些非常大的对象可能会导致数据分布不均匀。例如,总计 4 GB 的 4K 对象均匀分布在 10 个 OSD 上的 1000 个放置组之间。它们将在每个 OSD 上使用 4 GB / 10 = 400 MB
。如果一个 400 MB 对象添加到池中,为放置了该对象的放置组提供支持的三个 OSD 将会填充 400 MB + 400 MB = 800 MB
,而其他七个 OSD 仍然仅被占据 400 MB。
3.3.3. 资源使用量
对于每个放置组,OSD 和 Ceph 监视器会一直需要内存、网络和 CPU,在恢复期间甚至更多。由集群放置组中的集群对象共享这个开销是放置组存在的主要原因之一。
尽量减少放置组的数量可以节省大量资源。
3.4. 放置组计数
池中放置组的数量对于集群如何对等、分布数据和重平衡操作起非常重要的作业。与大型集群相比,在小集群中增加放置组的数据对性能并不会有显著提高。但是,具有许多池访问同一 OSD 的集群可能需要仔细考虑 PG 数,以便 Ceph OSD 高效地使用资源。
红帽建议每个 OSD 100 到 200 个 PG。
3.4.1. 放置组计算器
放置组(PG)计算器计算您和地址特定用例的放置组数量。当使用 Ceph 客户端(如 Ceph 对象网关)时,PG 计算器尤其有用,其中有许多池通常使用相同的规则(CRUSH 层次结构)。您仍然可以使用 小集群的放置组计数和计算放置组计数 中的准则来手动 计算 PG。但是,PG 计算器是计算 PG 的首选方法。
3.4.2. 配置默认放置组计数
在创建池时,您还会为池创建多个放置组。如果您没有指定放置组数量,Ceph 将使用默认值 8
,这并不低。您可以为池增加放置组数量,但我们建议也设置合理的默认值。
osd pool default pg num = 100 osd pool default pgp num = 100
您需要设置放置组数量(总计)以及用于对象的放置组数量(在 PG 分隔中使用的数量)。它们应该相等。
3.4.3. 小集群的放置组计数
小集群不会从大量放置组中受益。随着 OSD 数量的增加,为 pg_num
和 pgp_num
选择正确的值会变得更为重要,因为在出现问题时以及数据不稳定(这是严重事件导致数据丢失的可能性)时,对集群的行为有显著影响。将 PG 计算器 与小集群一起使用非常重要。
3.4.4. 计算放置组计数
如果您有超过 50 个 OSD,我们建议每个 OSD 大约有 50-100 个放置组,以平衡资源使用量、数据持久性和分布。如果您有超过 50 个 OSD,在 PG Count for Small Clusters 中选择是理想的选择。对于单个对象池,您可以使用以下公式获取基准:
(OSDs * 100) Total PGs = ------------ pool size
其中,pool size 是复制池的副本数,或用于删除代码池的 K+M
总和(ceph osd erasure-code-profile
的返回值)。
然后,您应该检查结果是否适合您设计 Ceph 集群以最大化数据持久性、数据分布和最小化资源使用量。
结果应舍入到最接近的 2 的指数。向上舍入是可选的,但建议 CRUSH 在放置组之间均匀平衡对象数量。
对于 200 个 OSD 和池大小为 3 个副本的集群,您可以估计您的 PG 数量,如下所示:
(200 * 100) ----------- = 6667. Nearest power of 2: 8192 3
当 8192 个放置组分布到 200 个 OSD 时,每个 OSD 大约评估为 41 个放置组。您还需要考虑集群中可能会使用的池数量,因为每个池也会创建放置组。确保具有合理 的最大放置组计数。
3.4.5. 最大放置组计数
当使用多个数据池来存储对象时,您需要确保平衡每个池的放置组数量与每个 OSD 的放置组数量,以便您可以达到合理的放置组总数。其目的是在不用系统资源或使对等进程变得太慢的情况下,每个 OSD 取得明显低差异。
在由 10 个池组成的 exemplary Ceph Storage 集群中,每个池在 10 个 OSD 上有 512 个放置组,总计有 5120 个 PG 分布于 10 个 OSD 中,或每个 OSD 都有 512 个放置组。取决于硬件配置,可能无法使用过多的资源。相反,如果您创建 1,000 个池,每个 PG 具有 512 个 PG,OSD 将处理 ~50,000的放置组,这需要大量资源。运行每个 OSD 的 PG 数量太多可能会显著降低性能,特别是在重新平衡或恢复期间。
Ceph Storage 集群具有每个 OSD 的默认最大值为 300 个放置组。您可以在 Ceph 配置文件中设置不同的最大值。
mon pg warn max per osd
Ceph 对象网关部署有 10-15 池,因此您可能会考虑每个 OSD 使用小于 100 个 PG,以达到合理的最大数量。
3.5. 自动扩展放置组
池中放置组(PG)的数量对于集群如何对等、分布数据和重平衡操作起非常重要的作业。
自动扩展 PG 数量可以更轻松地管理集群。pg-autoscaling
命令提供扩展 PG 的建议,或者根据集群的使用方式自动扩展 PG。
- 要了解更多有关自动扩展如何工作的信息,请参阅 第 3.5.1 节 “放置组自动扩展”。
- 要启用或禁用自动扩展,请参阅 第 3.5.3 节 “设置放置组自动扩展模式”。
- 要查看放置组扩展建议,请参阅 第 3.5.4 节 “查看放置组扩展建议”。
- 要设置放置组自动扩展,请参阅 第 3.5.5 节 “设置放置组自动扩展”。
-
要全局更新自动扩展,请参阅 第 3.5.6 节 “更新
noautoscale
标记” - 要设置目标池大小,请参阅 第 3.6 节 “指定目标池大小”。
3.5.1. 放置组自动扩展
auto-scaler 的工作原理
auto-scaler 分析池并根据每个子树进行调整。由于每个池都可以映射到不同的 CRUSH 规则,并且每个规则可以在不同的设备间分布数据,Ceph 都将独立使用每个子树。例如,映射到类 ssd
的 OSD 的池以及映射到类 hdd
的 OSD 的池,各自具有取决于这些对应设备类型的最优 PG 数量。
3.5.2. 放置组分割和合并
分割
Red Hat Ceph Storage 可将现有放置组(PG)分成较小的 PG,这会增加给定池的 PG 总数。分割现有放置组(PG)允许小的 Red Hat Ceph Storage 集群随着存储要求增加而进行扩展。PG 自动扩展功能可以增加 pg_num
值,这会导致现有 PG 在存储集群扩展时分割。如果 PG 自动扩展功能被禁用,您可以手动增加 pg_num
值,这将触发 PG 分割进程开始。例如,将 pg_num
值从 4
增加到 16
,将分为四部分。增加 pg_num
值也会增加 pgp_num
值,但 pgp_num
值会以 gradual 速率增加。逐步增加是为了最大程度降低存储集群性能和客户端工作负载的影响,因为迁移对象数据给系统带来显著的负载。默认情况下,Ceph 队列且不超过处于"misplaced"状态的对象数据的 5%。可以使用 target_max_misplaced_ratio
选项调整此默认百分比。
合并
Red Hat Ceph Storage 也可以将两个现有的 PG 合并到一个更大的 PG 中,这可以减少 PG 总数。将两个 PG 合并在一起会很有用,特别是当池中对象的相对量逐渐下降时,或者选择初始的 PG 数量太大时。虽然合并 PG 非常有用,但它也是一个复杂的 delicate 进程。在进行合并时,到 PG 的 I/O 会暂停,一次只合并一个 PG,从而最大程度降低对存储集群性能的影响。Ceph 在合并对象数据时很慢,直到达到新的 pg_num
值。
3.5.3. 设置放置组自动扩展模式
Red Hat Ceph Storage 集群中的每个池都有一个 pg_autoscale_mode
属性,用于可以设置为 off
、或 warn
。
-
off
:禁用池的自动扩展。管理员最多可为每个池选择适当的 PG 数。如需更多信息,请参阅 放置组计数 部分。 -
在 上
:为给定池启用自动调整 PG 数。 -
warn
:当 PG 数量需要调整时,请检测健康警报。
在 Red Hat Ceph Storage 5 及更新的版本中,pg_autoscale_mode
默认为 on
。升级的存储集群保留现有的 pg_autoscale_mode
设置。对于新创建的池,pg_auto_scale
模式为 on
。PG 数量会自动调整,ceph 状态
可能会在 PG 计数调整期间显示 recovering 状态。
自动缩放器使用 bulk
标志来确定哪个池应当以完整补充的 PG 开头,并且仅在池之间的使用量比率不会被缩减。但是,如果池没有 bulk
标记,池以最少的 PG 开头,并且仅在池中有更多使用量时才会开始。
自动扩展程序(autoscaler)会识别任何重叠的根,并防止扩展带有重叠根的池,因为重叠的根可能会导致扩展过程出现问题。
流程
在现有池中启动自动扩展:
语法
ceph osd pool set POOL_NAME pg_autoscale_mode on
示例
[ceph: root@host01 /]# ceph osd pool set testpool pg_autoscale_mode on
在新创建的池中启用自动扩展:
语法
ceph config set global osd_pool_default_pg_autoscale_mode MODE
示例
[ceph: root@host01 /]# ceph config set global osd_pool_default_pg_autoscale_mode on
使用
批量标记创建池
:语法
ceph osd pool create POOL_NAME --bulk
示例
[ceph: root@host01 /]# ceph osd pool create testpool --bulk
为现有池设置或取消设置
批量
标记:重要该值必须写为
true
、false
、1
或0。
1
等同于true
,0
相当于false
。如果使用不同的大写或其它内容编写,则会发出错误。以下是使用错误语法编写的命令示例:
[ceph: root@host01 /]# ceph osd pool set ec_pool_overwrite bulk True Error EINVAL: expecting value 'true', 'false', '0', or '1'
语法
ceph osd pool set POOL_NAME bulk true/false/1/0
示例
[ceph: root@host01 /]# ceph osd pool set testpool bulk true
获取现有池的
批量
标记:语法
ceph osd pool get POOL_NAME bulk
示例
[ceph: root@host01 /]# ceph osd pool get testpool bulk bulk: true
3.5.4. 查看放置组扩展建议
您可以查看池,它的相对利用率以及存储集群中 PG 数量的建议更改。
先决条件
- 正在运行的 Red Hat Ceph Storage 集群
- 所有节点的根级别访问权限。
流程
您可以使用以下方法查看每个池、其相对利用率以及对 PG 数量的建议更改:
[ceph: root@host01 /]# ceph osd pool autoscale-status
输出类似如下:
POOL SIZE TARGET SIZE RATE RAW CAPACITY RATIO TARGET RATIO EFFECTIVE RATIO BIAS PG_NUM NEW PG_NUM AUTOSCALE BULK device_health_metrics 0 3.0 374.9G 0.0000 1.0 1 on False cephfs.cephfs.meta 24632 3.0 374.9G 0.0000 4.0 32 on False cephfs.cephfs.data 0 3.0 374.9G 0.0000 1.0 32 on False .rgw.root 1323 3.0 374.9G 0.0000 1.0 32 on False default.rgw.log 3702 3.0 374.9G 0.0000 1.0 32 on False default.rgw.control 0 3.0 374.9G 0.0000 1.0 32 on False default.rgw.meta 382 3.0 374.9G 0.0000 4.0 8 on False
SIZE
是池中存储的数据量。
TARGET SIZE
存在(如果存在)是管理员指定的数据量,管理员期望最终存储在这个池中。系统在计算时会使用这两个值中的较大的值。
RATE
是池的倍数,用于确定池使用的原始存储容量量。例如,一个 3
副本池的比率为 3.0
,而 k=4,m=2
纠删代码池的比例为 1.5
。
RAW CAPACITY
是 OSD 上负责存储池数据的原始存储容量总量。
RATIO
是池消耗的总容量的比率,即 ratio = size = rate / raw capacity。
TARGET RATIO
(如果存在)是管理员指定的存储比率,是与带有目标比率的其他池相对应的期望池的消耗。如果指定了目标大小字节和比率,则比率将具有优先权。TARGET RATIO
的默认值为 0,
除非在创建池时指定。您在一个池中提供的 --target_ratio
越多,您期望池的 PG 越大。
EFFECTIVE RATIO
是在以两种方式调整后的目标比率:1。减去设置了目标大小的池使用的任何容量。2. 在带有目标比率设置的池之间规范化目标比率,以便它们一起处理剩余空间。例如,带有 目标比率
1.0 的 4 个池 将有效
比率为 0.25。系统使用的较大的实际比率,以及计算的有效比率。
BIAS
被视为一个倍数,根据之前有关特定池应有的 PG 量的信息,手动调整池的 PG。默认情况下,如果 1.0,其值是在创建池时指定的值。您在一个池中提供的 --bias
越多,您期望池的 PG 越大。
PG_NUM
是池的当前 PG 数量,或者当 pg_num
更改正在进行时池正在工作的当前 PG 数量。NEW PG_NUM
(如果存在)是推荐的 PG 数量(pg_num
)。它始终是 2 的指数,它只有在建议的值与因当前值的不同大于 3 倍时才存在。
AUTOSCALE
,是池 pg_autoscale_mode
,可以为 on
, off
, 或 warn
。
BULK
用于确定哪个池应以 PG 的完整补充开头。BULK
仅在使用量在池中的使用比率不平衡时进行缩减。如果池没有此标志,池以最少的 PG 开始,且仅在池中有更多使用量时才使用。
BULK
的值为 true
, false
, 1
, 或 0
, 其中 1
等同于 true
,0
等同于 false
。默认值为 false
。
BULK
值可以在池创建过程中或之后设置 。
有关使用 bulk 标记的更多信息,请参阅 创建池 和设置放置组自动扩展模式。
3.5.5. 设置放置组自动扩展
允许集群根据集群使用量自动扩展 PG,是扩展 PG 的最简单方法。Red Hat Ceph Storage 使用整个系统的可用存储和 PG 的目标数量,比较每个池中存储的数据数量,并相应地应用 PG。该命令仅更改其当前 PG 数 (pg_num
) 大于计算出的或建议的 PG 数的 3 倍的池。
每个 OSD 的目标 PG 数量基于 mon_target_pg_per_osd
可配置。默认值为 100
。
流程
调整
mon_target_pg_per_osd
:语法
ceph config set global mon_target_pg_per_osd number
例如:
[ceph: root@host01 /]# ceph config set global mon_target_pg_per_osd 150
3.5.6. 更新 noautoscale
标记
如果要同时为所有池启用或禁用自动扩展器,您可以使用 noautoscale
全局标志。当某些 OSD 被退回或集群处于维护状态时,这个全局标志很有用。您可以在任何活动前设置标志,并在活动完成后取消设置它。
默认情况下,noautoscale
标志被设置为 off
。当设置此标志时,所有池都有 pg_autoscale_mode
为 off
,所有池都禁用了自动扩展器。
先决条件
- 正在运行的 Red Hat Ceph Storage 集群
- 所有节点的根级别访问权限。
流程
获取
noautoscale
标志的值:示例
[ceph: root@host01 /]# ceph osd pool get noautoscale
在任何活动前设置
noautoscale
标志:示例
[ceph: root@host01 /]# ceph osd pool set noautoscale
在完成活动时取消设置
noautoscale
标志:示例
[ceph: root@host01 /]# ceph osd pool unset noautoscale
3.6. 指定目标池大小
新创建的池消耗少量集群容量,并出现在需要少量的 PG 的系统中。然而,在大多数情形中,集群管理员知道哪些池预期消耗了大多数系统容量。如果您向 Red Hat Ceph Storage 提供此信息,称为 目标大小
,此类池可以从开始使用更合适的 PG 数量(pg_num
)。这种方法可防止 pg_num
中的后续更改,以及进行这些调整时移动数据相关的开销。
您可以使用以下方法指定池的目标大小
:
3.6.1. 使用池的绝对大小指定目标大小
流程
使用池绝对
大小(以字节为单位)设置目标大小
:ceph osd pool set pool-name target_size_bytes value
例如,要指示
mypool
应该消耗 100T 的空间:$ ceph osd pool set mypool target_size_bytes 100T
您还可以通过将可选的 --target-size-bytes <bytes>
参数添加到 ceph osd pool create
命令中,来设置池创建的目标大小。
3.6.2. 使用集群容量指定目标大小
流程
使用集群容量总数来设置
目标大小
:语法
ceph osd pool set pool-name target_size_ratio ratio
例如:
[ceph: root@host01 /]# ceph osd pool set mypool target_size_ratio 1.0
告诉系统,池
mypool
期望消耗 1.0,相对于其他设置了target_size_ratio
的池。如果mypool
是集群中唯一的池,这意味着预期使用总容量的 100%。如果有一个target_size_ratio
为 1.0 的第二个池,则两个池都应该使用 50% 的集群容量。
您还可以通过将可选的 --target-size-ratio <ratio>
参数添加到 ceph osd pool create
命令,在创建时设置池的目标大小。
如果您指定了无法达到的目标大小值,例如:大于总集群的容量,或者设置比例的总和大于 1.0,集群会引发 POOL_TARGET_SIZE_RATIO_OVERCOMMITTED
或 POOL_TARGET_SIZE_BYTES_OVERCOMMITTED
健康警告。
如果您同时为池指定 target_size_ratio
和 target_size_bytes
,集群仅考虑比例,并引发 POOL_HAS_TARGET_SIZE_BYTES_AND_RATIO
健康警告。
3.7. 放置组命令行界面
ceph
CLI 允许您设置并获取池的 PG 数量,查看 PG map 并检索 PG 统计信息。
3.7.1. 在池中设置放置组数量
要在池中设置放置组数量,您必须在创建池时指定放置组数量。详情请参阅 创建池。为池设置放置组后,您可以增加放置组的数量(但您无法减少放置组数量)。要增加放置组的数量,请执行以下操作:
语法
ceph osd pool set POOL_NAME pg_num PG_NUM
增加放置组数量后,还必须在集群重新平衡前增加放置的放置组数量(pgp_num
)。pgp_num
应该等于 pg_num
。要增加放置的放置组数量,请执行以下操作:
语法
ceph osd pool set POOL_NAME pgp_num PGP_NUM
3.7.2. 在池中获取放置组数量
要获取池中的放置组数量,请执行以下操作:
语法
ceph osd pool get POOL_NAME pg_num
3.7.3. 获取放置组的统计信息
要在您的 storag 集群中获取放置组的统计信息,请执行以下操作:
语法
ceph pg dump [--format FORMAT]
有效格式为 plain
(默认)和 json
。
3.7.4. 获取卡住放置组的统计信息
要获取所有放置组的统计数据处于指定状态,请执行以下操作:
语法
ceph pg dump_stuck {inactive|unclean|stale|undersized|degraded [inactive|unclean|stale|undersized|degraded...]} INTERVAL
Inactive 放置组无法处理读取或写入,因为它们正在等待具有最新数据最多的 OSD 上线并在内。
Unclean 放置组包含没有复制所需时间的对象。它们应该正在进行恢复。
Stale 放置组处于未知状态 - 托管它们尚未报告至监控集群的 OSD (由 mon_osd_report_timeout
配置)。
有效格式为 plain
(默认)和 json
。阈值定义了放置组在返回统计之前卡住的最小秒数(默认为 300 秒)。
3.7.5. 获取放置组映射
要获取特定放置组的放置组映射,请执行以下操作:
语法
ceph pg map PG_ID
示例
[ceph: root@host01 /]# ceph pg map 1.6c
Ceph 返回放置组映射、放置组和 OSD 状态:
osdmap e13 pg 1.6c (1.6c) -> up [1,0] acting [1,0]
3.7.6. 清理放置组
要清理放置组,请执行以下操作:
语法
ceph pg scrub PG_ID
Ceph 检查主节点和任何副本节点,生成放置组中所有对象的目录,并比较它们以确保没有缺少或不匹配对象,并且其内容一致。假设副本都匹配,最终语义 sweep 可确保所有与快照相关的对象元数据一致。通过日志报告错误。
3.7.7. 标记 unfound
对象
如果集群丢失了一个或多个对象,并且您决定取消搜索丢失数据,您必须将未找到的对象标记为 lost
。
如果查询了所有可能的位置,并且对象仍然丢失,您可能需要放弃丢失的对象。这是可行的失败组合,允许集群了解在写入本身恢复之前执行的写入操作。
目前唯一支持的选项为 "revert",该选项可回滚到对象的旧版本,或者完全忘记了它(如果它是新对象)。要将 "unfound" 对象标记为 "lost",请执行以下操作:
语法
ceph pg PG_ID mark_unfound_lost revert|delete
请谨慎使用此功能,因为它可能会混淆预期对象存在的应用程序。
第 4 章 池概述
Ceph 客户端将数据存储在池中。创建池时,您要为客户端创建一个 I/O 接口来存储数据。
从 Ceph 客户端的角度来看,即块设备、网关和其他,与 Ceph 存储集群交互非常简单:
- 创建集群句柄。
- 将集群句柄连接到集群。
- 创建用于读取和写入对象及其扩展属性的 I/O 上下文。
创建集群句柄并连接到集群
要连接到 Ceph 存储集群,Ceph 客户端需要以下详情:
- 集群名称(默认为 Ceph )- 不使用通常,因为它听起来很不确定。
- 初始监控地址。
Ceph 客户端通常使用 Ceph 配置文件的默认路径检索这些参数,然后从文件读取,但用户也可以在命令行中指定参数。Ceph 客户端还提供用户名和密钥,身份验证默认为 on
。然后,客户端联系 Ceph 监控集群,并检索 cluster map 的最新副本,包括其 monitor、OSD 和池。
创建池 I/O 上下文
为了读取和写入数据,Ceph 客户端会为 Ceph 存储集群中的特定池创建一个 I/O 上下文。如果指定的用户具有池的权限,Ceph 客户端可以从指定的池读取和写入。
Ceph 的架构使存储集群能够将此简单接口提供给 Ceph 客户端,以便客户端可以通过指定池名称并创建 I/O 上下文来选择您定义的一个复杂的存储策略。存储策略对 Ceph 客户端在容量和性能方面不可见。类似地,Ceph 客户端的复杂性(如将对象映射到块设备表示或提供 S3/Swift RESTful 服务)对 Ceph 存储集群不可见。
池为您提供了弹性、放置组、CRUSH 规则和配额。
-
弹性 :您可以设置允许多少个 OSD 失败,而不丢失数据。对于复制池,这是对象的所需副本数。典型的配置存储一个对象和一个额外副本,即
size = 2
,但您可以确定副本或副本数。对于纠删代码池,它是 纠删代码 profile 中的编码区块数,即m=2
。 - 放置组 :您可以为池设置放置组数量。典型的配置为每个 OSD 使用大约 50 到 100 个放置组来提供最佳平衡,而无需使用太多计算资源。在设置多个池时,要小心,请务必为池和集群设置合理的放置组数量。
- CRUSH 规则 :当您在池中存储数据时,映射到池的 CRUSH 规则可让 CRUSH 识别每个对象及其副本放置的规则,或者集群中纠删代码池的块。您可以为池创建自定义 CRUSH 规则。
-
配额 :当您使用
ceph osd pool set-quota
命令在池中设置配额时,您可以限制对象的最大数量或指定池中存储的最大字节数。
4.1. 池和存储策略概述
要管理池,您可以列出、创建和删除池。您还可以查看各个池的使用情况统计信息。
4.2. 列出池
列出集群的池:
示例
[ceph: root@host01 /]# ceph osd lspools
4.3. 创建池
在创建池前,请参阅 配置指南 以了解更多详情。
最好为放置组数量调整默认值,因为默认值不必适合您的需要:
示例
[ceph: root@host01 /]# ceph config set global osd_pool_default_pg_num 250 [ceph: root@host01 /]# ceph config set global osd_pool_default_pgp_num 250
创建复制池:
语法
ceph osd pool create POOL_NAME PG_NUM PGP_NUM [replicated] \ [CRUSH_RULE_NAME] [EXPECTED_NUMBER_OBJECTS]
创建纠删代码池:
语法
ceph osd pool create POOL_NAME PG_NUM PGP_NUM erasure \ [ERASURE_CODE_PROFILE] [CRUSH_RULE_NAME] [EXPECTED_NUMBER_OBJECTS]
创建批量池:
语法
ceph osd pool create POOL_NAME [--bulk]
其中:
- POOL_NAME
- 描述
- 池的名称。它必须是唯一的。
- 类型
- 字符串
- 必填
- 是。如果没有指定,则会设置为默认值。
- 默认
-
ceph
- PG_NUM
- 描述
-
池的放置组总数。有关计算合适的数字的详细信息,请参阅每个池计算器的放置组 部分和 Ceph Placement Groups (PG)计算器。默认值
8
不适用于大多数系统。 - 类型
- 整数
- 必填
- 是
- 默认
-
8
- PGP_NUM
- 描述
- 用于放置的放置组总数。这个值必须等于放置组总数,但放置组分割场景除外。
- 类型
- 整数
- 必填
- 是。如果没有指定,则设置为默认值。
- 默认
-
8
复制或纠删代码
- 描述
-
池类型可以通过保留对象的多个副本来获取通用的 RAID5 功能,
从而
从丢失的 OSD 中恢复。复制池需要更多原始存储,但实施所有 Ceph 操作。纠删代码池需要较少的原始存储,但仅实现可用操作的一个子集。
- 类型
- 字符串
- 必填
- 否
- 默认
-
复制
- CRUSH_RULE_NAME
- 描述
-
池的 CRUSH 规则的名称。规则 必须存在。对于复制池,name 是
osd_pool_default_crush_rule
配置设置指定的规则。对于纠删代码池,如果您指定了默认的纠删代码 profile 或POOL_NAME
,则名称为erasure-code
。如果规则尚不存在,Ceph 会隐式创建具有指定名称的规则。 - 类型
- 字符串
- 必填
- 否
- 默认
-
对纠删代码池使用
erasure-code
。对于复制池,它使用 Ceph 配置中的osd_pool_default_crush_rule
变量的值。
- EXPECTED_NUMBER_OBJECTS
- 描述
- 池的预期对象数量。Ceph 在创建池时分割放置组,以避免对运行时目录分割造成延迟。
- 类型
- 整数
- 必填
- 否
- 默认
-
0
,创建池时不进行分割。
- ERASURE_CODE_PROFILE
- 描述
-
仅针对纠删代码池。使用纠删代码 profile。它必须是 Ceph 配置文件中
osd erasure-code-profile set
变量定义的现有配置集。如需更多信息,请参阅 Erasure Code Profiles 部分。 - 类型
- 字符串
- 必填
- 否
当您创建池时,将放置组数量设置为合理的值,例如 100
。考虑每个 OSD 的放置组总数。放置组的计算代价比较高,因此当您有很多放置组的池时,性能会降低,例如 50 个池,每个放置组有 100 个放置组。减弱的返回点取决于 OSD 主机的电源。
其它资源
有关 计算池 的适当放置组的详细信息,请参阅 每个池计算器的放置组部分和 Ceph 放置组(PG)。
4.4. 设置池配额
您可以为最大字节数和每个池的最大对象数量设置池配额。
语法
ceph osd pool set-quota POOL_NAME [max_objects OBJECT_COUNT] [max_bytes BYTES]
示例
[ceph: root@host01 /]# ceph osd pool set-quota data max_objects 10000
要删除配额,请将其值设为 0
。
in-flight 写入操作可能会短时间内运行池配额,直到 Ceph 在集群中传播池使用量为止。这是正常的行为。在动态写操作中强制执行池配额会带来显著的性能机。
4.5. 删除池
删除池:
语法
ceph osd pool delete POOL_NAME [POOL_NAME --yes-i-really-really-mean-it]
为保护数据,存储管理员默认无法删除池。在删除池前设置 mon_allow_pool_delete
配置选项。
如果池有自己的规则,请考虑在删除池后将其删除。如果池强制为用户自己使用,请考虑在删除池后删除这些用户。
4.6. 重命名池
重命名池:
语法
ceph osd pool rename CURRENT_POOL_NAME NEW_POOL_NAME
如果您重命名池并且具有经过身份验证的用户的每个池功能,您必须更新用户的功能,即使用新的池名称更新用户的功能。
4.7. 迁移池
有时,需要将所有对象从一个池迁移到另一个池。这是在需要更改无法修改特定池中的参数的情况下完成的。例如,需要减少池的 PG 数量。
Ceph 块设备描述的迁移方法比此处记录的迁移方法更高。使用 cppool 不保留所有快照和快照相关的元数据,从而导致数据异常副本。例如,复制 RBD 池不会完全复制镜像。在这种情况下,snaps 不存在,且无法正常工作。cppool 也不会保留某些 librados 用户可能依赖的 user_version
字段。
如果迁移池是必要的,并且您的用户工作负载包含 Ceph 块设备以外的镜像,请继续按照这里介绍的步骤之一。
先决条件
如果使用
rados cppool
命令:- 需要对池进行只读访问。
-
只有当您没有 RBD 镜像及其 snaps 以及 librados 消耗的
user_version
时,才使用此命令。
- 如果使用本地驱动器 RADOS 命令,请验证是否有足够的集群空间可用。随着池复制因子,存在两个、三个或更多的数据副本。
流程
方法一 - 推荐的直接方法
使用 rados cppool
命令复制所有对象。
复制过程中需要对池的只读访问权限。
语法
ceph osd pool create NEW_POOL PG_NUM [ <other new pool parameters> ] rados cppool SOURCE_POOL NEW_POOL ceph osd pool rename SOURCE_POOL NEW_SOURCE_POOL_NAME ceph osd pool rename NEW_POOL SOURCE_POOL
示例
[ceph: root@host01 /]# ceph osd pool create pool1 250 [ceph: root@host01 /]# rados cppool pool2 pool1 [ceph: root@host01 /]# ceph osd pool rename pool2 pool3 [ceph: root@host01 /]# ceph osd pool rename pool1 pool2
方法 2 - 使用本地驱动器
使用
rados export
和rados 导入
命令和一个临时本地目录来保存所有导出的数据。语法
ceph osd pool create NEW_POOL PG_NUM [ <other new pool parameters> ] rados export --create SOURCE_POOL FILE_PATH rados import FILE_PATH NEW_POOL
示例
[ceph: root@host01 /]# ceph osd pool create pool1 250 [ceph: root@host01 /]# rados export --create pool2 <path of export file> [ceph: root@host01 /]# rados import <path of export file> pool1
- 必需。停止到源池的所有 I/O。
必需。重新同步所有修改的对象。
语法
rados export --workers 5 SOURCE_POOL FILE_PATH rados import --workers 5 FILE_PATH NEW_POOL
示例
[ceph: root@host01 /]# rados export --workers 5 pool2 <path of export file> [ceph: root@host01 /]# rados import --workers 5 <path of export file> pool1
4.8. 查看池统计信息
显示池的利用率统计信息:
示例
[ceph: root@host01 /] rados df
4.9. 设置池值
为池设置值:
语法
ceph osd pool set POOL_NAME KEY VALUE
Pool Values 部分列出了您可以设置的所有键值对。
4.10. 获取池值
从池获取值:
语法
ceph osd pool get POOL_NAME KEY
您可以在 Pool Values 部分中查看所有键值对列表。
4.11. 启用客户端应用程序
Red Hat Ceph Storage 为池提供额外的保护,以防止未经授权的客户端将数据写入池。这意味着系统管理员必须以表达方式启用池,以便从 Ceph 块设备、Ceph 对象网关、Ceph Filesystem 或自定义应用接收 I/O 操作。
启用客户端应用程序对池执行 I/O 操作:
语法
ceph osd pool application enable POOL_NAME APP {--yes-i-really-mean-it}
其中 APP
是:
-
cephfs
用于 Ceph 文件系统。 -
rbd
,表示 Ceph 块设备。 -
rgw
用于 Ceph 对象网关。
为自定义应用程序指定不同的 APP
值。
未启用的池将生成 HEALTH_WARN
状态。在这种情况下,ceph health detail -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_', where _APP_ 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 池 init POOL_NAME
初始化 Ceph 块设备的池。
4.12. 禁用客户端应用程序
禁用客户端应用程序对池执行 I/O 操作:
语法
ceph osd pool application disable POOL_NAME APP {--yes-i-really-mean-it}
其中 APP
是:
-
cephfs
用于 Ceph 文件系统。 -
rbd
,表示 Ceph 块设备。 -
rgw
用于 Ceph 对象网关。
为自定义应用程序指定不同的 APP
值。
4.13. 设置应用程序元数据
提供设置描述客户端应用程序属性的键值对的功能。
在池中设置客户端应用程序元数据:
语法
ceph osd pool application set POOL_NAME APP KEY
其中 APP
是:
-
cephfs
用于 Ceph 文件系统。 -
RBD
用于 Ceph 块设备 -
rgw
用于 Ceph 对象网关
为自定义应用程序指定不同的 APP
值。
4.14. 删除应用程序元数据
删除池中的客户端应用程序元数据:
语法
ceph osd pool application rm POOL_NAME APP KEY
其中 APP
是:
-
cephfs
用于 Ceph 文件系统。 -
RBD
用于 Ceph 块设备 -
rgw
用于 Ceph 对象网关
为自定义应用程序指定不同的 APP
值。
4.15. 设置对象副本数量
在复制池中设置对象副本数量:
语法
ceph osd pool set POOL_NAME size NUMBER_OF_REPLICAS
您可以为每个池运行这个命令。
NUMBER_OF_REPLICAS
参数包括对象本身。如果要包含对象和对象总数的两个副本,请指定 3
。
示例
[ceph: root@host01 /]# ceph osd pool set data size 3
对象可能会接受降级模式中的 I/O 操作,其副本数少于 pool size
设置指定的副本。要为 I/O 设置所需的副本数,请使用 min_size
设置。
示例
[ceph: root@host01 /]# ceph osd pool set data min_size 2
这样可确保数据池中没有对象接收的 I/O 少于 min_size
设置指定的副本数。
4.16. 获取对象副本数量
获取对象副本数量:
示例
[ceph: roo@host01 /]# ceph osd dump | grep 'replicated size'
Ceph 列出池,突出显示了 replicated size
属性。默认情况下,Ceph 为一个对象创建两个副本,总共有三个副本,或大小为 3
。
4.17. 池值
以下列表包含您可以设置或获取的键值对。如需更多信息,请参阅 Set Pool Values 和 Getting Pool Values 部分。
- size
- 描述
- 指定池中对象的副本数量。如需了解更多详细信息 ,请参阅设置 Object Replicas 部分。仅适用于复制池。
- 类型
- 整数
- min_size
- 描述
-
指定 I/O 所需的最少副本数。如需了解更多详细信息 ,请参阅设置 Object Replicas 部分。对于纠删代码池,应将其设置为大于
k
的值。如果在k
值下允许 I/O,则在永久 OSD 出现故障时没有冗余,数据将会丢失。如需更多信息,请参阅 纠删代码池概述。 - 类型
- 整数
- crash_replay_interval
- 描述
- 指定允许客户端重播已确认但未提交的请求的秒数。
- 类型
- 整数
- pg-num
- 描述
-
池的放置组总数。有关计算合适的数字的详细信息,请参阅 Red Hat Ceph Storage 配置指南中的 池、放置组和 CRUSH 配置参考 一节。默认值
8
不适用于大多数系统。 - 类型
- 整数
- 必填
- 是。
- 默认
- 8
- pgp-num
- 描述
- 用于放置的放置组总数。这应该等于放置组的总数量,但放置组 分割场景除外。
- 类型
- 整数
- 必填
- 是。若未指定,则获取默认值或 Ceph 配置值。
- 默认
- 8
- 有效范围
-
等于或小于
pg_num
变量指定的内容。
- crush_rule
- 描述
- 用于映射集群中的对象放置的规则。
- 类型
- 字符串
- hashpspool
- 描述
-
在给定池中启用或禁用
HASHPSPOOL
标志。启用此选项后,池散列和放置组映射将更改为改进池和放置组重叠的方式。 - 类型
- 整数
- 有效范围
1
启用标志,0
禁用该标志。重要不要在具有大量 OSD 和数据的集群池中启用此选项。池中的所有放置组都必须重新映射导致数据移动过多。
- fast_read
- 描述
-
在启用这个标志的池中,如果启用了这个标志,读取请求会发出后续读取操作,并等待其接收足够的分片来解码客户端。如果是
jerasure
和isa erasure
plug-ins,当第一个 K 回复返回后,客户端请求会立即使用来自这些回复的数据来提供。这有助于分配一些资源以提高性能。目前,这个标志只支持纠删代码池。 - 类型
- 布尔值
- 默认值
-
0
- allow_ec_overwrites
- 描述
- 写入到纠删代码池都可以更新对象的一部分,因此 Ceph Filesystem 和 Ceph Block Device 可以使用它。
- 类型
- 布尔值
- compression_algorithm
- 描述
-
设置用于 BlueStore 存储后端的内联压缩算法。此设置覆盖
bluestore_compression_algorithm
配置设置。 - 类型
- 字符串
- 有效设置
-
lz4
,snappy
,zlib
,zstd
- compression_mode
- 描述
-
为 BlueStore 存储后端设置内联压缩算法的策略。此设置覆盖
bluestore_compression_mode
配置设置。 - 类型
- 字符串
- 有效设置
-
none
,passive
,aggressive
,force
- compression_min_blob_size
- 描述
-
BlueStore 不压缩比这个大小小的块。此设置覆盖
bluestore_compression_min_blob_size
配置设置。 - 类型
- Unsigned 整数
- compression_max_blob_size
- 描述
-
在压缩数据前,BlueStore 将大于这个大小的块分成较小的
compression_max_blob_size
的 Blob。 - 类型
- Unsigned 整数
- nodelete
- 描述
-
在给定池中设置或取消设置
NODELETE
标志。 - 类型
- 整数
- 有效范围
-
1
设置标志。0
unsets 标志。
- 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 默认使用复制池,这意味着 Ceph 将每个对象从 Primary OSD 节点复制到一个或多个次要 OSD。纠删代码(erasure-coded)池可以减少确保数据持久性所需的磁盘空间量,但它的计算比复制要高得多。
Ceph 存储策略涉及定义数据持久性要求。数据持久性意味着,在丢失一个或多个 OSD 时可以保持数据不会丢失。
Ceph 在池中存储数据,其中有两种池类型:
- 复制
- erasure-coded
纠删代码是一种在 Ceph 存储群集中存储对象的方法,即:该算法将对象分割为数据区块(k
)和编码区块(m
),并将这些区块存储在不同的 OSD 中。
如果 OSD 失败,Ceph 会从其他 OSD 检索剩余的数据(k
)和编码(m
)块,以及纠删代码算法从这些块中恢复对象。
红帽建议 min_size
用于纠删代码池为 K+1
或更高版本,以防止丢失写入和数据。
纠删代码使用存储容量比复制更高效。n-replication 方法维护对象的 n
个副本(在 Ceph 中默认为 3x),而区块则仅维护 k
+ m
个区块。例如,3 个数据和 2 个编码区块使用 1.5 倍的原始对象的存储空间。
纠删代码使用比复制少的存储开销,但纠删代码池使用的内存比访问或恢复对象时使用的 CPU 数要多。当数据存储需要具有持久性和容错能力,但不需要快速读取性能(如冷存储、历史记录等)时,擦除代码具有优势。
有关纠删代码如何在 Ceph 中工作的信息,请参阅 Red Hat Ceph Storage 7 架构指南中的 Ceph Erasure Coding 部分。
Ceph 在使用 k=2 和 m=2 初始化集群时 会创建一个默认 纠删代码配置集,这意味着 Ceph 将通过三个 OSD (k+m == 4)分散对象数据,Ceph 可以在不丢失数据的情况下丢失其中一个 OSD。要了解有关纠删代码性能分析的更多信息,请参阅 Erasure Code Profiles 部分。
将 .rgw.buckets
池配置为纠删代码,所有其他 Ceph 对象网关池都复制,否则尝试创建新存储桶失败,并显示以下错误:
set_req_state_err err_no=95 resorting to 500
这样做的原因是,纠删代码池不支持 omap
操作,某些 Ceph Object Gateway 元数据池需要 omap
支持。
5.1. 创建纠删代码池示例
创建纠删代码池并指定放置组。ceph osd pool create
命令会创建一个带有 default 配置集的纠删代码池,除非指定了另一个配置集。配置集通过设置两个参数 k
和 m
来定义数据的冗余性。这些参数定义数据被分割的区块数量,并创建编码区块数量。
最简单的纠删代码池等同于 RAID5,且至少需要四个主机。您可以创建一个带有 2+2 配置集的纠删代码池。
流程
在带有 2+2 配置的四个节点上为纠删代码池设置以下配置。
语法
ceph config set mon mon_osd_down_out_subtree_limit host ceph config set osd osd_async_recovery_min_cost 1099511627776
重要通常不需要纠删代码池。
重要async 恢复成本是副本后面的 PG 日志条目数以及缺失的对象数量。
osd_target_pg_log_entries_per_osd
是30000
。因此,具有单个 PG 的 OSD 可能具有30000
条目。由于osd_async_recovery_min_cost
是 64 位整数,因此将带有 2+2 配置的 EC 池的osd_async_recovery_min_cost
的值设置为1099511627776
。注意对于具有四个节点的 EC 集群,K+M 的值为 2+2。如果节点完全失败,它不会恢复为四个块,且只有三个节点可用。当您将
mon_osd_down_out_subtree_limit
的值设置为host
时,它会在主机停机场景中阻止 OSD 标记为 out,因此防止数据重新平衡,并等待节点再次启动。对于带有 2+2 配置的纠删代码池,请设置配置集。
语法
ceph osd erasure-code-profile set ec22 k=2 m=2 crush-failure-domain=host
示例
[ceph: root@host01 /]# ceph osd erasure-code-profile set ec22 k=2 m=2 crush-failure-domain=host Pool : ceph osd pool create test-ec-22 erasure ec22
创建纠删代码池。
示例
[ceph: root@host01 /]# ceph osd pool create ecpool 32 32 erasure pool 'ecpool' created $ echo ABCDEFGHI | rados --pool ecpool put NYAN - $ rados --pool ecpool get NYAN - ABCDEFGHI
32 是放置组的数量。
5.2. 纠删代码 profile
Ceph 使用 配置集 定义一个纠删代码池。Ceph 在创建纠删代码池和关联的 CRUSH 规则时使用配置集。
Ceph 在初始化集群时创建默认纠删代码配置集,它提供与复制池中的两个副本相同的冗余级别。此默认配置集定义 k=2 和 m=2,这意味着 Ceph 将对象数据分散到四个 OSD (k+m=4),Ceph 可以在不丢失数据的情况下丢失其中一个 OSD。EC2+2 需要最少部署 4 个节点(推荐 5 个节点),并可以临时丢失 1 个 OSD 节点。
使用以下命令显示默认配置集:
$ ceph osd erasure-code-profile get default k=2 m=2 plugin=jerasure technique=reed_sol_van
您可以创建新配置集来提高冗余,而不增加原始存储要求。例如,一个具有 k=8 和 m=4 的配置集,可以丢失四个(m=4)OSD,这通过在 12 个 (k+m=12) OSD 中分布一个对象实现。Ceph 将对象分成 8 个块,并计算 4 个编码区块来进行恢复。例如,如果对象大小为 8 MB,每个数据块都是 1 MB,每个编码区块的大小也与 1 MB 相同。即使四个 OSD 同时失败,对象也不会丢失。
配置集最重要的参数是 k、m 和 crush-failure-domain,因为它们定义存储开销和数据持久性。
选择正确的配置集非常重要,因为您创建池后无法更改配置集。若要修改配置文件,您必须创建一个具有不同配置文件的新池,并将对象从旧池中迁移到新池中。
例如,如果所需的架构需要可以丢失两个机架,且存储开销为 40% 的开销,则可以定义以下配置集:
$ 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
主 OSD 将 NYAN 对象分成四个 (k=4) 数据块,并创建两个额外的块 (m=2)。m 的值定义可以同时丢失 OSD 的数量,而不会丢失任何数据。crush-failure-domain=rack 将创建一个 CRUSH 规则,以确保在同一机架中不会存储两个块。
红帽支持对 k 和 m 的以下 jerasure 编码值:
- k=8 m=3
- k=8 m=4
- k=4 m=2
如果 OSD 数量丢失等于编码区块数(m
),则灾难恢复池中的某些放置组将进入不完整的状态。如果丢失的 OSD 数量小于 m
,则任何放置组将处于不完整的状态。在这两种情况下,不会发生数据丢失。如果放置组处于 incomplete 状态,则暂时减少纠删代码池的 min_size
允许恢复。
5.2.1. 设置 OSD erasure-code-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]
其中:
- 目录
- 描述
- 设置载入 code 插件的目录名称。
- 类型
- 字符串
- 必填
- No.
- 默认
-
/usr/lib/ceph/erasure-code
- plugin
- 描述
- 使用纠删代码插件计算编码区块并恢复缺少的块。详情请查看 Erasure Code 插件 部分。
- 类型
- 字符串
- 必填
- No.
- 默认
-
Jerasure
- stripe_unit
- 描述
-
每个条带的数据块中的数据量。例如,带有 2 个数据块和
stripe_unit=4K
的配置集会将范围 0-4K 置于块 0 中,将 4K-8K 置于块 1 中,8K-12K 再次置于块 0 中。这应该是 4K 的倍数以获得最佳性能。创建池时,从 monitor 配置选项osd_pool_erasure_code_stripe_unit
中获取了默认值。使用这个配置集的池的 stripe_width 将是这个 stripe_unit 的数据区块数乘以这个stripe_unit
。 - 类型
- 字符串
- 必填
- No.
- 默认
-
4K
- crush-device-class
- 描述
-
设备类,如
hdd
或ssd
。 - 类型
- 字符串
- 必填
- 否
- 默认
-
none
,这意味着 CRUSH 使用所有设备,而不需要考虑类型。
- crush-failure-domain
- 描述
-
故障域,如
host
或rack
。 - 类型
- 字符串
- 必填
- 否
- 默认
-
主机
- key
- 描述
- 剩余的键值对的语义由退出代码插件定义。
- 类型
- 字符串
- 必填
- No.
- --force
- 描述
- 按名称覆盖现有配置集。
- 类型
- 字符串
- 必填
- No.
5.2.2. 删除 OSD erasure-code-profile
删除纠删代码 profile:
语法
ceph osd erasure-code-profile rm RULE_NAME
如果池引用配置集,则删除会失败。
使用 osd erasure-code-profile rm
命令删除纠删代码 profile 不会自动删除与纠删代码配置集关联的 CRUSH 规则。红帽建议使用 ceph osd crush rule remove RULE_NAME
命令手动删除关联的 CRUSH 规则,以避免意外行为。
5.2.3. 获取 OSD erasure-code-profile
显示纠删代码池配置集:
语法
ceph osd erasure-code-profile get NAME
5.2.4. 列出 OSD erasure-code-profile
列出所有纠删代码 profile 的名称:
语法
ceph osd erasure-code-profile ls
5.3. 使用 Overwrites 的纠删代码
默认情况下,纠删代码池仅适用于 Ceph 对象网关,后者执行完整的对象写入和附加。
使用带有覆盖的纠删代码池允许 Ceph 块设备,CephFS 将其数据存储在纠删代码池中:
语法
ceph osd pool set ERASURE_CODED_POOL_NAME allow_ec_overwrites true
示例
[ceph: root@host01 /]# ceph osd pool set ec_pool allow_ec_overwrites true
启用带有覆盖的纠删代码池只能驻留在使用 BlueStore OSD 的池中。因为 BlueStore 的校验和用于在深度清理过程中检测位 rot 或其他崩溃。
纠删代码池不支持 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
示例
[ceph: root@host01 /]# rbd create --size 1G --data-pool ec_pool rep_pool/image01
如果将纠删代码池用于 CephFS,那么必须在文件布局中设置覆盖。
5.4. 纠删代码插件
Ceph 支持通过插件架构进行评分码,这意味着您可以使用不同类型的算法创建纠删代码池。Ceph 支持 Jerasure。
5.4.1. 使用 jerasure 纠删代码插件创建一个新的纠删代码配置集
jerasure 插件是最通用的且灵活的插件。也是 Ceph 纠删代码池的默认设置。
jerasure 插件封装 JerasureH 库。有关参数的详情,请查看 jerasure 文档。
要使用 jerasure 插件创建新的纠删代码配置集,请运行以下命令:
语法
ceph osd erasure-code-profile set NAME \ plugin=jerasure \ k=DATA_CHUNKS \ m=DATA_CHUNKS \ technique=TECHNIQUE \ [crush-root=ROOT] \ [crush-failure-domain=BUCKET_TYPE] \ [directory=DIRECTORY] \ [--force]
其中:
- k
- 描述
- 每个对象被分成 data-chunks 部分,各自存储在不同的 OSD 上。
- 类型
- 整数
- 必填
- 是。
- 示例
-
4
- m
- 描述
- 每个对象 的计算编码区块,并将其存储在不同的 OSD 中。编码区块数也是可以停机的 OSD 的数量,而不丢失数据。
- 类型
- 整数
- 必填
- 是。
- 示例
- 2
- technique
- 描述
- reed_sol_van 更灵活的技术是 reed_sol_van ;它足以设置 k 和 m。cauchy_good 技术可能会更快,但您需要仔细选择 packetsize。所有 reed_sol_r6_op,liberation,blaum_roth,liber8tion 是 RAID6 等效的,它们只能使用 m=2 配置。
- 类型
- 字符串
- 必填
- No.
- 有效设置
-
reed_sol_van
reed_sol_r6_op
cauchy_orig
cauchy_good
liberation
blaum_roth
liber8tion
- 默认
-
reed_sol_van
- packetsize
- 描述
- 编码将一次对 字节数 的数据包进行。选择正确的数据包大小比较困难。jerasure 文档包含有关此主题的广泛信息。
- 类型
- 整数
- 必填
- No.
- 默认
-
2048
- crush-root
- 描述
- 用于规则第一步的 CRUSH bucket 的名称。例如 ,默认为。
- 类型
- 字符串
- 必填
- No.
- 默认
- default
- crush-failure-domain
- 描述
- 确定在具有相同故障域的存储桶中没有两个块。例如,如果故障域没有将两个块存储在同一主机上。它用于创建规则步骤,如 step chooseleaf host。
- 类型
- 字符串
- 必填
- No.
- 默认
-
主机
- 目录
- 描述
- 设置载入 code 插件的目录名称。
- 类型
- 字符串
- 必填
- No.
- 默认
-
/usr/lib/ceph/erasure-code
- --force
- 描述
- 按名称覆盖现有配置集。
- 类型
- 字符串
- 必填
- No.
5.4.2. 控制 CRUSH 放置
默认 CRUSH 规则提供位于不同主机上的 OSD。例如:
chunk nr 01234567 step 1 _cDD_cDD step 2 cDDD____ step 3 ____cDDD
需要 8 个 OSD,每个块对应一个。如果主机位于两个相邻的机架中,则前四个块可以放在第一个机架中,后 4 个放在第二个机架中。如果恢复单个 OSD 丢失,不需要在两个机架之间使用带宽。
例如:
crush-steps='[ [ "choose", "rack", 2 ], [ "chooseleaf", "host", 4 ] ]'
创建一个规则,用于选择两个类型为 rack 的 CRUSH bucket,各自选择四个 OSD,它们各自位于主机类型的不同 bucket 中。
也可以手动创建该规则以进行更精细的控制。