写在前面
有些日志没更新了,原因比较多,后续也还是会努力更新…
本次是处理一个测试集群的unknown的PG问题,总体来说算基本操作,不是很复杂,重在思路
问题
首先是集群发现有一个pg进入了unknown状态:
1 | data: |
这里有个细节,其实一开始pg并不是unknown状态的,而是stale状态的,但是经过排查,松鼠哥发现mgr服务貌似有问题,像是卡住的状态,于是重启了一下mgr服务,pg就立刻进入unknown状态了,实际上这两个状态都很糟糕。
查一下osd的状态,发现是大量的osd挂掉了,三副本的pool有3个及以上的不同host的osd发生down,出问题几乎是必然的
1 | [test1mon-1 user1]$ sudo ceph osd tree down |
注意到,这些down状态的osd都是out的,也就是REWEIGHT都为0,这种情况下,只有1个pg是unknown已是万幸,应该是osd发生down的事件连续发生,而该pg还没有来得及完整地backfill到其他osd上,其所有副本就都down了,尝试了一下拉起那些osd,有点麻烦,拉不起来。
初步看一下这个pg的map
1 | [test1mon-1 user1]$ sudo ceph pg map 7.6ec |
发现2174,2191,2332这三个osd都是up的,但是他们上面都没有7.6ec这个pg,而且使用ceph pg 7.6ec query命令居然报错,说没有这个pg,上面的猜想看来是对的,该pg的三个副本都没有完成backfill就down了。
那么基于这个原因,我们能想到的处理方案就很直接了:从这个pg原来的osd中导出pg数据,再导入现在的pg的主osd中(2174)来恢复数据
问题的处理
要从pg的原来的osd中导出它的整个pg数据,首先要知道它原来在哪些osd上,这有几种思路:
- 从所有down的osd中,使用ceph-objectstore-tool工具,去逐个找,看看哪个osd中存放了这个pg
- 定位到故障前的某个osdmap版本,从该osdmap中找出当时的pg映射集合,找出目标osd
松鼠哥不用蛮力,用第二种方法。
首先是要找到osdmap的版本,初步想了一下,有2种方案:
- 1、使用目标pg的前后一个pg,查看它们的详细信息,定位版本
- 2、从osd中探查osdmap的早期版本
第1种想法是基于故障发生的时间戳,我们可以找一个pg,跟目标pg 7.6ec是相邻的,那么我们可以认为,该pg与目标pg 7.6ec发生故障的时间应该是一样的,于是,如果我们基于这个pg的最后clean时间,理论上就能够知道,目标pg7.6ec最后一次clean状态的osdmap版本,从而达到我们的目的。
这里松鼠哥选择 7.6ed,探查一下它的pg clean版本
1 | [test1mon-1 user1]$ sudo ceph pg 7.6ed query|grep last_epoch_clean |
这里可以看到最小的osdmpa版本是288951,那么这就是我们要的版本吗?实际处理发现,并不是,在该版本中,7.6ec已经发生了remap,不是我们要的版本。
于是松鼠哥继续采取第2种想法,从osd种探查osdmap的更早的版本。
这里选择了osd.2160,这个是随机选择的,它的原理是,在pg全面进入active+clean状态之后,osd才会对本地的osdmap进行裁剪,这是为了让osd能够使用osdmap进行集群事件的回溯,于是我们在osd.2160种进行查找。
首先需要导出osd的rocksdb
1 | ceph-bluestore-tool bluefs-export --path /var/lib/ceph/osd/ceph-2160 --out-dir /ceph-2160 |
然后,在该rocksdb中选择osdmap
1 | [test1mon-1 user1]$ ceph-kvstore-tool rocksdb /ceph-2160/db/ list O|grep osdmap > osdmaps |
这里使用grep和awk处理后,发现osd.2160本地存储的最早期的osdmap版本就是287881,于是我们可以从集群得到这个版本的osdmap,从而实现pg的映射查找
1 | [test1mon-1 user1]$ ceph osd getmap 287881 -o osdmap.287881 |
好的,得到了[2252,2233,2308],这就够了,现在可以去osd.2233上导出pg了
1 | [root@mon-3 user1]# ceph-objecttest1-tool --data-path /var/lib/ceph/osd/ceph-2233/ --op list-pgs|grep 7.6ec |
导出没问题,看大小也是挺正常的,接下来根据现在最新的pg映射将pg导入,因为3副本min_size设置为1,因此导一个osd就够了,
1 | [test1mon-1 user1]$ sudo ceph pg map 7.6ec |
这就完成了,拉起osd.2174,过一会pg就都正常了
1 | data: |
总结
本次故障并不复杂,大多数是基本操作,主要是思路,用蛮力去查找所有osd,找出目标pg进行导出,也是一个有效方案,本次松鼠哥使用历史osdmap导出,并在该版本上使用pg map找到目标osd,是一个比较有意思的视角,实际上,我们可以从中举一反三,只要是需要定位故障时间戳、集群版本号的,都可以使用该思路
- 本文作者: 奋斗的松鼠
- 本文链接: http://www.strugglesquirrel.com/2026/09/29/处理一个unkonwn的PG/
- 版权声明: 本博客所有文章除特别声明外,创作版权均为作者个人所有,未经允许禁止转载!