ceph集群中由monitor负责维护的运行图包括:
crush map是ceph集群物理拓扑的抽象,CRUSH算法通过crush map中集群拓扑结构、副本策略以及故障域等信息,来选择存放数据的osd。
以我当前集群为例,crush map描述的集群物理拓扑结构层级如下图,包括3个层级,分别是root、host和osd:
导出当前集群的crush map
ceph osd getcrushmap -o crushmap.bin #导出之后是一个二进制文件
crushtool -d crushmap.bin -o crushmap.txt #使用crushtool将二进制文件解析为文本
当前集群的crush map内容如下:
# 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
# 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
device 9 osd.9 class hdd
device 10 osd.10 class ssd
device 11 osd.11 class ssd
device 12 osd.12 class ssd
device 13 osd.13 class ssd
device 14 osd.14 class ssd
device 15 osd.15 class hdd
device 16 osd.16 class hdd
device 17 osd.17 class ssd
# 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
# buckets
host ceph-osd-05 {
id -3 # do not change unnecessarily
id -4 class hdd # do not change unnecessarily
id -13 class ssd # do not change unnecessarily
# weight 0.146
alg straw2
hash 0 # rjenkins1
item osd.2 weight 0.049
item osd.8 weight 0.049
item osd.14 weight 0.049
}
host ceph-osd-04 {
id -5 # do not change unnecessarily
id -6 class hdd # do not change unnecessarily
id -14 class ssd # do not change unnecessarily
# weight 0.146
alg straw2
hash 0 # rjenkins1
item osd.3 weight 0.049
item osd.5 weight 0.049
item osd.10 weight 0.049
}
host ceph-osd-01 {
id -7 # do not change unnecessarily
id -8 class hdd # do not change unnecessarily
id -15 class ssd # do not change unnecessarily
# weight 0.146
alg straw2
hash 0 # rjenkins1
item osd.1 weight 0.049
item osd.6 weight 0.049
item osd.11 weight 0.049
}
host ceph-osd-03 {
id -9 # do not change unnecessarily
id -10 class hdd # do not change unnecessarily
id -16 class ssd # do not change unnecessarily
# weight 0.146
alg straw2
hash 0 # rjenkins1
item osd.0 weight 0.049
item osd.7 weight 0.049
item osd.13 weight 0.049
}
host ceph-osd-02 {
id -11 # do not change unnecessarily
id -12 class hdd # do not change unnecessarily
id -17 class ssd # do not change unnecessarily
# weight 0.146
alg straw2
hash 0 # rjenkins1
item osd.4 weight 0.049
item osd.9 weight 0.049
item osd.12 weight 0.049
}
host ceph-osd-06 {
id -19 # do not change unnecessarily
id -20 class hdd # do not change unnecessarily
id -21 class ssd # do not change unnecessarily
# weight 0.146
alg straw2
hash 0 # rjenkins1
item osd.16 weight 0.049
item osd.17 weight 0.049
item osd.15 weight 0.049
}
root default {
id -1 # do not change unnecessarily
id -2 class hdd # do not change unnecessarily
id -18 class ssd # do not change unnecessarily
# weight 0.878
alg straw2
hash 0 # rjenkins1
item ceph-osd-05 weight 0.146
item ceph-osd-04 weight 0.146
item ceph-osd-01 weight 0.146
item ceph-osd-03 weight 0.146
item ceph-osd-02 weight 0.146
item ceph-osd-06 weight 0.146
}
# rules
rule replicated_rule {
id 0
type replicated
min_size 1
max_size 10
step take default
step chooseleaf firstn 0 type host
step emit
}
rule erasure-code {
id 1
type erasure
min_size 3
max_size 4
step set_chooseleaf_tries 5
step set_choose_tries 100
step take default
step chooseleaf indep 0 type host
step emit
}
# end crush map
crush map主要由5部分组成:
各tunable参数含义如下:
#为了向后兼容应保持为0
tunable choose_local_tries 0
#为了向后兼容应保持为0
tunable choose_local_fallback_tries 0
#选择bucket的最大重试次数,如果重试50次crush算法还未选择出合适的bucket就失败,可以调整此参数
tunable choose_total_tries 50
#为了向后兼容应保持为1
tunable chooseleaf_descend_once 1
#修复旧bug,为了向后兼容应该保持为1
tunable chooseleaf_vary_r 1
#避免不必要的pg迁移,为做向后兼容应保持为1
tunable chooseleaf_stable 1
#straw算法版本,为了向后兼容应保持为1
tunable straw_calc_version 1
#允许使用的bucket选择算法,通过位运算计算得出的值
tunable allowed_bucket_algs 54
bucke选择算法包括:uniform、list、straw和straw2
devices定义了集群中的每个osd,每个device都有一个id和name,例如osd.1中的1就是device的id
device也可以设置对应的类别,比如hdd、ssd,这样方便crush规则根据磁盘类型来选择osd
#device定格式
device {num} {osd.name} class {disk-type}
例如:
device 0 osd.0 class hdd
device 1 osd.1 class hdd
device 13 osd.13 class ssd
types表示bucket的类型,crush树状结构中除了osd外,其余层级的节点都是bucket,osd一般作为叶子节点。每个bucket对应ceph集群的每个物理拓扑位置,每个bucket可以是低一层级bucket的集合或者是一些叶子节点的集合
可以自定义新的type,但按照惯例,叶子节点必须为osd,其type为0
ceph默认定义的11种type如下:
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 #数据中心
type 9 zone
type 10 region #区域
type 11 root #根节点
所有的中间节点就叫bucket,bucket可以是一些devices的集合,也可以是低一级的buckets的集合,根节点root是整个集群的入口。
定义一个bucket时需要遵循以下语法:
<bucket-type> <bucket-name> {
#全局唯一的负整数id
id <-num>
#所有item的存储容量,1代表1TB,0.5代表0.5TB,依次类推
weight <num>
#选择下一级bucket使用的算法,uniform、list、straw或straw2
alg <value>
#bucket使用的hash算法,默认为0
hash <value>
#低一层级的bucket名称,以及其对应的weight
item <item-name> weight <weight-value>
}
例如当前集群中有6个节点,每个节点上有两块50G HDD和一块50G SSD,其定义如下:
host ceph-osd-05 {
id -3 # do not change unnecessarily
id -4 class hdd # do not change unnecessarily
id -13 class ssd # do not change unnecessarily
# weight 0.146
alg straw2
hash 0 # rjenkins1
item osd.2 weight 0.049
item osd.8 weight 0.049
item osd.14 weight 0.049
}
host ceph-osd-04 {
id -5 # do not change unnecessarily
id -6 class hdd # do not change unnecessarily
id -14 class ssd # do not change unnecessarily
# weight 0.146
alg straw2
hash 0 # rjenkins1
item osd.3 weight 0.049
item osd.5 weight 0.049
item osd.10 weight 0.049
}
rules定义了pool中数据在集群中的存储规则,crush算法的每一步都按照规则来执行
默认情况下,crush map中定义了两个rule:replicated_rule和erasure-code,分别对应副本池和纠删码池。用户可以根据自己的需求添加不同的rule,并为pool指定不同的rule。比如,对于性能要求较高的业务,将其数据存储在ssd pool中,其余业务的数据存放在hdd pool中。
rule的定义规范如下:
rule <rule-name> {
#全局唯一的id
id <num>
#副本类型,副本或纠删码
type <replicated|erasure>
#如果副本数小于该值,不会采用此rule
minsize <num>
#如果副本数大于该值,不会采用该rule
maxsize <num>
#crush规则选择bucket的入口,如果指定了device-class,则必须选择匹配类型的osd
step take <bucket-name> [class <device-calss>]
#crush规则选择bucket的方式,分为choose和chooseleaf两种,N代表选择的数量,是预期的bucket类型,代表故障域
step <choose|chooseleaf> <firstn|indep> <N> type <bucket-type>
#代表规则执行结束,返回选择结果给客户端
step emit
}
关于step
choose:表示选择到预期数量和类型的的bucket即可结束
chooseleaf:表示选择到预期数量和类型的bucket,并从这些bucket中选出osd。chooseleaf可以看做是choose的封装,如果只使用choose,需要定义多条choose规则最终选择出osd
例如,下面的chooselaef规则和choose规则的作用是一致的:
step chooseleaf firstn 0 type host
step choose firstn 0 type host
step choose firstn 1 type osd
firstn和indep:当出现osd down的情况时,用于控制CRUSH的副本策略。副本池使用firstn,纠删码池选择indep,纠删码池要求选择结果是有序的
例如:一个PG分布在osd 1、2、3、4、5上,然后3 down了
在firstn模式下,crush算法会选择1、2,选择3时发现down掉了,然后接着选择4、5,最后选择一个新的未down掉的6,最终结果会变迁为[1、2、3、4、5] -> [1、2、4、5、6]
在indep模式下,crush算法会选择1、2,选择3时发现其down掉了,接着会尝试选择一个未down掉的6,然后选择4、5,最终的结果会变迁为[1、2、3、4、5] -> [1、2、6、4、5]
N:如果N=0,选择的数量等于副本数;如果0
crush map默认的副本池规则和纠删码池规则如下:
rule replicated_rule {
id 0
type replicated
min_size 1
max_size 10
step take default #从default根节点开始选择bucket
step chooseleaf firstn 0 type host #以host为故障域,选择3个host,并从这3个host上分别选择一个osd
step emit
}
rule erasure-code {
id 1
type erasure
min_size 3
max_size 4
step set_chooseleaf_tries 5
step set_choose_tries 100
step take default
step chooseleaf indep 0 type host #选择
step emit
}
修改osd的weight值
ceph osd crush reweight osd.1 0.1 #修改osd.1的权重为0.1
修改osd的reweight值
ceph osd reweight osd.5 0.8 #修改osd.5的reweight的值为0.8
在osd使用率不均匀的时候,可以通过调低使用率较高的osd的reweight值来触发pg数据迁移,降低osd利用率。
不过要注意,修改osd的weight和reweight值都会立即触发pg数据迁移,在数据量较大时可能会集群性能。
集群中ssd和hdd磁盘共存时,可以创建ssd存储池和hdd存储池,将对存储性能要求较高的业务的数据存放在ssd存储池中,以提升业务性能
创建两条针对副本池的crush rule
#语法格式
#ceph osd crush rule create-replicated
#创建名为rule-ssd的规则,从根default开始选择host类型bucket,并最终从host中选择ssd类型的osd
ceph osd crush rule create-replicated rule-ssd default host ssd
#创建名为rule-hdd的规则,从根default开始选择host类型bucket,并最终从host中选择hdd类型的osd
ceph osd crush rule create-replicated rule-ssd default host hdd
ceph osd crush rule list #查看crush rule规则
创建两个pool,分别使用上面的rule-ssd和rule-hdd
ceph osd pool create ssd-pool 16 16 replicated rule-ssd
ceph osd pool create hdd-pool 16 16 replicated rule-hdd
查看两个pool中pg对应的osd组合
ceph osd crush class ls-osd ssd #列出所有ssd类型的osd
ceph osd crush class ls-osd hdd #列出所有hdd类型的osd
ceph pg ls-by-pool ssd-pool |awk '{print $1,$2,$15}'
ceph pg ls-by-pool hdd-pool |awk '{print $1,$2,$15}'
如上图,所有ssd-pool中的pg都分布在ssd osd上,hdd-pool中的pg都分布在hdd osd上。
导出集群当前的crush map
ceph osd getcrushmap -o crushmap.bin
crushtool -d crushmap.bin -o crushmap-v1.txt
cp crushmap-v1.txt crushmap-v2.txt
修改crush map,添加rack bucket和crush rule
vim crushmap-v2.txt
###############################################
#添加3个rack类型的bucket,每个rack包含两个host
rack rack-1 {
id -25
id -26 class hdd
id -27 class ssd
# weight 0.294
alg straw2
hash 0
item ceph-osd-01 weight 0.148
item ceph-osd-02 weight 0.146
}
rack rack-2 {
id -28
id -29 class hdd
id -30 class ssd
# weight 0.292
alg straw2
hash 0
item ceph-osd-03 weight 0.146
item ceph-osd-04 weight 0.146
}
rack rack-3 {
id -31
id -32 class hdd
id -33 class ssd
# weight 0.292
alg straw2
hash 0
item ceph-osd-05 weight 0.146
item ceph-osd-06 weight 0.146
}
#添加一个根节点,包含3个rack
root rep-rack {
id -34
id -35 class hdd
id -36 class ssd
# weight 0.880
alg straw2
hash 0
item rack-1 weight 0.294
item rack-2 weight 0.292
item rack-3 weight 0.292
}
#添加一个副本型rule,以rack为故障域
rule rule-cross-rack {
id 4
type replicated
min_size 1
max_size 10
step take rep-rack
step chooseleaf firstn 0 type rack
step emit
}
###############################################
导入修改后的crush map
crushtool -c crushmap-v2.txt -o crushmap-v2.bin
ceph osd setcrushmap -i crushmap-v2.bin
可以通过ceph osd tree验证新的物理拓扑结构是否生效,如下图
创建pool验证
ceph osd pool create cross-rack-pool 16 16 replicated rule-cross-rack
ceph pg ls-by-pool cross-rack-pool | awk '{print $1,$2,$15}' #查看pg对应osd