首先说下ceph环境

uname -a
Linux mon3 3.10.0-327.el7.x86_64 #1 SMP Thu Nov 19 22:10:57 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
ceph -v
ceph version 10.2.2 (45107e21c568dd033c2f0a3107dec8f0b0e58374)

crush map状态

ceph -s
    cluster 99cc26bd-f8b0-438a-8085-a60da971afae
     health HEALTH_OK
     monmap e1: 3 mons at {mon1=192.168.7.21:6789/0,mon2=192.168.7.22:6789/0,mon3=192.168.7.23:6789/0}
            election epoch 550, quorum 0,1,2 mon1,mon2,mon3
     osdmap e20778: 15 osds: 15 up, 15 in
            flags sortbitwise
      pgmap v668984: 1612 pgs, 4 pools, 627 GB data, 157 kobjects
            1257 GB used, 15407 GB / 16665 GB avail
                1612 active+clean

在不改变crush map,不添加新osd情况下,ceph集群中pg数量是固定不变的,上面可以看到集群中pg总数为1612 ,我们来看看这个pg数怎么来的

计算pg数量

ceph pg dump可以输出集群所有pg详细信息

ceph pg dump 2>/dev/null | egrep '^[0-9]+\.[0-9a-f]+\s' | wc -l
1612

#或者可以使用如下命令
ceph pg ls | grep -v '^pg_stat' | wc -l
1612

上面输出也可以验证集群中pg数量确实有1612个,我们这样考虑,所有的pg都肯定存在于某个pool上,因此计算所有pool上的pg数之和也可以得到总pg数

#ceph pg ls-by-pool poolname 可以查看存在于poolname上的所有pg详细信息
for i in `ceph osd pool ls`;do ceph pg ls-by-pool $i | grep -v '^pg_stat' | wc -l;done | awk '{a+=$1} END{print a}'
1612

根据pool计算结果也是1612,还可以这样考虑,所有的pg最终都是要放在某个osd上的,因此我们也可以根据osd计算集群中pg总数

#ceph osd df 可以查看集群中每个osd的使用信息,以及各个osd上的pg数 
ceph osd df tree | grep 'osd\.'
 2  0.50000  1.00000  1116G  65551M  1052G  5.73 0.74 281             osd.2  
13  0.09999  1.00000  1116G  12679M  1104G  1.11 0.14  50             osd.13 
14  0.09999  1.00000  1116G  13505M  1103G  1.18 0.15  46             osd.14
...

#用awk计算倒数第二个字段之和,系统总pg数
ceph osd df tree | grep 'osd\.' | awk '{a+=$(NF-1)} END{print a}'
3812

看来osd上存在的实际pg数3812跟上面的计算并不一致,要知道这些输出不一致的原因,我们先看一个具体的pg映射关系

pg与replicated size

随便从ceph pg dump输出中选择一个pg,比如我们选择这个1.fc,看看它的映射关系

ceph pg dump | grep '1.fc' | awk '{print $1,$15}'
1.fc [7,2]

截取的是第一字段和第15字段,[7,2]意思是此pg有两个副本(副本数取决于pool的replicated size设置的值),也即osd.7osd.2上都有这个pg1.fc的一份拷贝。可以知道,每个pg都像这样有多个副本,存在于多个osd上,当我们计算所有osd上的pg时,1.fc的两个副本都会被计算一次,同理其它pg会也被计算replicated size次,因此最终根据osd计算出的pg是包括副本数的,下面我们从理论上计算下所有osd上的pg数量

我们查看集群有多少个pool

ceph osd dump |grep pool | awk '{print $1,$3,$4,$5":"$6,$13":"$14}'
pool 'rbd' replicated size:2 pg_num:1024
pool 'ecpool' erasure size:3 pg_num:64
pool 'hotstorage' replicated size:3 pg_num:12
pool 'pool14' replicated size:3 pg_num:512

可以看到有4个pool,以pool rbd来说,其设置的pg数pg_num1024,副本数replicated size为2,即pool rbd上的每个pg都有两个副本,因此rbd中所有pg总数为2 * 1024个,2048个pg,这样我们可以计算所有pool上包括副本数的pg总数

#$6 replicated
#$14 pg_num
ceph osd dump |grep pool | awk '{a+=$6 * $14} END{print a}'
3812

这里理论上计算的pg数3812与上面根据osd计算的pg总数一样,因此可以验证ceph osd df得到的pg数为包含副本的pg数量

根本原因在于ceph集群中副本数(replicated size)的存在,从monitor角度来看系统中确确实实有1612个名称互不相同的pg,比如上面提到的1.fc。像ceph pg lsceph pg dump这些输出都可以列出所有这些pg信息,并显示其副本数。但是到了osd这一层,每个pg都复制了replicated size份,然后存入osd,从osd角度来计算自然也包括复制的pg。像1.fc这个pg,osd看到的是2个一模一样的1.fc,只是存在于不同的osd上,但是在monitor看,只能算一个pg,只是有多个拷贝而已

集群中每个pg经过crush算法被映射到多个osd上去,ceph pg ls列出了所有pg到osd的映射信息