暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

记一次ceph osd出现no reply的问题排查

翼起云桌面 2020-08-12
4111

1.问题描述

在某些ceph测试池,经常出现osd心跳no reply的日志导致osd down或者心跳超时问题,平常情况下怀疑与网络丢包有关。某些环境网络下也确实发生丢包导致该问题复现,但是有些环境在ping测不丢包的情况下,也出现了心跳no reply的情况


2.排查过程

2.1 网络侧排查

通过ansible对所有osd节点根据关键词“no reply”进行查找日志,找出其中发生心跳没响应的两个osd节点,通过日志可以判断为该osd没有收到241节点的心跳响应,对两个节点所在的主机进行ip a查看网络配置情况,怀疑网络问题导致心跳丢包(该问题在其他环境下发生过,所以初步怀疑网络问题)。

通过在两个主机上进行ping测试和iperf进行测试,测试结果发现两个节点之间并没有丢包。网络侧应该没有问题,怀疑是否主机防火墙策略导致心跳包拦截,但是通过排查主机防火墙,两个主机都是关闭了防火墙,所以不存在拦截问题。

由于网络和防火墙都没有问题,怀疑是否osd问题,所以需要查看ceph osd 代码,了解具体的心跳机制,才能继续排查问题。


2.2 ceph osd 心跳机制解读

ceph osd在启动过程中,osd->init()中采用了单独线程heartbeat_thread.create("osd_srv_heartbt")发送心跳问题。其中心跳入口为OSD::heartbeat_entry(),该函数主要为定期(或者加随机参数)发送心跳(执行heartbeat()函数)


函数说明:

  • heartbeat函数:该函数主要获取cpu负载,遍历osd的所有heartbeat_peers,对每个peers构造OSDPing类的PING包,通过con_back进行发送,若有con_front,同时也发送。并将该心跳消息加入ping_history中。如果peers为空,则只需跟mon节点发送消息

  • heartbeat_dispatch函数:该函数主要为osd接收消息的处理函数,osd通过注册dispatcher来处理接收的message,该函数中根据message的类型进行不同处理,对于ping包,则交给handle_osd_ping函数来处理

  • handle_osd_ping函数:该函数主要对messager类接收到的MOSDPing消息类型进行不同处理,先检查集群情况,然后分为3种情况处理,1、接收到为MOSDPing:PING,则回复MOSDPing:REPLY包,2、如果接收到为MOSDPing:REPLY,在heartbeat_peers中找对应的peer,根据ping_histroy中的记录,确定需要心跳响应的数量,每收到一个响应后自减,如果全部心跳都接收到,则将该心跳以及之前所有的其他旧的心跳从ping_history中去掉。收到心跳响应后,判断是否超时,不超时则从failure_pending和failure_queue中删除该响应心跳的osd。取消上报mon 3、如果接收到MOSDPing:DIE,则重新更新osdmap

  • tick_without_osd_lock函数:该函数主要调用heartbeat_check检查心跳是否超时

  • heartbeat_check函数:该函数主要遍历heartbeat_peers,对于没有发送过ping包的osd,跳过,检查当前时间对应的peer的heartbeatinfo是否healthy,若不健康,则输出日志以及加入failure_queue,判断是否healthy根据ping_history中最老的deadline时间,如当前时间大于deadline,则不健康。

  • maybe_update_heartbeat_peers函数:该函数主要工作为更新osd的heartbeat_peers,主要步骤为:

    • i.遍历osd上pg对应的up的peer将其加入heartbeat_peer;

    • ii.遍历probe集合且up的peer将其加入到heartbeat_peer;

    • iii.定义了两个集合, 一个是want, 一个是extras, want为获取当前osd的前一个和后一个up的osd,主要采用两个函数: get_next_up_osd_after(whoami)、get_previous_up_osd_before(whoami), 分别是比当前osd id大的处于up的第一个osd; 比osd id小的第一个up osd, 将want加入heartbeat中,同时插入extras,将heartbeat_peers中所有osd down的peer移除掉,如果osd为up,但是heartbeat_peers记录的osd epoch小于集群的osd epoch,则加入extras,extras主要对hearbeat_peers进行判断是否需要剔除。

    • iv.根据heartbeat_peers中的数量和osd_heartbeat_min_peers对比,如peers数量不够,则继续调用get_next_up_osd_after获取下一个up的osd,加入heartbeat_peers和extras中(原本不在这两个集合里面且不是本osd),直到满足条件或者所有osd都遍历,如peers数量大于min_peers,若peer不在want集合里,则从heartbeat_peers中remove

