ceph中的 weight

Last updated on 8 months ago

最近在群里讨论 crush weight的问题,什么是 crush weight?这两天都只是部署安装,还没了解这个,在osd tree中是可以看到 weight,如下图,有weight 和 reweight。前者我知道是对应osd (磁盘)容量,后者呢?这个reweight有什么?这几个问题网上几乎是千篇一律,说是 weight会改变 它影响PG的到OSD的映射关系?是为什么呢?而且还有一个问题,Ceph osd weight与ceph osd crush weight 这两个命令之间又有什么区别?

image-20220730012445791

先说下几个知识点

  • CRUSH 层级结构

    假如一个数据中心里面有很多个机房,机房里面又有很多机柜,机柜里面又有很多服务器,服务器又可以挂载很多磁盘,层层递进就像是多叉树一样,前面所说的 基础设备,在ceph中统称为 故障域或者CRUSH bucket ,这里的 bucket 就是桶的意思,如在机房room0里面就是一个桶,桶里面装的时候rack0,rack1,rack2,rack0也是个bucket,这个bucket里面装的是host,以此类推,但是osd并不是桶,在这个层级结构中osd是最小的单位 ;这些bucket 表明了设备的位置,此外 ceph在管理这种大型分级存储网络,会将这些 基础设备 用crush map映射起来形成一个嵌套层次的结构如下图

    image-20220731001442177

    在 ceph 的命令 也可以看到设备对应的层级结构

    image-20220730012445791
  • crush rule

    从 crush map知道了数据可以放在哪里,数据应该怎么放呢,这也是有对应的规则的,ceph客户端如何去选bucket,以及到最后的osd,选择那个osd作为主osd,那个作为辅助osd ;如果我想 把将热数据存放于SSD中,而将冷数据放在HDD中,这也可以设定相关的规则,crush 算法会根据相应的规则去调整,接下来看下ceph 中的规则是怎样的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    # getcrushmap 获取CRUSH map,这个输出是编译后的,人不看不了,需要反编译下
    [root@node29 ceph]# ceph osd getcrushmap -o crushmap.bin
    33
    #crushtool -d 反编译
    [root@node29 ceph]# crushtool -d crushmap.bin -o crushmap.txt

    #这里面有map 中 每个bucket的详细情况
    # 如 node29 和 root,参照上一张图片的 osd tree
    # buckets
    host node29 {
    id -3 # do not change unnecessarily id为正数说明是osd
    id -4 class hdd # do not change unnecessarily
    # weight 0.586
    alg straw2
    hash 0 # rjenkins1
    item osd.0 weight 0.293
    item osd.3 weight 0.293
    }
    .....
    root default {
    id -1 # do not change unnecessarily
    id -2 class hdd # do not change unnecessarily
    # weight 1.177 #这的weight是 item weight的总和
    alg straw2 #每个bucket选择item时都有指定算法,这里用的是 straw2算法
    hash 0 # rjenkins1
    # bucket 里面的item, 按照层级关系
    item rack01 weight 0.586
    item rack02 weight 0.298
    item rack03 weight 0.293
    }

    #最后是rules
    # rules
    rule replicated_rule {
    id 0 #rule 的编号
    type replicated # pool的类型 多副本还是EC
    min_size 1 #pool的最小副本数
    max_size 10 #pool 的最大副本数
    step take default # bucket的入口点, default 是bucket root的名称
    step chooseleaf firstn 0 type host # fistst 算法,返回 osd位置
    step emit
    }

    rule中有三个 setp

    1. take 从crush map选定编号(选定特定的bucket,示例中 选择的是 root ),作为步骤的开始
    2. select 从输入的bucket中选择随机选择指定类型 type 的item(桶里面的元素),bucket里面有type类型的item,为了尽可能的随机,会使用随机选择算法(有四种),ceph默认是使用 straw2 算法,使用straw2算法,选择item概率都相同,但是会为每一个item计算一个长度,最终会取最长的那个item;计算公式是一个hash值(这个hash值产生与pgid有关系)乘以 item的weight(crush weight ),item weight大的元素有较大的概率算出最长的长度,从而更容易被抽中,当达到一点的数量规模,宏观上看是随机的。(straw2算法还有很多细节,这里知识简单概述下)
    3. emit 将结果返回上一层;

    接下来的crush 算法步骤,这里不在继续讨论,会再另外篇文章 结合源码再来介绍crush 中具体实现算法


    bucket weight是其item weight 的总和,weight是从下往上推的,若是改变osd的weight,osd的上一层bucket weight,会影响cursh 层级,修改 weight 的命令是

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     #ceph osd crush reweight {name} {weight}
    #这里修改 osd.0 的weight
    [root@node29 ~]# ceph osd tree |grep -E "WEIGHT|osd.0"
    ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
    0 hdd 0.29300 osd.0 up 1.00000 1.00000
    #修改之前导出 pg的分布
    [root@node29 ~]# ceph pg dump pgs|awk '{print $1,$17}' > old
    dumped pgs
    [root@node29 ~]# cat old | head -n 10
    2.0 [1,3,2]
    3.1 [1,3,2]
    2.1 [3,2,1]
    3.0 [1,2,0]
    2.2 [2,0,1]
    3.3 [0,2,1]
    2.3 [3,1,2]
    3.2 [3,1,2]
    2.4 [3,1,2]
    [root@node29 ~]#
    #现在修改 osd.0 weight
    [root@node29 ~]# ceph osd crush reweight osd.0 0.1
    ^[[Areweighted item id 0 name 'osd.0' to 0.1 in crush map
    [root@node29 ~]# ceph osd tree |grep -E "WEIGHT|osd.0"
    ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
    0 hdd 0.09999 osd.0 up 1.00000 1.00000
    [root@node29 ~]# ceph pg dump pgs|awk '{print $1,$17}' > new
    dumped pgs

    [root@node29 ~]# diff old new -y -W 30 --suppress-common-lines | head -n 10
    2.0 [1,3,2] | 2.0 [1,2,3]
    3.0 [1,2,0] | 3.0 [1,2,3]
    2.2 [2,0,1] | 2.2 [2,3,1]
    3.4 [2,1,0] | 3.4 [2,1,3]
    2.6 [3,1,2] | 2.6 [1,0,2]
    3.6 [1,3,2] | 3.6 [1,0,2]
    2.8 [0,1,2] | 2.8 [3,1,2]
    3.9 [3,2,1] | 3.9 [1,3,2]
    2.a [0,1,2] | 2.a [1,3,2]
    2.d [2,0,1] | 2.d [2,3,1]
    [root@node29 ~]# diff old new -y -W 30 --suppress-common-lines |wc -l
    101
    [root@node29 ~]# wc -l old
    259
    #pg在osd分布可以看出, 将osd weight 调小后,选择 osd.0 比较少了,所以调整item权重在step 中select是有影响的

总之我们的目的是,尽最大可能让数据均衡在 osd中,这个均衡并不是说 让每个osd存放的数据尽可能一样多,而是说数据所占的百分比,假如有两个硬盘,容量是100g和300g,如果要均衡,存放数据时,存放比例为 1:3 时才能到达均衡,而 osd reweight 就可以的调节;osd reweight 默认为1 ,其这个过程称为过载测试,算法流程如下:

image-20220731175714700

is_out 则是 选出osd的结果,reweight 调整得越高,那么通过测试的概率越高,通过调节reweight可以使数据分布更加合理

1
2
3
4
5
6
7
8
ceph osd reweight {osd} {reweight}
[root@node29 ~]# ceph osd reweight osd.1 0.5
reweighted osd.1 to 0.5 (8000)
[root@node29 ~]# ceph osd tree |grep -E "WEIGHT|osd.1"
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
1 hdd 0.29799 osd.1 up 0.50000 1.00000
#修改后pg分布也有改变

ceh osd weight 是修改 reweight,数值在 [0,1], 选出osd后,通过 reweight可以进行过载测试
ceph osd crush weight 是修改 bucket weight, 这个weight 影响在bucket中选择那个 item起着关键作用