runsisi's

technical notes

ceph-mgr PG stat

2019-02-27 runsisi#ceph

在 Luminous 版本之前,mon 中有一个 PGMonitor paxos 模块,专门用于统计 PG、存储池相关的各种信息,在 Luminous 中引入了 ceph-mgr 守护进程,这些统计相关的工作都转交给 mgr 进行处理,同时在 mon 中又新引入了一个 MgrStatMonitor paxos 模块。

出于兼容性考虑,Luminous 版本仍然保留了 PGMonitor 模块,为了统一新老代码,在 mon 中引入了 MonPGStatService 中间层,如下所示:

OSDMonitor::update_from_paxos
  // make sure we're using the right pg service.. remove me post-luminous!
  if (osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) {
    dout(10) << __func__ << " pgservice is mgrstat" << dendl;
    mon->pgservice = mon->mgrstatmon()->get_pg_stat_service();
  } else {
    dout(10) << __func__ << " pgservice is pg" << dendl;
    mon->pgservice = mon->pgmon()->get_pg_stat_service();
  }

在 Luminous 版本及以后,MonPGStatService 中间层的实例指向 MgrPGStatService:

MgrStatMonitor::get_pg_stat_service
  new MgrPGStatService

而 Luminous 版本之前,MonPGStatService 中间层的实例指向 PGMonStatService:

PGMonitor::get_pg_stat_service
  new PGMonStatService

这里几个类的命名比较混乱,导致相互之间的关系显得非常混乱:

PGMapStatService : public PGStatService

MonPGStatService : public PGStatService
MgrPGStatService : public MonPGStatService
PGMonStatService : public MonPGStatService, public PGMapStatService

但实际上这是因为代码复用导致的,由于我们不用关心 PGMonStatService,因此类之间的关系简化如下:

PGMapStatService : public PGStatService

MonPGStatService : public PGStatService
MgrPGStatService : public MonPGStatService

mon 中的 pgservice 指针成员变量指向 MgrPGStatService 实例,mgr 中 ClusterState 的成员变量 pgservice 指向 PGMapStatService 实例。

PGMapStatService 中有一个 const 引用成员变量指向一个外部的 PGMap 变量,在 mgr 中就是 ClusterState 的成员变量 ClusterState::pg_map,所有 PG 的相关的信息都是通过更新 PGMap 得到的,PGMapStatService 只是一个对外的 wrapper 而已。

在 mon 中 PGMonStatService 之所以需要继承 PGMapStatService 就是需要得到它的 const 引用成员变量 PGMapStatService::pgmap,而这个引用成员变量指向 PGMonitor 的成员变量 PGMonitor::pg_map,当然 PGMonitor、PGMonStatService 以及相关的代码在 Luminous 之后的版本中都已经不复存在。

下面分别站在 mgr 和 mon 两个角度,来分析 PG 信息是如何从各 OSD 收集、汇总并持久化的。

mgr

PG 相关的信息都保存在 ClusterState 中:

class ClusterState
{
protected:
  ...
  set<int64_t> existing_pools; ///< pools that exist, as of PGMap epoch
  PGMap pg_map;
  PGMap::Incremental pending_inc;
  map<pg_t, utime_t> pending_stale;

  PGMapStatService pgservice;
  ...
};

其中 ClusterState::pg_map 的更新有两个途径:

ClusterState::ingest_pgstats
ClusterState::notify_osdmap

即根据单个 OSD 上报的消息 MPGStats 以及集群的 osdmap 的变化进行相应的更新。

mon

mon 中的 PG 汇总信息由 mgr 定时上报:

void Mgr::tick() {
  server.send_report();
}

上报消息类型为 MMonMgrReport,上报的信息包括 PGMapDigest、health check 以及 service map,mon 在 MgrStatMonitor::prepare_report 中对这些信息进行处理。

上报的信息保存在如下成员变量中:

class MgrStatMonitor : public PaxosService {
  // live version
  version_t version = 0;
  PGMapDigest digest;
  ServiceMap service_map;

  // pending commit
  PGMapDigest pending_digest;
  health_check_map_t pending_health_checks;
  bufferlist pending_service_map_bl;
  ...
};

其中那些 pending 的信息将通过 paxos 进行持久化。