异常PG处理套路

PG的全称为Placement Group(放置组),放置顾名思义放置Object的载体。PG的创建是在创建Pool的时候根据指定的数量进行创建。PG的数量与副本数也有关系,比如是3副本的则会有3个相同的pg存在于3个不同的osd上,以filestore为例pg其实在osd的存在形式就是一个目录。其目录的命名规则为 {pool-id}.{pg-id}_head{pool-id}.{pg-id}.TEMP。如果你想找出一个pg对应哪些个osd,可以使用ceph pg map {pgid}的命令。

eg:

1
2
[root@ceph71 ~]# ceph pg map 1.5f
osdmap e30 pg 1.5f (1.5f) -> up [2,0,1] acting [2,0,1]

背景就是介绍这么多吧,接下来说说PG状态。

状态

状态 描述
active 当前拥有最新状态数据的pg正在工作中,能正常处理来自客户端的读写请求。
inactive 正在等待具有最新数据的OSD出现,即当前具有最新数据的pg不在工作中,不能正常处理来自客户端的读写请求。
activating Peering 已经完成,PG 正在等待所有 PG 实例同步并固化 Peering 的结果 (Info、Log 等)
clean pg所包含的object达到指定的副本数量,即object副本数量正常
unclean PG所包含的object没有达到指定的副本数量,比如一个PG没在工作,另一个PG在工作,object没有复制到另外一个PG中。
peering PG所在的OSD对PG中的对象的状态达成一个共识(维持对象一致性)
peered peering已经完成,但pg当前acting set规模小于存储池规定的最小副本数(min_size)
degraded 主osd没有收到副osd的写完成应答,比如某个osd处于down状态
stale 主osd未在规定时间内向mon报告其pg状态,或者其它osd向mon报告该主osd无法通信
inconsistent PG中存在某些对象的各个副本的数据不一致,原因可能是数据被修改
incomplete peering过程中,由于无法选出权威日志,通过choose_acting选出的acting set不足以完成数据修复,导致peering无法正常完成
repair pg在scrub过程中发现某些对象不一致,尝试自动修复
undersized pg的副本数少于pg所在池所指定的副本数量,一般是由于osd down的缘故
scrubbing pg对对象meta的一致性进行扫描
deep pg对对象数据的一致性进行扫描
creating pg正在被创建
recovering pg间peering完成后,对pg中不一致的对象执行同步或修复,一般是osd down了或新加入了osd
recovering-wait 等待 Recovery 资源预留
backfilling 一般是当新的osd加入或移除掉了某个osd后,pg进行迁移或进行全量同步
down 包含必备数据的副本挂了,pg此时处理离线状态,不能正常处理来自客户端的读写请求
remapped 重新映射态。PG 活动集任何的一个改变,数据发生从老活动集到新活动集的迁移。在迁移期间还是用老的活动集中的主 OSD 处理客户端请求,一旦迁移完成新活动集中的主 OSD 开始处理
misplaced 有一些回填的场景:PG被临时映射到一个OSD上。而这种情况实际上不应太久,PG可能仍然处于临时位置而不是正确的位置。这种情况下个PG就是misplaced。这是因为正确的副本数存在但是有个别副本保存在错误的位置上。

异常

active+undersized+degraded

若发现有osd挂掉,先尝试将osd重新拉起来,拉起来后集群会自动重新恢复健康状态。
但是也有可能出现这个osd再也起不来了,比如硬盘损坏了,这时多副本就发挥作用了,因为还有其它副本在其它osd上,这时我们可以通过均衡数据的方法来将集群恢复并将该osd踢出集群。

解决

  1. 将osd reweight权重置0,将数据分散到其他osd上 ceph osd reweight {osd-id} 0
  2. 待集群rebalance后,开始删除osd

unfound objects

ceph集群知道该对象存在,但无法定位该object在哪时会报这个错误。

解决

  1. 尝试让失败的osd起来,如果起来后集群恢复正常,则结束
  2. 试将该pg的unfound对象回滚到上一个版本,ceph pg {pgid} mark_unfound_lost revert如果恢复正常,则结束
  3. 如果还是不行,那只有将该object删除掉了,注意这会导致丢失数据,执行ceph pg {pgid} mark_unfound_lost delete删除unfound对象

inconsistent objects

pg中保存的object中有些副本数据不一致,有些事伴随着scrub errors错误

解决

  1. ceph health detail找出问题pg
  2. 尝试ceph pg repair {pgid},若成功,则结束;不成功进行如下操作。
  3. 使用ceph pg map {pgid}找出主osd,打开日志查看哪个object不一致
  4. 找出所有该objects所有副本存放的位置,用摘要算法(md5sum,sha256)等计算出其hash值,如果是3副本,删除与其他副本不一致的;如果是2副本,则可能会误删。
  5. 再次执行ceph pg repair {pgid}

stale pg

pg出现stale状态,也就是pg处于僵死状态,该状态是无法处理新的请求了的,新的请求过来只会block,这种情况一般是由于所有副本pg的osd都挂了。
Ceph使用心跳来确保主机和进程都在运行,OSD进程如果不能周期性的发送心跳包,那么PG就会变成stuck状态。默认情况下,OSD每半秒钟汇汇报一次PG,up thru,boot, failure statistics等信息,要比心跳包更会频繁一点。如果主OSD不能汇报给MON或者其他OSD汇报主OSD挂了,Monitor会将主OSD上的PG标记为stale。当启动集群后,直到peer过程完成,PG都会处于stale状态。而当集群运行了一段时间后,如果PG卡在stale状态,说明主OSD上的PG挂了或者不能给MON发送信息。

要模拟其实也很简单,比如设置2副本,然后将2个不同故障域的osd挂掉即可出现,最好的恢复方法当然是重新拉起这两个osd,但有时可能出现这样的情况,两个osd永远也拉不起来了,然后你把这两个osd清理出去了,清理完后这些pg当然就是stale的状态,这时的恢复方法只能是丢掉这个pg里的数据了,重新创建pg。

解决

  1. 使用命令ceph pg dump |grep stale找出所有的stale的pg,也可以ceph health detail | grep stale
  2. 执行ceph pg force_create_pg {pgid}命令强制重新创建pg,会看到pg转为creating状态
  3. 重启ceph中所有osd服务

Peered

Peering 已经完成,但是 PG 当前 Acting Set 规模小于存储池规定的最小副本数 (min_size)。
如果pool的副本数为3、min_size=2,停掉两个副本所在的osd,此时访问集群的客户端处于blocked状态。

解决

  1. 先尝试将down掉的两个osd恢复,或至少恢复一个。
  2. 若不能正常恢复,可修改min_size=1,解除客户端blocked状态

鸣谢&参考