CRUSH:基于hash的数据分布算法,ceph集群当中独有的一种数据分布机制。

输入:对象的标识符、crush运行图crush map、归置规则Placement rule。

输出:OSD集合。

计算OSD.png

用户给定一个对象标识,CRUSH算法就能够通过计算得出这些对象将存储在那些个OSD上。


CRUSH分两步:

OBJ -> PG :一致性哈希

PG -> OSD:CRUSH算法

冗余方法有两种:副本池、纠删码池。


故障域:

无论是副本池还是纠删码池都要考虑故障域的概念,

        选择OSD的时候不仅是数量,还要保证OSD垮故障域,如果故障域的级别只是OSD为目标而不管OSD来自于那些地方,OSD的容灾级别就是通过故障域来实现的。故障域可以是跨主机跨地域等。


Cluster Map五大运行图:

Monitor Map:保存当前集群的唯一标识、集群的位置、名称、地址、端口、版本等等

OSD Map:保存OSD的创建时间、存储池数量、版本、规制组、OSD自身的信息等。

PG Map:保存PG数量,状态、时间戳、占满率。

CRUSH Map:存储设备列表、故障域的树状结构、存储数据时如何你用树状结构的规则即Placement Rule、(CRUSH=故障域的树状结构+归置规则。有时会分开叫crush运行图和归置规则)。

MDS Map:当前集群metadata server的数量、活跃数、备用的、备用状态等。

上面这些包括monitor map的所有运行图都放在Monitor进程上了,各运行图维护着各自的运行状态的变更。


故障域的树状结构:

数据中心->机房->机排->机架->主机->磁盘->OSD

        以OSD为故障域如果所有OSD都在一个主机上主机故障之后所有的副本就会丢失。如果以主机为故障域这几个存放副本的OSD就必须在不同的主机上。机架为故障域时几个OSD就在不同的机架上以此类推。

树状结构.png

bucket.png

        归置规则就是定义如何使用这个树状结构来跟好的布局树对象。树状图中的每一个节点都成为一个桶(bucket),这个bucket和OSS中的bucket是不同的东西。找OSD的时候故障域可以告诉我们这些OSD可以跨那个级别的设备。

tack:CRUSH算法搜寻OSD的起始位置,指定入口。

select:根据CSUDH算法和指定的故障域,从入口向下去挑选出符合条件的OSD集合。

副本池和纠删码池使用的不同的挑选算法:副本池:firstn、纠删码池:indep。都是深度优先算法,不过选出的OSD个数有区别。

桶算法:树结构中子项目的选择算法(一个桶当中选子项目的算法)。

uniform、list、tree、straw、straw2

        Ceph集群在运行起来之后也会自己生成运行图当中的每一个bucket的定义,归置规则Placement Rule定义Ceph客户端如何选择存储桶,以及桶当中的主OSD是谁,也就是从列表当中选中谁是主OSD。管理员可以自定义归置规则,也可以让存储池自行生成归置规则。


在Ceph集群上使用归置规则和调制CRUSH:

常用命令:

ceph osd crush

获取当前运行图:

先获取crushmap的二进制:

~]$ ceph osd getcrushmap -o /tmp/mycrushmap.bin
14

再反编译成文本:

~]$ crushtool -d /tmp/mycrushmap.bin -o ./mycrushmap.txt

获取到的运行图如下:

~]$ cat mycrushmap.txt 
# begin crush map 可调参数,微调crush的某些特性
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

# types 支持的桶bucket类型
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

# buckets 这里的桶类型为host
host ceph04 {
	id -3		# do not change unnecessarily
	id -4 class hdd		# do not change unnecessarily
	# weight 0.029
	alg straw2 # 桶算法
	hash 0	# rjenkins1 使用哪种hash计算的类型为rjenkins1
	item osd.0 weight 0.015 # host下面有两个子项目osd0和osd1,和对应的权重,根据磁盘大小做的比例计算
	item osd.1 weight 0.015
}
host ceph05 {
	id -5		# do not change unnecessarily
	id -6 class hdd		# do not change unnecessarily
	# weight 0.029
	alg straw2
	hash 0	# rjenkins1
	item osd.2 weight 0.015
	item osd.3 weight 0.015
}
host ceph06 {
	id -7		# do not change unnecessarily
	id -8 class hdd		# do not change unnecessarily
	# weight 0.029
	alg straw2
	hash 0	# rjenkins1
	item osd.4 weight 0.015
	item osd.5 weight 0.015
}
# 还可以定义主机的上级结构
# 如果没有下面就是跟结构
root default {
	id -1		# do not change unnecessarily
	id -2 class hdd		# do not change unnecessarily
	# weight 0.088
	alg straw2
	hash 0	# rjenkins1
	item ceph04 weight 0.029 # 因为是树状结构,这里没有其他结构了所以直接就是节点名称
	item ceph05 weight 0.029 # 如果还有其他结构填写相应的结构即可
	item ceph06 weight 0.029
}

# rules 从这个树状结构当中如何选择OSD
rule replicated_rule { # 这是个副本池的规则,如果创建的是纠删码池则会生成一个默认的纠删码池规则
	id 0
	type replicated # 冗余数据的类型方式。通过replicated冗余逻辑来存放
	min_size 1 # 冗余的最小个数
	max_size 10 # 冗余的最多个数,默认为3个
	step take default # 开始挑选设备的位置,这里为default,就是上面的root default
	step chooseleaf firstn 0 type host # 深度优先遍历算法,chooseleaf:直接选择叶子节点;firstn 选择前n个;host:故障域为host
	step emit # 弹出结果
}

# end crush map

将修改好的运行图注入回集群:

将修改好的文本文件编译成二进制:

~]$ crushtool -c mycrushmap.txt -o mycrushmap-v2.bin

将curshmap注入回集群:注入后即可生效,务必做好充分测试。

~]$ ceph osd setcrushmap -i mycrushmap-v2.bin 
15