查看原文
其他

学习 Ceph 运维操作 —— CRUSH MAP

李航 twt企业IT社区 2022-07-03

1. 介绍

CRUSH 算法通过计算数据存储位置来确定如何存储和检索。 CRUSH 授权 Ceph 客户端直接连接 OSD,而非通过一个中央服务器或代理。数据存储、检索算法的使用,使 Ceph 避免了单点故障、性能瓶颈、和伸缩的物理限制。

CRUSH 需要一张集群的 Map,且使用 CRUSH Map 把数据伪随机地、尽量平均地分布到整个集群的 OSD 里。

CRUSH Map 包含 OSD 列表、把设备汇聚为物理位置的“桶”列表、和指示 CRUSH 如何复制存储池里的数据的规则列表。

完全手动管理 CRUSH Map 也是可能的,在配置文件中设定:

osd crush update on start = false


2. 操作 CRUSH Map

2.1 提取CRUSH Map

#提取最新crush图#ceph osd getcrushmap -o {compiled-crushmap-filename}

$ ceph osd getcrushmap -o /tmp/crush

#反编译crush图

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

$ crushtool -d /tmp/crush -o /tmp/decompiled_crush

2.2 注入CRUSH Map

#编译crush图#crushtool -c {decompiled-crush-map-filename} -o {compiled-crush-map-filename}

$ crushtool -c /tmp/decompiled_crush -o /tmp/crush_new

#注入crush图

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

$ ceph osd setcrushmap -i /tmp/crush_new


3. CRUSH Map 参数

CRUSH Map 主要有 4 个段落。

  1. 设备:由任意对象存储设备组成,即对应一个 ceph-osd进程的存储器。 Ceph 配置文件里的每个 OSD 都应该有一个设备。

  2. 桶类型: 定义了 CRUSH 分级结构里要用的桶类型( types ),桶由逐级汇聚的存储位置(如行、机柜、机箱、主机等等)及其权重组成。

  3. 桶实例: 定义了桶类型后,还必须声明主机的桶类型、以及规划的其它故障域。

  4. 规则: 由选择桶的方法组成。

3.1 CRUSH Map 之设备

为把 PG 映射到 OSD , CRUSH Map 需要 OSD 列表(即配置文件所定义的 OSD 守护进程名称),所以它们首先出现在 CRUSH Map 里。

要在 CRUSH Map 里声明一个设备,在设备列表后面新建一行,输入 device 、之后是唯一的数字 ID 、之后是相应的 ceph-osd 守护进程实例名字。

# devices

device {num} {osd.name}

#例如:

# devices

device 0 osd.0

device 1 osd.1

device 2 osd.2

device 3 osd.3

3.2 CRUSH Map 之桶类型

CRUSH Map 里的第二个列表定义了 bucket (桶)类型,桶简化了节点和叶子层次。节点(或非叶子)桶在分级结构里一般表示物理位置,节点汇聚了其它节点或叶子,叶桶表示 ceph-osd 守护进程及其对应的存储媒体。

要往 CRUSH Map 中增加一种 bucket 类型,在现有桶类型列表下方新增一行,输入 type 、之后是惟一数字 ID 和一个桶名。按惯例,会有一个叶子桶为 type 0 ,然而你可以指定任何名字(如 osd 、 disk 、 drive 、 storage 等等):

# types

type {num} {bucket-name}

#例如:

# types

type 0 osd

type 1 host

type 2 chassis

type 3 rack

type 4 row

type 5 pdu

type 6 pod

type 7 room

type 8 datacenter

type 9 region

type 10 root

3.3 CRUSH Map 之桶层次

CRUSH 算法根据各设备的权重、大致统一的概率把数据对象分布到存储设备中。 CRUSH 根据你定义的集群运行图分布对象及其副本,CRUSH Map 表达了可用存储设备以及包含它们的逻辑单元。

