bluestore拯救pg
写在前面
松鼠哥的ceph专业课程上线啦!
面向新手同学,从0实战,全面入门ceph安装部署与运维,有需要的同学赶紧扫码订购吧:
最近线上的池子已经达到13个,每天写入总量超过1PB,人手严重不足啊啊啊~
今天要讲的是比较极端情况,osd因为osdmap的问题无法正常启动,需要重新对osd的数据进行处理,还要确保数据不丢失
问题的出现
刚接手这个集群的时候,现象是有16个不同故障域的osd没有起来,这16个osd是out的状态,考虑到12+4的场景,16个osd down意味着有一批pg肯定是down的,另外还有很多pg受到牵连,处于降级和remapped状态,伴有2G的recovery流量
操作的话,知道的是使用了ceph osd primary-temp <pgid> <osdname>
这个命令修改了63.850这个pg的主osd
排查
osd起不来怎么办?看日志呗
1 | PG.h: 2817: FAILED assert(primary.osd == new_acting_primary) |
看了一下,osd到这就挂了,对照了一下代码位置,没有什么有用的信息~看样子,跟前面贸然修改主pg是有关的,虽然名义上说是primary-temp,但实际上也不是怎么回事,日志打开20/20继续看
1 | osd.321 15461 get_map 15431 - loading and decoding 0x55e249ec6c00 |
在挂之前,发现有这两个信息,在mon日志中查了一轮,发现15467这个版本的osdmap,恰好是第二次重启后,集群不正常的osdmap,这个osdmap正是16个osd out 出去之后的map,看样子,osd看到这个osdmap,发现pgmap内容与它的的不一致,所以就断言失败退出了,再仔细看了一下,由于在重启前没有设置noout,导致16个osd都out出去了,这是osdmap发生了根本变化的原因!!!mon中的osdmap版本到了16407!!我的天,osdmap版本差距特别大,而且,因为这样,当前的pgmap中,63.850映射的osd全部发生了变化
难怪了,首先重启osd后,由于osd数量大重启时间不一,且启动缓慢,导致部分osd超时out出集群,使得osdmap版本快速变化,从而引发pg重新map,另外一个重要原因,修改了pg的主osd,使得osd起动过程中发现主pg有问题而无法正常启动,引发整个pg关联的osd直接挂掉
如果集群osd数量大,例如这个集群osd共1324个,重启全部的osd前最好设置一个noout
由于in状态的osd数量发生变化,导致osdmap发生变化,crush规则重新计算出的pgmap也就发生了变化,为了恢复原来的osdmap,需要手动先将out出去的osd先手工一个个加进来,即使它们是down的
osd加进来后,osdmap应该是恢复到了早前正常的状态,那这个时候启动那16个osd试试看
启动结果仍然让人痛心,原因一样,启动到15467这个版本,就会挂掉,看起来osd启动的过程中,会逐步提高osdmap的版本,而不是一次性立马就使用最新的osdmap,看来15467这个坎不好过
能不能这样操作,导出现在最新的osdmap,注入给osd呢?让osd直接使用最新的版本,而不是慢慢提升?想法很美好,事实却不行,首先从mon导出当前版本的osdmap,再注入到osd中,只要注入的osdmap内容中,有这个osd不含有的内容,就会注入失败,注入早一点的版本确是可以的,但实际结果就是,osd仍然会挂在某个有问题的版本上
解决
操作拉满,osd死活起不来,总是挂在有错误的osdmap版本上,思前想后,主要原因应该是63.850和这个pg,它的分布被人为改变了,所以无法正常起来
那么能不能先导出这个pg,然后删掉这个pg,再拉起osd,等osd正常启动并更新到最新的osdmap后,再将pg导回去呢?
说干就干,用到的工具是ceph-objectstore-tool
首先将osd停掉,虽然它起不来,但是它会被systemctl一直尝试拉起,所以进程看起来是在的,要停掉,否则无法操作
1 | systemctl stop ceph-osd@321.service |
接下来,导出有问题的pg,注意到,63.850s0
表示的是63.850
这个pg的第一个副本,这里是EC的12+4,因此会有63.850s0
-63.850s15
共16个分片,全部都要分别导出
1 | ceph-objectstore-tool --data-path /var/lib/ceph/osd/ceph-321/ --type bluestore --pgid 63.850s0 --op import --file 63.850s0.pgdata |
这个过程取决于pg 中的数据量,这个osd的数据大概36G,导出花了50分钟左右
1 | [root@ceph009 ~]# du -m 63.850s0.pgdata |
然后,将这个osd上的对应pg删除
1 | ceph-objectstore-tool --data-path /var/lib/ceph/osd/ceph-321/ --type bluestore --pgid 63.850s0 --op remove --force |
这样,这个pg就从bluestore中删掉了,接下来,启动这个osd
1 | systemctl start ceph-osd@321.service |
啊~~终于起来了!osd启动后,快速地更新它的osdmap,与之关联的其他pg立刻得到更新,很快就恢复了正常,剩下的15个osd如法炮制,待全部都起来后,63.850这个pg就显示为unknown
,那当然,它的acting set和up set都全部为NONE
,因此集群无法得知这个pg的情况
接下来,将osd再次stop,然后导入刚才导出的pg
1 | systemctl stop ceph-osd@321.serivce |
与导出一样,花费了差不多1个小时,导入完成提示Import successful
,就可以启动osd了
另外的15个osd也依葫芦画瓢,随着osd起来的越来越多,63.850这个pg状态从unknown变成down,再变成active,逐渐恢复了正常
1 | pools: 11 pools, 18184 pgs |
总结
第一次处理这种osd起不来的故障,还是有点手忙脚乱,这里也可以看出,EC模式的修复比副本模式是要复杂的,副本模式的话,就算只剩下一份副本了,可以导出这个pg副本,再导入其他osd,就可以恢复,但是EC下,每个副本都是不相同的,无法这样操作,而且必须有K个以上的副本,才有可能恢复数据,要求更高
从解决过程来看,将pg从osd导出,再导入,可以看作是osd灾难性故障恢复的一般操作,从中也可以看到,只要磁盘还在,数据没丢,恢复的可能性是非常大的,千万不要随便放弃治疗~
- 本文作者: 奋斗的松鼠
- 本文链接: http://www.strugglesquirrel.com/2020/01/23/bluestore拯救pg/
- 版权声明: 本博客所有文章除特别声明外,创作版权均为作者个人所有,未经允许禁止转载!