CRUSH Maps
所述CRUSH算法确定如何存储和通过计算数据存储位置检索数据。CRUSH使Ceph客户端能够直接与OSD通信,而不是通过集中式服务器或代理进行通信。通过算法确定的存储和检索数据的方法,Ceph避免了单点故障,性能瓶颈以及对其可扩展性的物理限制。
CRUSH映射包含OSD列表,用于将设备聚合到物理位置的“存储桶”列表以及告诉CRUSH如何在Ceph集群池中复制数据的规则列表。通过反映安装的底层物理组织,CRUSH可以对相关设备故障的潜在来源进行建模(从而解决)。典型的来源包括物理邻近度,共享的电源和共享的网络。通过将此信息编码到群集图中,CRUSH放置策略可以在不同故障域之间分离对象副本,同时仍保持所需的分布。例如,为了解决并发故障的可能性,可能需要确保数据副本位于使用不同架子,机架,电源,控制器和/或物理位置的设备上。
部署OSD时,它们会自动放置在CRUSH映射中的host节点下,该 节点的名称是运行它们的主机的主机名。这与默认的CRUSH故障域结合在一起,可确保副本或擦除代码碎片在主机之间是分开的,并且单个主机故障不会影响可用性。但是,对于较大的群集,管理员应仔细考虑他们对故障域的选择。
CRUSH结构
粗略地说,CRUSH映射由描述群集物理拓扑的层次结构和一组规则定义,这些规则定义了有关如何将数据放置在这些设备上的策略。层次结构ceph-osd在叶子上具有设备(守护程序),以及与其他物理功能或分组相对应的内部节点:主机,机架,行,数据中心等。规则描述了如何按照该层次结构放置副本(例如,“不同机架中的三个副本”)。
手动编辑crush结构
来理解crush中devices,types,buckets,rules这四个主要模块:
获取一个CRUSH MAP
[ceph@ceph03 ~]$ ceph osd getcrushmap -o crushmap.map #输出为二进制的文件
反编译CRUSH MAP
[ceph@ceph03 ~]$ crushtool -d crushmap.map -o crushmap.txt #把二进制文件转为文本文件,方便修改
重新编译一个CRUSH MAP
[ceph@ceph03 ~]$ crushtool -c crushmap.txt -o crushmap.map
设置CRUSH MAP
ceph osd setcrushmap -i crushmap.map
这里看一下crushmap.txt里面的内容:
[ceph@ceph03 ~]$ cat crushmap.txt
# begin 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
#设备还可以具有与它们关联的设备类(例如 hdd或ssd),从而可以通过crush规则方便地将它们作为目标。
# 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
#要将存储桶类型添加到CRUSH映射中,请在存储桶类型列表下创建新行。输入,type后跟唯一的数字ID和存储桶名称。
# 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 zone
type 10 region
type 11 root
#创建存储桶层次结构的目的是通过叶子节点的故障域(例如上面的host,rack,row,room等)隔离叶子节点。
# buckets
host ceph06 { #这里是声明为主机存储桶,当然还可以声明为rack(机架)等类型的存储桶。
id -3 # do not change unnecessarily
id -4 class hdd # do not change unnecessarily
# weight 0.078
alg straw2 #存储桶类型,默认为straw2,还有uniform,list,tree,straw这四种
hash 0 # rjenkins1
item osd.0 weight 0.039 #osd所占的权重
item osd.3 weight 0.039
}
host ceph04 {
id -5 # do not change unnecessarily
id -6 class hdd # do not change unnecessarily
# weight 0.039
alg straw2
hash 0 # rjenkins1
item osd.1 weight 0.039
}
host ceph05 {
id -7 # do not change unnecessarily
id -8 class hdd # do not change unnecessarily
# weight 0.039
alg straw2
hash 0 # rjenkins1
item osd.2 weight 0.039
}
root default { #这里是声明为root的存储桶,root下面可以再细分为rack等类型的存储桶。
id -1 # do not change unnecessarily
id -2 class hdd # do not change unnecessarily
# weight 0.156
alg straw2
hash 0 # rjenkins1
item ceph06 weight 0.078
item ceph04 weight 0.039
item ceph05 weight 0.039
}
####这里举个例,如果不要root类型的,改声明为rack类型的如何设置。
rack rack1 {
id -1
alg straw2
hash 0
item ceph06 weight 0.078
item ceph04 weight 0.039
item ceph05 weight 0.039
}
# rules
rule replicated_rule {
id 0
type replicated #描述存储驱动器(复制)或RAID的规则。这里是复制
min_size 1 #如果池中的副本数量少于此数量,则CRUSH将不会选择此规则
max_size 10 #如果池中的副本数量超过此数量,则CRUSH将不会选择此规则
step take default #取一个存储桶名称,然后开始遍历树。
step chooseleaf firstn 0 type host
#step chooseleaf firstn {num} type {bucket-type}即selects a set of buckets of {bucket-type}
#firstn是控制在CRUSH映射中标记了项目(OSD)时CRUSH使用的替换策略,replicated用firstn,erasure用indep
#If {num} == 0, choose pool-num-replicas buckets (all available).
#If {num} > 0 && < pool-num-replicas, choose that many buckets.
#If {num} < 0, it means pool-num-replicas - {num}.
step emit
}
rule erasure-code {
id 2
type erasure
min_size 3
max_size 3
step set_chooseleaf_tries 5
step set_choose_tries 100
step take default
step chooseleaf indep 0 type host
step emit #输出当前值并清空堆栈。
}
通过解读上面的配置文件我们对crush map有了一定的了解,我们用图再来理解一下buckets,如下图,rack类型存储桶下有host类型的存储桶,host下包含着osd类型的bucket。
DEVICE CLASSES
每个设备可以选择具有与之关联的类。默认情况下,OSD在启动时会根据其支持的设备类型自动将其类设置为 hdd,ssd或nvme。
可以使用以下命令显式设置一个或多个OSD的设备类:
ceph osd crush set-device-class <class> <osd-name> [...]
设置设备类别后,除非使用以下方法取消设置旧类别,否则无法将其更改为另一个类别:
ceph osd crush rm-device-class <osd-name> [...]
例:
[ceph@ceph03 ~]$ ceph osd crush set-device-class ssd osd.0
Error EBUSY: osd.0 has already bound to class 'hdd', can not reset class to 'ssd'; use 'ceph osd crush rm-device-class <id>' to remove old class first
[ceph@ceph03 ~]$ ceph osd crush rm-device-class osd.0
done removing class of osd(s): 0
[ceph@ceph03 ~]$ ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-1 0.15636 root default
-5 0.03909 host ceph04
1 hdd 0.03909 osd.1 up 1.00000 1.00000
-7 0.03909 host ceph05
2 hdd 0.03909 osd.2 up 1.00000 1.00000
-3 0.07817 host ceph06
0 0.03908 osd.0 up 1.00000 1.00000
3 hdd 0.03909 osd.3 up 1.00000 1.00000
[ceph@ceph03 ~]$ ceph osd crush set-device-class ssd osd.0
set osd(s) 0 to class 'ssd'
[ceph@ceph03 ~]$ ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-1 0.15636 root default
-5 0.03909 host ceph04
1 hdd 0.03909 osd.1 up 1.00000 1.00000
-7 0.03909 host ceph05
2 hdd 0.03909 osd.2 up 1.00000 1.00000
-3 0.07817 host ceph06
3 hdd 0.03909 osd.3 up 1.00000 1.00000
0 ssd 0.03908 osd.0 up 1.00000 1.00000
这使管理员可以设置设备类,而无需在OSD重新启动时或通过其他脚本更改类。
可以使用以下方式创建针对特定设备类别的放置规则:
ceph osd crush rule create-replicated <rule-name> <root> <failure-domain> <class>
然后可以将池更改为在以下情况下使用新规则:
ceph osd pool set <pool-name> crush_rule <rule-name>
修改CRUSH MAP
添加/移动OSD
ceph osd crush set {name} {weight} root={root} [{bucket-type}={bucket-name} ...]
name:OSD的全名,例:osd.0
weight:OSD的CRUSH权重,通常以太字节(TB)为单位。例:2.0
root:OSD所在树的根节点(通常为default),例:root=default
bucket-type:您可以在CRUSH层次结构中指定OSD的位置,例:datacenter=dc1 room=room1 row=foo rack=bar host=foo-bar-1
举例:
ceph osd crush set osd.0 1.0 root=default datacenter=dc1 room=room1 row=foo rack=bar host=foo-bar-1
调整OSD权重
ceph osd crush reweight {name} {weight}
删除OSD
ceph osd crush remove {name}
添加一个桶
ceph osd crush add-bucket {bucket-name} {bucket-type}
#例:
ceph osd crush add-bucket rack12 rack
移动桶
要将存储桶移动到CRUSH地图层次结构中的其他位置或位置,请执行以下操作:
ceph osd crush move {bucket-name} {bucket-type}={bucket-name}, [...]
删除桶
ceph osd crush remove {bucket-name}
为复制池创建规则
对于复制池,创建CRUSH规则时的主要决策是故障域的类型。例如,如果选择的故障域host,则CRUSH将确保数据的每个副本都存储在不同的主机上。如果rack 选择,则每个副本将存储在不同的机架中。
还可以创建一个规则,将数据放置位置限制为特定类别的设备。默认情况下,Ceph OSD会根据所使用设备的基础类型自动将其自身分类为hdd或ssd。这些类也可以自定义。
要创建复制规则,请执行以下操作:
ceph osd crush rule create-replicated {name} {root} {failure-domain-type} [{class}]
name:规则名称
root:应在其下放置数据的节点的名称。例:default
failure-domain-type:我们应在其中分离副本的CRUSH节点的类型。例:rack
class:设备类别数据应放在上面。例:ssd
删除规则
ceph osd crush rule rm {rule-name}
查看规则
ceph osd crush rule ls
可以使用以下方法查看规则的内容:
ceph osd crush rule dump
划分故障域
原文转载:https://blog.csdn.net/qq_33218245/java/article/details/103312942
1.目标
希望创建2个存储池,一个全hhd作为后端存储,一个全ssd作为后端存储池的高速缓存池,并且当有个别服务器宕机时,依然不影响数据的读写。
2.规划
创建两个root(hhd,ssd),6个host(node1_hhd,node2_hhd,node3_hhd,node1_ssd,node2_ssd,node3_ssd),最后将每个服务器对应的osd加入到crush中。
3.创建crush
ceph osd crush add-bucket hhd root
ceph osd crush add-bucket ssd root
ceph osd crush add-bucket node1_hhd host
ceph osd crush add-bucket node2_hhd host
ceph osd crush add-bucket node3_hhd host
ceph osd crush add-bucket node1_ssd host
ceph osd crush add-bucket node2_ssd host
ceph osd crush add-bucket node3_ssd host
4.移动crush
ceph osd crush move node1_hhd root=hhd
ceph osd crush move node2_hhd root=hhd
ceph osd crush move node3_hhd root=hhd
ceph osd crush move node1_ssd root=ssd
ceph osd crush move node2_ssd root=ssd
ceph osd crush move node3_ssd root=ssd
5.创建并移动osd crush
这里需要计算osd权重,权重计算公式(权重=osd大小%1T),如果osd大小为500G,权重就是0.50000,osd大小为2T,权重就是2.00000,我这里为了方便将osd权重全设为1.0000。
ceph osd crush create-or-move osd.0 1.00000 host=node1_hhd
ceph osd crush create-or-move osd.1 1.00000 host=node2_hhd
ceph osd crush create-or-move osd.2 1.00000 host=node3_hhd
ceph osd crush create-or-move osd.3 1.00000 host=node1_ssd
ceph osd crush create-or-move osd.4 1.00000 host=node2_ssd
ceph osd crush create-or-move osd.5 1.00000 host=node3_ssd
6.创建rule
ceph osd crush rule create-simple hhd_rule host hhd
ceph osd crush rule create-simple ssd_rule host ssd
7、创建存储池
ceph osd pool create hhd 64 64
ceph osd pool create ssd 64 64
8、给存储池指定rule
ceph osd pool set hhd crush_rule hhd_rule
ceph osd pool set ssd crush_rule ssd_rule