Ceph 集群中由 mon 服务器维护着的五种运行图:
- Monitor map:监视器运行图(监视 mon 进程的状态,哪个是主、哪个是从);
- OSD map:OSD 运行图(各个 OSD 的状态,每个 OSD 会汇报自己的状态并且还会感知其它 OSD 的状态,如果一个 OSD 被其它 OSD 进程判定为 down,则在 20 秒后该 OSD 会被踢出集群);
- PG map:PG 运行图(一个存储池有哪些 PG,每个 PG 又包含哪些 OSD);
- Crush (Controllers replication under scalable hashing,可控的、可复制的、可伸缩的一致性 hash 算法) map:
crush 运行图,当新建存储池时会基于 OSD map 创建出合适的 PG 组合列表用于存储数据; - MDS map:cephfs metadata 运行图;
一个文件向 Ceph 集群写入时,首先这个文件会被拆分为多个数据对象(object),然后根据每个 object 的 oid 来选择一个 PG(
hash(oid)%pg数量
)。CRUSH 会根据当前的运行图返回 pg 内的最新的 OSD 组合,每个 object 包含的数据就可以向主 OSD 写,然后同步到副本 OSD 最后完成数据的写入。Crush 算法目前有 5 种算法来实现节点的选择,包括 Uniform、List、Tree、Straw、Straw2, 早期版本使用的是 Ceph 项目的发起者发明的算法 Straw,目前已经发展到 Straw2 版本。
PG 与 OSD 的映射调整
默认情况下,Crush 算法自行对创建的 pool 中的 PG 分配 OSD,但是可以手动基于权重设置 Crush 算法分配数据的倾向性,比如 1T 的磁盘权重是 1,2T 的就是 2。
虽然可以调整,但还是推荐使用相同大小的设备以便于维护。
查看当前状态
weight 表示设备(device)的容量相对值,比如 1TB 对应 1.00,那么 500G 的 OSD 的 weight 就应该是 0.5,weight 可以基于磁盘空间大小来分配 PG 的数量,让 Crush 算法尽可能往磁盘空间大的 OSD 多分配 OSD,往磁盘空间小的 OSD 分配较少的 OSD。
reweight 参数的目的是重新平衡 Ceph 的 CRUSH 算法随机分配的 PG,默认的分配策略是随机概率上的均衡,即使 OSD 都是一样的磁盘空间也会产生一 此 PG 分布不均匀的情况, 此时可以通过调整 reweight 参数,让 Ceph 集群立即重新平衡当前磁盘的 PG,以达到数据均衡分布的目的。reweight 通常在 PG 已经分配完成,要在 Ceph 集群重新平衡 PG 的分布的时候使用。
可以通过如下方式来查看各 OSD 的 weight 和 reweight 参数:
$ ceph osd df
ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE VAR PGS STATUS
0 hdd 0.01949 1.00000 20 GiB 16 MiB 1.8 MiB 0 B 14 MiB 20 GiB 0.08 1.00 88 up
1 hdd 0.01949 1.00000 20 GiB 16 MiB 1.8 MiB 0 B 14 MiB 20 GiB 0.08 1.00 81 up
2 hdd 0.01949 1.00000 20 GiB 16 MiB 1.8 MiB 0 B 14 MiB 20 GiB 0.08 1.00 87 up
3 hdd 0.01949 1.00000 20 GiB 16 MiB 1.8 MiB 0 B 14 MiB 20 GiB 0.08 1.00 85 up
4 hdd 0.01949 1.00000 20 GiB 16 MiB 1.8 MiB 0 B 14 MiB 20 GiB 0.08 1.00 84 up
5 hdd 0.01949 1.00000 20 GiB 16 MiB 1.8 MiB 0 B 14 MiB 20 GiB 0.08 1.00 87 up
6 hdd 0.01949 1.00000 20 GiB 16 MiB 1.8 MiB 0 B 14 MiB 20 GiB 0.08 1.00 82 up
7 hdd 0.01949 1.00000 20 GiB 16 MiB 1.8 MiB 0 B 14 MiB 20 GiB 0.08 1.00 87 up
8 hdd 0.01949 1.00000 20 GiB 16 MiB 1.8 MiB 0 B 14 MiB 20 GiB 0.08 1.00 87 up
TOTAL 180 GiB 142 MiB 16 MiB 8.5 KiB 125 MiB 180 GiB 0.08
MIN/MAX VAR: 1.00/1.00 STDDEV: 0
修改 weight
以修改 ID 为 5 的 OSD 的权重为 1.5 为例:
$ ceph osd crush reweight osd.5 1.5
reweighted item id 5 name 'osd.5' to 1.5 in crush map
在执行完这个操作后,Ceph 会立即执行数据的均衡(重新分配 PG),所以这个操作需要在业务空闲期间执行以降低对业务的影响。
修改 reweight
OSD 的 reweight 值默认为 1,值可以调整,范围在 0~1 之间,值越低则落在对应 OSD 的 PG越少,如果调整了任何一个 OSD 的 reweight 值,那么 OSD 的 PG 会立即和其它 OSD 进行重新平衡,即数据重新进行分配。它主要用于当某个 OSD 的 PG 相对较多需要降低其 PG 数量的场景。
以修改 ID 为 3 的 OSD 的 reweight 值为 0.5 为例:
$ ceph osd reweight 3 0.5
reweighted osd.3 to 0.5 (8000)
经过上述两轮调整,现在就可以明显看到调整过的 OSD 和未调整的 OSD 上落到的 PG 数量差异:
$ ceph osd df
ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE VAR PGS STATUS
0 hdd 0.01949 1.00000 20 GiB 17 MiB 1.9 MiB 0 B 15 MiB 20 GiB 0.08 1.00 96 up
1 hdd 0.01949 1.00000 20 GiB 17 MiB 1.9 MiB 0 B 15 MiB 20 GiB 0.08 1.00 77 up
2 hdd 0.01949 1.00000 20 GiB 17 MiB 1.9 MiB 0 B 15 MiB 20 GiB 0.08 1.00 93 up
3 hdd 0.01949 0.50000 20 GiB 16 MiB 1.9 MiB 0 B 14 MiB 20 GiB 0.08 0.98 15 up
4 hdd 0.01949 1.00000 20 GiB 16 MiB 1.9 MiB 0 B 14 MiB 20 GiB 0.08 0.98 8 up
5 hdd 1.50000 1.00000 20 GiB 17 MiB 1.9 MiB 0 B 15 MiB 20 GiB 0.08 1.04 247 up
6 hdd 0.01949 1.00000 20 GiB 17 MiB 1.9 MiB 0 B 15 MiB 20 GiB 0.08 1.00 88 up
7 hdd 0.01949 1.00000 20 GiB 17 MiB 1.9 MiB 0 B 15 MiB 20 GiB 0.08 1.00 78 up
8 hdd 0.01949 1.00000 20 GiB 17 MiB 1.9 MiB 0 B 15 MiB 20 GiB 0.08 1.00 66 up
TOTAL 180 GiB 150 MiB 17 MiB 8.5 KiB 132 MiB 180 GiB 0.08
MIN/MAX VAR: 0.98/1.04 STDDEV: 0.00
Crush 运行图管理
Crush 运行图无法直接进行管理操作,需要通过工具将 Ceph 的 Crush 运行图配置导出进行编辑,然后导入以实现修改操作。
导出二进制
导出的 Crush 运行图为二进制格式,无法通过文本编辑器直接打开。
# 创建一个目录保存导出的文件
$ mkdir /data/ceph -p
# 执行导出操作
$ ceph osd getcrushmap -o /data/ceph/crushmap
26
转换文本格式
可以使用 crushtool
将导出的 Crush 运行图二进制文件转换成文本格式再进行查看与编辑。
# 安装包含 crushtool 的包
$ apt install ceph-base -y
# 执行转换操作
$ crushtool -d /data/ceph/crushmap > crushmap.txt
此时就可以查看当前 Crush map 的配置了:
$ cat /data/ceph/crushmap.txt
# begin crush map
# crush map 可调整的参数
tunable choose_local_tries 0
tunable choose_local_fallback_tries 0
tunable choose_total_tries 50
tunable chooseleaf_descend_once 1
tunable chooseleaf_vary_r 1
tunable chooseleaf_stable 1
tunable straw_calc_version 1
tunable allowed_bucket_algs 54
# devices
# 当前存储设备列表
device 0 osd.0 class hdd
device 1 osd.1 class hdd
device 2 osd.2 class hdd
device 3 osd.3 class hdd
device 4 osd.4 class hdd
device 5 osd.5 class hdd
device 6 osd.6 class hdd
device 7 osd.7 class hdd
device 8 osd.8 class hdd
# types
# 当前支持的 bucket 类型
type 0 osd # 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 # 一个数据中心或 IDS
type 9 zone # 一个区域,比如 AWS 宁夏中卫数据中心
type 10 region # 地域,比如亚洲、欧洲
type 11 root # 最顶层,根
# buckets
host ceph-node1 { # 类型 host,名称为 ceph-node1
# ceph 生成的 host id,非必要不要改
id -3 # do not change unnecessarily
# 设备类型 id,也不需要修改
id -4 class hdd # do not change unnecessarily
# weight 0.058
alg straw2 # crush 算法,管理 osd 角色
hash 0 # rjenkins1 指定 hash 算法,0 表示选择 rjenkins1 这种 hash 算法
# osd 权重比例,crush 会自动根据磁盘容量计算
item osd.0 weight 0.019
item osd.1 weight 0.019
item osd.2 weight 0.019
}
host ceph-node2 {
id -5 # do not change unnecessarily
id -6 class hdd # do not change unnecessarily
# weight 1.539
alg straw2
hash 0 # rjenkins1
item osd.3 weight 0.019
item osd.4 weight 0.019
item osd.5 weight 1.500
}
host ceph-node3 {
id -7 # do not change unnecessarily
id -8 class hdd # do not change unnecessarily
# weight 0.058
alg straw2
hash 0 # rjenkins1
item osd.6 weight 0.019
item osd.7 weight 0.019
item osd.8 weight 0.019
}
root default {
id -1 # do not change unnecessarily
id -2 class hdd # do not change unnecessarily
# weight 1.656
alg straw2
hash 0 # rjenkins1
item ceph-node1 weight 0.058
item ceph-node2 weight 1.539
item ceph-node3 weight 0.058
}
# rules
rule replicated_rule { # 副本池的默认配置
id 0
type replicate
min_size 1
max_size 10 # 默认最大副本为 10
step take default # 基于上面定义的 default 规则来分配 OSD
step chooseleaf firstn 0 type host # 选择主机,故障域类型为主机
step emit # 弹出配置即返回给客户端
}
# end crush map
导入配置
如果对上面的文本文件做了修改,需要将其转换回二进制格式才能够导入集群。
为演示效果我这里将 replicated_rule
的 max_size
修改为 5
,然后执行转换操作:
$ crushtool -c /data/ceph/crushmap.txt -o /data/ceph/newcrushmap
导入的运行图会立即覆盖原有的运行图并立即生效:
$ ceph osd setcrushmap -i /data/ceph/newcrushmap
27
验证新运行图是否生效:
$ ceph osd crush rule dump
[
{
"rule_id": 0,
"rule_name": "replicated_rule",
"ruleset": 0,
"type": 1,
"min_size": 1,
"max_size": 5,
"steps": [
{
"op": "take",
"item": -1,
"item_name": "default"
},
{
"op": "chooseleaf_firstn",
"num": 0,
"type": "host"
},
{
"op": "emit"
}
]
}
]
数据分类管理
Ceph Crush 算法分配 PG 的时候可以将 PG 分配到不同主机的 OSD 上,以实现以主机为单位的高可用,这也是默认机制。但是该方式无法保证不同 PG 位于不同机柜或者机房的主机,如果要实现基于机柜或者是更高级的 IDC 等方式的数据高可用,或者要实现 A 项目的数据在 SSD, B 项目的数据在机械盘此类功能,则需要导出 Crush 运行图并手动编辑配置,之后再导人并覆盖原有的 Crush 运行图。
修改配置
修改导出的 Crushmap 文本文件,在其中添加如下内容:
host ceph-node1-ssd {
id -13 # do not change unnecessarily
id -14 class hdd # do not change unnecessarily
alg straw2
hash 0 # rjenkins1
item osd.2 weight 0.019
}
host ceph-node2-ssd {
id -15 # do not change unnecessarily
id -16 class hdd # do not change unnecessarily
alg straw2
hash 0 # rjenkins1
item osd.5 weight 0.019
}
host ceph-node3-ssd {
id -17 # do not change unnecessarily
id -18 class hdd # do not change unnecessarily
alg straw2
hash 0 # rjenkins1
item osd.8 weight 0.019
}
root ssd {
id -11 # do not change unnecessarily
id -12 class hdd # do not change unnecessarily
alg straw2
hash 0 # rjenkins1
item ceph-node1-ssd weight 0.058
item ceph-node2-ssd weight 0.058
item ceph-node3-ssd weight 0.058
}
rule ssd_replicated_rule {
id 1
type replicated
min_size 1
max_size 5
step take ssd
step chooseleaf firstn 0 type host
step emit
}
上述配置将 ID 为 2、5、8 的三个 OSD 当做 SSD 盘,单独创建一个名为 ssd_replicated_rule
的 rule 关联对应几块磁盘所在主机。所以后续使用该 rule 创建的存储池的 PG 仅会分配在这几个使用 SSD 盘的 OSD。
执行导入操作:
$ crushtool -c /data/ceph/crushmap.txt -o /data/ceph/crushmap-ssd
$ ceph osd setcrushmap -i /data/ceph/crushmap-ssd
28
此时查看 OSD 结构可以看到两个 root 节点:
$ ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-11 0.17400 root ssd
-13 0.05800 host ceph-node1-ssd
2 hdd 0.01900 osd.2 up 1.00000 1.00000
-15 0.05800 host ceph-node2-ssd
5 hdd 0.01900 osd.5 up 1.00000 1.00000
-17 0.05800 host ceph-node3-ssd
8 hdd 0.01900 osd.8 up 1.00000 1.00000
-1 1.65498 root default
-3 0.05800 host ceph-node1
0 hdd 0.01900 osd.0 up 1.00000 1.00000
1 hdd 0.01900 osd.1 up 1.00000 1.00000
2 hdd 0.01900 osd.2 up 1.00000 1.00000
-5 1.53899 host ceph-node2
3 hdd 0.01900 osd.3 up 0.50000 1.00000
4 hdd 0.01900 osd.4 up 1.00000 1.00000
5 hdd 1.50000 osd.5 up 1.00000 1.00000
-7 0.05800 host ceph-node3
6 hdd 0.01900 osd.6 up 1.00000 1.00000
7 hdd 0.01900 osd.7 up 1.00000 1.00000
8 hdd 0.01900 osd.8 up 1.00000 1.00000
测试创建存储池
指定使用 ssd_replicated_rule
rule 来创建存储池:
$ ceph osd pool create ssd-pool 32 32 ssd_replicated_rule
pool 'ssd-pool' created
查看 PGP 的状态来验证仅使用了 SSD OSD:
$ ceph pg ls-by-pool ssd-pool | awk '{print $1,$2,$15}'
PG OBJECTS ACTING
2.0 0 [5,2,8]p5
2.1 0 [5,8,2]p5
2.2 0 [5,2,8]p5
2.3 0 [2,8,5]p2
2.4 0 [5,8,2]p5
2.5 0 [2,5,8]p2
2.6 0 [8,2,5]p8
2.7 0 [5,8,2]p5
2.8 0 [8,2,5]p8
2.9 0 [5,8,2]p5
2.a 0 [2,8,5]p2
2.b 0 [2,8,5]p2
2.c 0 [5,8,2]p5
2.d 0 [2,8,5]p2
2.e 0 [8,5,2]p8
2.f 0 [5,8,2]p5
2.10 0 [8,2,5]p8
2.11 0 [2,5,8]p2
2.12 0 [8,5,2]p8
2.13 0 [2,8,5]p2
2.14 0 [2,8,5]p2
2.15 0 [5,2,8]p5
2.16 0 [5,2,8]p5
2.17 0 [5,2,8]p5
2.18 0 [2,5,8]p2
2.19 0 [2,8,5]p2
2.1a 0 [5,2,8]p5
2.1b 0 [2,5,8]p2
2.1c 0 [8,2,5]p8
2.1d 0 [5,2,8]p5
2.1e 0 [8,5,2]p8
2.1f 0 [2,5,8]p2
可以看到所有 PG 都是由我们指定的那几个 OSD 组成。
评论区