osd: fix heartbeat brain-split behaviour

Yet another similar issue as 8d8e8a359c.
To reproduce, construct a cluster with 3 hosts, each containing a single osd only:
- cut off osd.1's cluster network, waiting osd.1 to be marked as down
- cut off both osd.2 & osd.3's cluster network

It is possible we'll get __two__ down osds (e.g., both osd.1 & osd.2 are down)
now and then restore osd.1 and osd.2's cluster network won't change anything.

The root cause is that by default we always call for at least 1/3 active heartbeat
connections with all current __up__ osds to bring a previously dead (unhealthy)
osd back to life. However, it is possible that the __up__ set could be the
minority part that has been cut off from the rest of the cluster entirely and hence
cause brain-split behaviour as demonstrated above.

The simplest way to fix is to try to re-activate an unhealthy osd whenever
we are still safe to do so. Also please keep in mind that frequent up-to-down
transitions will kill off the osd process entirely, and that is why the
```osd_markdown_log``` related checking is needed here..

Signed-off-by: xie xingguo <xie.xingguo@zte.com.cn>
This commit is contained in:
xie xingguo 2018-11-16 14:56:59 +08:00
parent 8d8e8a359c
commit 114c65fc0b

View File

@ -5619,8 +5619,17 @@ bool OSD::_is_healthy()
}
if (is_waiting_for_healthy()) {
utime_t now = ceph_clock_now();
utime_t grace = utime_t(cct->_conf->osd_max_markdown_period, 0);
while (!osd_markdown_log.empty() &&
osd_markdown_log.front() + grace < now)
osd_markdown_log.pop_front();
if (osd_markdown_log.size() <= 1) {
dout(5) << __func__ << " first time marked as down,"
<< " try reboot unconditionally" << dendl;
return true;
}
std::lock_guard l(heartbeat_lock);
utime_t now = ceph_clock_now();
int num = 0, up = 0;
for (map<int,HeartbeatInfo>::iterator p = heartbeat_peers.begin();
p != heartbeat_peers.end();