要把 PG 映射到跨故障域的 OSD ,一个 CRUSH Map 需定义一系列分级桶类型(即现有 CRUSH Map 的 # type 下)。

创建桶分级结构的目的是按故障域隔离叶子节点,像主机、机箱、机柜、电力分配单元、机群、行、房间、和数据中心。

除了表示叶子节点的 OSD ,其它分级结构都是任意的,你可以按需定义。

声明一个桶实例时,你必须指定其类型、惟一名称(字符串)、惟一负整数 ID (可选)、指定和各条目总容量/能力相关的权重、指定桶算法(通常是 straw )、和哈希(通常为 0 ,表示哈希算法 rjenkins1 )。一个桶可以包含一到多个条目,这些条目可以由节点桶或叶子组成,它们可以有个权重用来反映条目的相对权重。

你可以按下列语法声明一个节点桶:

例如,我们可以定义两个主机桶和一个机柜桶,机柜桶包含两个主机桶, OSD 被声明为主机桶内的条目

3.3.1 调整桶的权重

Ceph 用双精度类型数据表示桶权重。权重和设备容量不同,我们建议用 1.00 作为 1TB 存储设备的相对权重,这样 0.5 的权重大概代表 500GB 、3.00 大概代表 3TB 。较高级桶的权重是所有叶子桶的权重之和。

一个桶的权重是一维的,你也可以计算条目权重来反映存储设备性能。例如,如果你有很多 1TB 的硬盘,其中一些数据传输速率相对低、其他的数据传输率相对高,即使它们容量相同,也应该设置不同的权重(如给吞吐量较低的硬盘设置权重 0.8 ,较高的设置 1.20 )。

3.4 CRUSH Map 之规则

CRUSH Map 支持“ CRUSH 规则”的概念,用以确定一个存储池里数据的分布。CRUSH 规则定义了归置和复制策略、或分布策略,用它可以规定 CRUSH 如何放置对象副本。对大型集群来说,你可能创建很多存储池,且每个存储池都有它自己的 CRUSH 规则集和规则。

默认的 CRUSH Map 里,每个存储池有一条规则、一个规则集被分配到每个默认存储池。

注意: 大多数情况下,你都不需要修改默认规则。新创建存储池的默认规则集是 0。

规则格式如下:

参数说明:

1.ruleset:区分一条规则属于某个规则集的手段。给存储池设置规则集后激活。

2.type:规则类型,目前仅支持 replicated 和 erasure ,默认是 replicated 。

3.min_size:可以选择此规则的存储池最小副本数。

4.max_size:可以选择此规则的存储池最大副本数。

5.step take <bucket-name>:选取起始的桶名,并迭代到树底。

6.step choose firstn {num} type {bucket-type}:选取指定类型桶的数量,这个数字通常是存储池的副本数(即 pool size )。如果 {num} == 0 , 选择 pool-num-replicas 个桶(所有可用的);如果 {num} > 0 && < pool-num-replicas ,就选择那么多的桶;如果 {num} < 0 ,它意味着选择 pool-num-replicas - {num} 个桶。

7.step chooseleaf firstn {num} type {bucket-type}:选择 {bucket-type} 类型的桶集合,并从各桶的子树里选择一个叶子节点。桶集合的数量通常是存储池的副本数(即 pool size )。如果 {num} == 0 ,选择 pool-num-replicas 个桶(所有可用的);如果 {num} > 0 && < pool-num-replicas ,就选择那么多的桶;如果 {num} < 0 ,它意味着选择 pool-num-replicas - {num}个桶。

8.step emit:输出当前值并清空堆栈。通常用于规则末尾,也适用于相同规则应用到不同树的情况。


4. 主亲和性

某个 Ceph 客户端读写数据时,总是连接 acting set 里的主 OSD (如 [2, 3, 4] 中, osd.2 是主的)。

有时候某个 OSD 与其它的相比并不适合做主 OSD (比如其硬盘慢、或控制器慢)。最大化硬件利用率时为防止性能瓶颈(特别是读操作),你可以调整 OSD 的主亲和性,这样 CRUSH 就尽量不把它用作 acting set 里的主 OSD 了。

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

主亲和性默认为 1 (就是说此 OSD 可作为主 OSD )。此值合法范围为 0-1 ,其中 0 意为此 OSD 不能用作主的, 1 意为 OSD 可用作主的。

此权重 < 1 时, CRUSH 选择主 OSD 时选中它的可能性就较低。

5. 增加/移动 OSD

要增加或移动在线集群里 OSD 所对应的 CRUSH Map 条目,执行 ceph osd crush set 命令。

crush set {id-or-name} {weight} {bucket-type}={bucket-name} [{bucket-type}={bucket-name} ...]

6. 调整 OSD 的 CRUSH 权重

要调整在线集群中某个 OSD 的 CRUSH 权重,执行命令:

ceph osd crush reweight {name} {weight}

7. 删除 OSD

要从在线集群里把某个 OSD 彻底踢出 CRUSH Map,或仅踢出某个指定位置的 OSD,执行命令:

  1. #从 crush map 中删除一个 osd

  2. $ ceph osd crush rm osd.0

8. 增加桶

要在运行集群的 CRUSH Map 中新建一个桶,用 ceph osd crush add-bucket 命令:

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

9. 移动桶

要把一个桶移动到 CRUSH Map 里的不同位置,执行命令:

move {bucket-name} {bucket-type}={bucket-name} [{bucket-type}={bucket-name} ...]

10. 删除桶

要把一个桶从 CRUSH Map 的分级结构中删除,可用此命令:

remove {bucket-name}

注意:从 CRUSH 分级结构里删除时必须是空桶。


本文作者:李航,多年的底层开发经验,在高性能nginx开发和分布式缓存redis cluster有着丰富的经验,目前从事Ceph工作两年左右。 先后在58同城、汽车之家、优酷土豆集团工作。 目前供职于滴滴基础平台运维部 负责分布式Ceph集群开发及运维等工作。 个人主要关注的技术领域:高性能Nginx开发、分布式缓存、分布式存储。



相关阅读:

Ceph 原理、架构等知识梳理总结 | 干货分享

学习 Ceph 运维操作 —— MON


点击阅读原文关注社区  分布式存储技术主题 ,将会不断更新优质资料、文章,您也可以前往提出疑难问题,与同行切磋交流。


下载 twt 社区客户端 APP

与更多同行在一起

高手随时解答你的疑难问题

轻松订阅各领域技术主题

浏览下载最新文章资料


长按识别二维码即可下载

或到应用商店搜索“twt”


长按二维码关注公众号

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存