故障描述
openstack环境中若干台虚拟机无法正常操作,尝试从horizon中重启虚拟机,重启过程中虚拟机状态一直停留在”powering on”的状态,无法进入系统
查看openstack环境,发现后端ceph的状态异常,一个OSD full,一个near full。(clock是这个集群已知问题,这里不做介绍)
(ceph-mon)[root@Node-160 /]# ceph -s
cluster 8a946765-1bb5-40bc-a0bc-4cd830aee2a4
health HEALTH_ERR
clock skew detected on mon.192.168.1.159, mon.192.168.1.160
1 full osd(s)
1 near full osd(s)
full flag(s) set
Monitor clock skew detected
monmap e1: 3 mons at {192.168.1.158=192.168.1.158:6789/0,192.168.1.159=192.168.1.159:6789/0,192.168.1.160=192.168.1.160:6789/0}
election epoch 16, quorum 0,1,2 192.168.1.158,192.168.1.159,192.168.1.160
osdmap e321: 13 osds: 13 up, 13 in
flags nearfull,full,sortbitwise,require_jewel_osds
pgmap v2886234: 624 pgs, 11 pools, 1706 GB data, 383 kobjects
5121 GB used, 2061 GB / 7183 GB avail
624 active+clean
client io 365 kB/s rd, 436 op/s rd, 0 op/s wr
其中一个osd的使用率显示是full的状态。 根据Ceph官方文档中的描述,当一个OSD full比例达到95%时,集群将不接受任何Ceph Client端的读写数据的请求。所以导致虚拟机在重启时,无法启动的情况。
查看ceph集群中各osd的使用率
发现osd的使用不均衡,最高的已超过95%,最低的才40%多点,缺省的均衡方式是按照PGS数量来做均衡,osd之间相差不大,但是真实占用的空间差别太大,根据ceph集群的定义,即使只有一个osd的使用率超过95%,整个集群将不可用,无法读写。
(ceph-mon)[root@Node-158 /]# ceph osd df
ID WEIGHT REWEIGHT SIZE USE AVAIL %USE VAR PGS
0 1.00000 1.00000 552G 353G 198G 64.02 0.90 142
2 1.00000 1.00000 552G 371G 181G 67.21 0.94 136
1 1.00000 1.00000 552G 440G 112G 79.71 1.12 159
4 1.00000 1.00000 552G 381G 170G 69.11 0.97 140
3 1.00000 1.00000 552G 338G 214G 61.20 0.86 125
5 1.00000 1.00000 552G 431G 120G 78.15 1.10 162
6 1.00000 1.00000 552G 422G 130G 76.45 1.07 160
7 1.00000 1.00000 552G 492G 61380M 89.15 1.25 158
8 1.00000 1.00000 552G 416G 135G 75.42 1.06 143
9 1.00000 1.00000 552G 525G 28015M 95.05 1.33 153
10 1.00000 1.00000 552G 348G 203G 63.15 0.89 135
11 1.00000 1.00000 552G 242G 310G 43.90 0.62 127
12 1.00000 1.00000 552G 354G 197G 64.20 0.90 132
TOTAL 7183G 5120G 2062G 71.29
MIN/MAX VAR: 0.62/1.33 STDDEV: 12.67
解决方法
根据官方的建议,首选的方案是添加osd磁盘,添加后将触发数据的重新均衡,full的osd使用率降到95%以下后err状态自然会清除。当时的实际情况无法添加。
网上查到的方案:
方案一,删除无用的rbd磁盘,这个办法也能够解决问题,由于当前的集群状态是err状态,不允许任何读写操作,所以删除的时候也会被卡住,网上查询的办法是使用“ceph osd unset full”命令暂时强制集群恢复读写,但是删除的时候遇到另一个”image still has watchers“的问题,所以该方法也未测试成功
方案二,临时调整osd full的阈值,然后删除不需要的rbd磁盘
ceph tell osd.* injectargs '--mon-osd-full-ratio 0.98'
实际执行命令的时候提示该参数unchangeable,所以也没成功。
临时方案
为了使集群能尽快回复读写状态,临时把osd.9所在的节点关机,集群丢失一个osd,但没了这个full的osd,集群的是warnning状态,这个状态下集群开始恢复数据,虽然不是active+clean的状态,但是ceph是可用的。这样做只是个临时方案,osd.9所在的节点如果不开机,数据无法达到完整状态,但只要开机,集群检测到full的osd,又会变成ERR状态。
最后方案
调整每个osd的weigh值,使数据重新分布
(ceph-mon)[root@Node-158 ceph]# ceph osd crush reweight osd.10 1.05
reweighted item id 10 name 'osd.10' to 1.05 in crush map
osd缺省的weight值为1,调整以后数据会向weigh值高的osd上重新分布,
把一些比较空闲的osd weight值调高,接收数据,使用率高的osd weight调低,释放数据
(ceph-mon)[root@Node-158 ceph]# ceph osd df
ID WEIGHT REWEIGHT SIZE USE AVAIL %USE VAR PGS
0 1.00000 1.00000 552G 298G 254G 53.97 0.91 144
2 1.00000 1.00000 552G 319G 233G 57.79 0.98 145
1 0.89999 1.00000 552G 329G 223G 59.60 1.01 148
4 1.00000 1.00000 552G 323G 229G 58.53 0.99 144
3 1.04999 1.00000 552G 311G 241G 56.37 0.95 135
5 1.00000 1.00000 552G 372G 179G 67.46 1.14 166
6 1.00000 1.00000 552G 381G 171G 68.97 1.17 167
7 0.79999 1.00000 552G 345G 207G 62.50 1.06 132
8 1.00000 1.00000 552G 349G 202G 63.29 1.07 146
9 0.75000 1.00000 552G 360G 192G 65.16 1.10 126
10 1.04999 1.00000 552G 303G 249G 54.89 0.93 141
11 1.09999 1.00000 552G 249G 302G 45.23 0.77 139
12 1.00000 1.00000 552G 298G 254G 53.99 0.91 139
TOTAL 7183G 4242G 2941G 59.06
MIN/MAX VAR: 0.77/1.17 STDDEV: 6.23
最终集群恢复正常
ceph中各osd的pg数量是近似均匀的,可以认为各pg下的数据容量大致相等,因此从原理上来说保证各osd pg相等,则各osd上的磁盘使用量也差不多相同,但是由于算法做不到绝对均匀的原因某些osd上的pg数会相差比较大,这样某些osd上的空间使用量就会比较多。建议是ceph部署完成,各pool也创建完成后,主动手工观察,通过命令调整osd的权重来调整osd上的pg数;
统计各osd上所有pg数:
ceph pg dump | awk '
/^pg_stat/ { col=1; while($col!="up") {col++}; col++ }
/^[0-9a-f]+\.[0-9a-f]+/ { match($0,/^[0-9a-f]+/); pool=substr($0, RSTART, RLENGTH); poollist[pool]=0;
up=$col; i=0; RSTART=0; RLENGTH=0; delete osds; while(match(up,/[0-9]+/)>0) { osds[++i]=substr(up,RSTART,RLENGTH); up = substr(up, RSTART+RLENGTH) }
for(i in osds) {array[osds[i],pool]++; osdlist[osds[i]];}
}
END {
printf("\n");
printf("pool :\t"); for (i in poollist) printf("%s\t",i); printf("| SUM \n");
for (i in poollist) printf("--------"); printf("----------------\n");
for (i in osdlist) { printf("osd.%i\t", i); sum=0;
for (j in poollist) { printf("%i\t", array[i,j]); sum+=array[i,j]; poollist[j]+=array[i,j] }; printf("| %i\n",sum) }
for (i in poollist) printf("--------"); printf("----------------\n");
printf("SUM :\t"); for (i in poollist) printf("%s\t",poollist[i]); printf("|\n");
}'
上面这个是获取各osd所有pool的pg数,其实我们只关注default.rgw.buckets.data这个pool,其他pool数据很少,我们通过ceph df知道default.rgw.buckets.data的pool id是23,通过一个更简单命令得到23号pool在各osd上的pg数排序:
ceph pg dump|grep '^23\.'|awk -F ' ' '{print $1, $15}'|awk -F "[ ]|[[]|[,]|[]]" '{print $3, $4}'|tr -s ' ' '\n'|sort|uniq -c|sort -n
输出如下:
95 1
95 312
96 252
99 177
99 265
99 62
101 121
101 261
......
132 102
132 105
132 179
132 253
132 256
133 111
133 115
133 151
133 203
133 259
133 271
133 292
134 257
134 302
134 61
135 220
可以看到最少的osd.1上面只有95个pg,最多的osd.220上有135个pg,调整pg的命令:
ceph osd reweight-by-pg 105 default.rgw.buckets.data
注:105这个数字貌似不起作用,ceph内部会自己调整
由于每次手动观察比较麻烦,可以通过计算每次调整后的个osd上pg数的方差来判断效果,如果每次反差在减小,说明分布相对更均匀一些:
ceph pg dump|grep '^23\.'|awk -F ' ' '{print $1, $15}'|awk -F "[ ]|[[]|[,]|[]]" '{print $3, $4}'|tr -s ' ' '\n'|sort|uniq -c|sort -r|awk '{printf("%s\n", $1)}'|awk '{x[NR]=$0;s+=$0;n++} END{a=s/n;for(i in x) {ss += (x[i]-a)^2} sd = sqrt(ss/n); print "SD = "sd}'
dumped all in format plain
SD = 8.71607
CEPH 数据不一致时,需要对ceph pg的数据进行平衡
1:检查数据分布是否均衡
#查看osd使用情况 # ceph osd df tree #查看osd_num,PGS, %USE # ceph osd df tree | awk '/osd\./{print $NF" "$(NF-1)" "$(NF-3) }' osd.0 up 0.92 osd.3 up 1.02 osd.1 up 0.90 osd.4 up 1.23 osd.2 up 0.95 osd.5 up 1.03 # |
2:reweight-by-pg 按归置组分布情况调整 OSD 的权重
# ceph osd reweight-by-pg
|
EX:
$ceph osd reweight-by-pg
moved 35 / 4032 (0.868056%) #35个PG发送迁移
avg 115.2 #每个OSD承载的平均PG数目为115.2
stddev 10.378 -> 9.47418 (expected baseline 10.5787) #执行本次调整后, 标准方差将由10.378变为9.47418
min osd.15 with 93 -> 92 pgs (0.807292 -> 0.798611 * mean) #当前负载最轻的OSD为osd.15,只承载了93个PG, 执行本次调整后,将承载92个PG
max osd.6 with 141 -> 132 pgs (1.22396 -> 1.14583 * mean) #当前负载最重的OSD为osd.6, 承载了141个PG, 执行本次调整后,讲承载132个PG
oload 120
max_change 0.05
max_change_osds 4
average_utilization 21.1365
overload_utilization 25.3638
osd.6 weight 1.0000 -> 0.9500 #执行本次调整后,对osd.6,osd.23,osd.7,osd.27的reweight进行调整
osd.23 weight 0.8500 -> 0.9000
osd.7 weight 0.9000 -> 0.9500
osd.27 weight 0.8500 -> 0.9000
3: reweight-by-utilization 按利用率调整 OSD 的权重
# ceph osd reweight-by-utilization moved 10 / 843 (1.18624%) #10个PG发送迁移 avg 140.5 #每个OSD承载的平均PG数目为140.5 stddev 8.69387 -> 12.339 (expected baseline 10.8205) #执行本次调整后, 标准方差将由8.69387 变为12.339 min osd.3 with 127 -> 127 pgs (0.903915 -> 0.903915 * mean) #负载最轻的OSD为osd.3,只承载了127个PG, 执行本次调整后,将承载127 max osd.0 with 154 -> 154 pgs (1.09609 -> 1.09609 * mean) #负载最重的OSD为osd.0, 承载了154个PG, 执行本次调整后,讲承载154个PG
oload 120 max_change 0.05 max_change_osds 4 average_utilization 0.0904 overload_utilization 0.1084 osd.4 weight 0.9500 -> 0.9000 检查数据的平衡状态: # ceph -s |
|
4: 数据均衡后还原权重
#统计osd_num, REWEIGHT [root@node-10 ~]# ceph osd df tree | awk '/osd\./{print $NF" "$4 }' osd.0 1.00000 osd.3 1.00000 osd.1 1.00000 osd.4 0.90002 osd.2 1.00000 osd.5 1.00000 [root@node-10 ~]#
#依次设置osd权重为默认值,1.0 #ceph osd reweight {id} {weight} #说明:osd weight的取值为0~1
$ ceph osd reweight 5 1.0 |
通过ceph osd tree 可以查看到 weight 和reweight的值weight的权重和磁盘的容量有关系: 一般定义1TB为1.0 ;500G为0.5 可以通过如下的命令修改: #ceph osd_id crush reweight
|
在这种状态下 如果直接stop掉 某个节点; 会影响到pg的数据重新分配 ;所以pg的分配取决于weigh值;
reweight的值只有0或者1 可以通过ceph osd reweight命令进行修改 如果从集群中踢出一块osd节点 reweight会从1变为0 ; 及时是up状态也不会变为1 说明reweight只代表crush中的数据分配是否均匀;
当reweight改变时,weight值并不会变化。它影响PG的到OSD的映射关系。Reweight参数的目的,由于ceph的CRUSH算法随机分配,是概率统计意义上的数据均衡,当小规模集群,pg数据相对较少时,会产生一些不均匀的情况,通过调整reweight 参数,达到数据均衡。 需要注意的是,这个参数不会持久化, 当该osd out 时,reweight的值为0 ,当该osd重新up时,该值会恢复到1,而不会保持之前修改过的值。 |
#依次设置osd权重为默认值,1.0 #ceph osd reweight {id} {weight} #说明:osd weight的取值为0~1
$ ceph osd reweight 1 1.0 |
ceph 调整权重
说明
调权重其实就是调优先级 简单来说 调整权重意思就是 ceph osd df |sort -nk 7
查看时有某些osd 使用率到达85%(user%),这时候ceph –s
查看就有near full osd(s)
,更重要的是 到达85以后,pg就会停止或者极少量写入数据。达到90%就会导致整个集群无法使用(比列可以调的,默认是90%), 一般不会某个让%user达到90,会提前调整权重 让使用率偏高的优先级调低 或者使用率低的优先级调高。
开始操作及注意事项
建议每次调整一个osd ,等同步完成后再进行下一个,下面会说调整如何查看
查看使用率
凡是%user达到85的都需要调整ceph osd df |sort -nk 7
调整权重及调整后查看
格式:ceph osd reweight osdID REWEIGHT
(osdid和reweight用ceph osd df查看)
如:调整上图调整osdid为1的优先级为0.85 :ceph osd reweight 1 0.85
注:这个REWEIGHT值 越低 表示优先级越低 也就是说数据会优先往REWEIGHT的上面写,默认是1.
调整完毕以后 使用ceph –s
查看 会有一个数据同步进度 等进度完成以后再调整下一个
使用率达到85%不调整的影响
刚开始说了 osd使用率达到85以后 数据会停止或者极少量写入,现在来详细说明,首先查看 remapped (重映射) ,具体看图ceph pg dump | grep remapped