peers的更新时机,主要是在pgmap变更时,具体有以下三处地方:

  • pg创建的时候,参见handle_pg_create;

  • osdmap变更时,参见handle_osd_map;

  • tick定时器会周期性的检测;

Ceph osd启动时候,会注册相应的4个心跳messager,分别为:

  • hb_front_client_messenger

  • hb_back_client_messenger

  • hb_front_server_messenger

  • hb_back_server_messenger

并向heartbeat_dispatcher注册,这4个messager关系如下:

通过上面描述可见,两个osd心跳机制,周期性或者强制执行heartbeat和handle函数来处理发送和接收message。根据函数打印的日志,我们可以判别是否网络问题还是osd问题,从该日志对应的代码上来看,就是发出的心跳包中,至少有一个心跳包在osd第一次发送心跳时候就没有收到reply响应:

由于代码上看,osd的ping包机制没有什么问题,也没有太多日志可以分析,考虑采用tcpdump抓包方式来分析,但由于osd的ping包不同于我们icmp协议的ping包,本身是对消息封装后信息,所以比较难以过滤出ping包,所以抓包后放弃该方式的分析,采用继续从发送包时候和接收包时候的机制的代码去分析,看是否有相关的日志可以提取,由于L版osd默认采用async方式进行数据封装,所以在调用send_message时候,采用为async connection进行发送,采用async connection部分的代码,发现其日志主要在ms模块:

所以对没有心跳的两个主机之间采用启动30/30的日志等级输出日志:

ceph tell osd.xx injectargs '--debug_ms 30/30'

主要为调高对应日志等级,然后对输出的日志进行分析。由于ms模块日志的输出没有osd.xx字样,所以无法通过osd来对日志进行过滤,需要采用ip和port方式来进行过滤,通过ps查看对应osd的pid,然后执行
netstat –nlp | grep pid查看具体osd在日志中的ip和端口,对日志进行过滤,从日志中可以看出,失败原因主要是在connection进行连接时候,对端报连接失败导致。如下日志:

从日志描述上看,是存在冲突的连接,所以导致本次连接失败,通过该报错日志,在ceph tracker里可以找到关于该async连接的issue:https://tracker.ceph.com/issues/38493

从ceph github上面可以看出ceph对该方面的修复记录,其中在https://github.com/ceph/ceph/pull/27583/commits上,看到了该问题的修复,该问题主要是修复对连接竞争成功的winner增加一个keepalive,避免竞争成功的winner在没有连接完全成功的时候进入stanby状态,避免该问题的发生。从ceph L版本的修复上看,还存在另一个问题会导致async连接失败,由于该bug修复在12.2.13版本上,所以升级到12.2.13解决该问题,同时也解决当前版本其他存在的问题


2.3 解决方法

2.3.1 彻底解决方法

由于该问题是L版12.2.11之前存在的bug,在12.2.13版本后才解决该bug,需要对集群进行升级版本来彻底解决该bug,同时12.2.13相对于12.2.11版本上也更新解决不少其他的问题,所以通过升级到L版本的最新版可以解决。


2.3.2 临时解决方法

临时解决可以通过对osd进行重启,重新建立连接来解决no reply问题。


3.问题总结

测试资源池的no reply告警是由于12.2.11版本使用的async messager在建立连接时候代码bug导致(在网络比较差的情况下容易复现),临时解决方法可以通过重启OSD重置连接解决,彻底解决需要升级Ceph至12.2.13版本。


文章转载自翼起云桌面,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论