概述
本文主要介绍crushmap相关概念,以及调整crush的几种不同方法。crush为ceph的核心之一,理解其中逻辑对pg规划,容量均衡,故障处理等非常有帮助
crushmap
CRUSH是ceph核心分布式算法,本质是以计算代替查表,去中心化结构,避免了单点故障,提升了性能与扩展性。
Crushmap可以理解为ceph集群拓扑的可视化,CRUSH根据Crushmap中设定的信息将数据随机进行随机分布(伪随机性,达不到理想情况下的完全均匀分布)
导出、导入crushmap
ceph osd getcrushmap -o crushmapold #导出crushmap
crushtool -d crushmapold -o crush.txt #反编译crushmap
vim crush.txt #手动编辑
crushtool -c crush.txt -o crushmapnew #编辑后重新编译
ceph osd setcrushmap -i crushmapnew #应用新的crushmap
crushmap内容
一般一个crushmap内容如下
# begin crush map
tunable choose_local_tries 0
tunable choose_local_fallback_tries 0
tunable choose_total_tries 150
...
# devices
device 0 osd.0
device 1 osd.1
device 2 osd.2
...
# types
type 0 osd
type 1 host
type 2 chassis
...
# buckets
root default{
...
}
root test{
...
item node1 weight 12
item node2 weight 12
...
}
host node1{
...
item osd.0 weight 6
item osd.1 weight 6
...
}
host node2{
...
item osd.2 weight 6
item osd.3 weight 6
...
}
# rules
rule replicated_rule {
...
}
rule test_rule{
...
id 1
type replicated
min_size 1
max_size 10
step take x
step chooseleaf firstn x type x
step emit
...
}
# end crush map
对应osd tree结构可能如下
[root@test ~]# ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-2 23.99996 root test
-3 11.99998 host node1
0 5.99999 osd.0 up 1.00000 1.00000
1 5.99999 osd.1 up 1.00000 1.00000
-4 11.99998 host node2
2 5.99999 osd.2 up 1.00000 1.00000
3 5.99999 osd.3 up 1.00000 1.00000
-1 0 root default
内容分析
- begin/end crush map:声明crushmap的头尾
- devices:列出一共有哪些osd和osd id
- types:容灾域类型,最低级是osd,也就是硬盘容灾,一般个人测试级别最低即可。常见情况host级别容灾,如果上生产需要达到rack级别容灾(map中的故障域为逻辑故障域,具体要根据硬件情况判断)
- buckets:各个层级结构,以及对应关系,weight值
- rules:crushrule,每个rule判断使用该rule的pool上的pg应该使用哪些osd来分担数据
buckets
观察osd tree和crushmap中的bucket,不难看出crushmap中buckets部分,包含了osd的weight值,位于哪个host,而host位于哪个root下。对应逻辑非常简单。
root test{
...
item node1 weight 12
item node2 weight 12
...
}
host node1{
...
item osd.0 weight 6
item osd.1 weight 6
}
-2 23.99996 root test
-3 11.99998 host node1
0 5.99999 osd.0 up 1.00000 1.00000
1 5.99999 osd.1 up 1.00000 1.00000
每层逻辑域的weight为其包含的下层逻辑域的weight值的和,而osd的weight值一般和硬盘的TB值相等,存在map中是会保留小数点后几位。
crushrule
rule,一组包括最大副本数、容灾级别等限制在内的自定义约束条件,也可以称为ceph的数据存储策略。它直接决定了使用了该rule的pool所包含的pg要存在哪些osd上,如何存放,决定了集群的容灾域从而影响集群的健壮性。一条rule可以包含多个操作,基本过程如下
- take:选择指定类型的一个集合作为入口,并作为后续步骤的输入,大部分情况下,我们会take 一个root作为输入
- select:选择指定类型设备指定数量个(firstn算法适用于副本,indep适用于纠删码,本身区别不大),例如 choose firstn 3 type host,就是在上一步take的root下,选择3个host,如果集群本身是host容灾,也可以直接写成chooseleaf firstn 3 type host,则会选出3个host同时,一直往下递归,最终选出分属在3个不同host下的osd设备
- emit:将选择的组合输出并返回
我们常见的3副本,节点容灾
step take root
step chooseleaf firstn 3 type host
其中step chooseleaf firstn 3 type host,chooseleaf为选择最终叶子结点(等于先执行take后面的部分,再从后面的结果中选择一个osd)。这里的含义就是先从上一步的返回中,选择3个type为host的结构,再从该host中选择一个osd,最终也就是实现了三节点每个节点上一个osd承担副本。
交互式调整osd tree
除了导出crushmap,进行编辑再导入的方式之外。一般也可以通过命令,显示调整osd tree结构(需要在ceph.conf中的全局模块中,添加osd_ crush_update_on_start=false,否则osd重新启动后会根据ip,实际位置自动更新,而不是设定的逻辑位置)。
例如,上面例子中
[root@test ~]# ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-2 23.99996 root test
-3 11.99998 host node1
0 5.99999 osd.0 up 1.00000 1.00000
1 5.99999 osd.1 up 1.00000 1.00000
-4 11.99998 host node2
2 5.99999 osd.2 up 1.00000 1.00000
3 5.99999 osd.3 up 1.00000 1.00000
-1 0 root default
现在想新建一个池,将其数据以三副本形式分布在0 1 2 三个osd上,以现有tree结构无法实现。我们可以通过命令手动完成
ceph osd crush add-bucket test1 root #新建一个名为test1的root
ceph osd crush add-bucket ceph1 host
ceph osd crush add-bucket ceph2 host
ceph osd crush add-bucket ceph3 host #新建三个host
ceph osd crush move ceph1 root=test1
ceph osd crush move ceph2 root=test1
ceph osd crush move ceph3 root=test1 #将这三个host移动到新建的test1的 root下
ceph osd crush add osd.0 1.6 root=test1 host=ceph1
ceph osd crush add osd.1 1.6 root=test1 host=ceph2
ceph osd crush add osd.2 1.6 root=test1 host=ceph3 #将三个osd分别移动到三个host下,wieght设置
操作完成后,ceph osd tree结构会变成如下,可以看到test1这个root符合我们预期。
[root@test ~]# ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-5 17.99997 root test1
-6 5.99999 host ceph1
0 5.99999 osd.0 up 1.00000 1.00000
-7 5.99999 host ceph2
1 5.99999 osd.1 up 1.00000 1.00000
-8 5.99999 host ceph3
2 5.99999 osd.2 up 1.00000 1.00000
-2 23.99996 root test
-3 11.99998 host node1
0 5.99999 osd.0 up 1.00000 1.00000
1 5.99999 osd.1 up 1.00000 1.00000
-4 11.99998 host node2
2 5.99999 osd.2 up 1.00000 1.00000
3 5.99999 osd.3 up 1.00000 1.00000
-1 0 root default
然后导出crushmap,新增一条rule,让其take test1这个root,选择3副本。编辑编译后,导回集群。
rule newrule{
id 2
type replicated
step take test1
step chooseleaf firstn 3 type host
}
再create pool时,就可以通过set pool crushruleset 2来让新的pool pg根据上述规则分布。
扩容和临时调整osd逻辑位置时,也常常使用这种方式。