Skip to main content
RunBook Academy

CephCXII · OSD Host LossOSD Host Loss

Deciding whether to let recovery start

Intermediate⏱ ~18 minceph

What you'll learn

  • Explain what the down-out interval buys
  • Quantify the data a recovery would move
  • Choose between cluster-wide and per-OSD noout
  • Recognise when waiting stops being cheaper

Prerequisites

None — start here.

Verified against Ceph Tentacle 20.2.x · Ceph Squid 19.2.x (supported previous) · cephadm matches the verified Ceph release · podman 4.x · csi-rbd and csi-cephfs current · RBD / CephFS / RGW current (matches Ceph release) · Linux kernel 5.15+ (5.10 minimum) · Ubuntu 24.04 LTS (Ceph host baseline) · Debian 12 (Bookworm) (Ceph host baseline) · Rocky Linux / RHEL / AlmaLinux 9.x (Ceph host baseline) · Proxmox VE 9.x (cross-course integration) · Kubernetes 1.31+ (cross-course integration) · 2026-08-18

Not yet marked complete on this device.

Why this matters in production

Recovery moves the failed host’s entire data footprint twice if the host comes back, and moves nothing if you guess the repair time correctly.

The timer

ceph config get mon mon_osd_down_out_interval        # 600
ceph config get mon mon_osd_down_out_subtree_limit   # rack
ElapsedState
0–20speers report; monitors mark the OSDs down
20s–10mindown and in; degraded, no data movement
10minmonitors mark the OSDs out; backfill begins
after backfillcopies restored elsewhere; the host holds stale data
The subtree limit is `rack` by default, so a whole host is marked out
automatically and a whole rack is not.

What recovery would cost

ceph osd df tree
ceph osd ls-tree ceph-osd-07 > /tmp/lost-osds
ceph osd df --format json | python3 -c '
import sys,json
ids = set(int(x) for x in open("/tmp/lost-osds").read().split())
n = [o for o in json.load(sys.stdin)["nodes"] if o.get("device_class")]
used = sum(o["kb_used"]  for o in n if o["id"] in ids) / 1024**2
free = sum(o["kb_avail"] for o in n if o["id"] not in ids) / 1024**2
print("to re-replicate: %8.1f GiB" % used)
print("headroom left:   %8.1f GiB" % free)
print("survivors:       %8d OSDs" % len([o for o in n if o["id"] not in ids]))'

Choosing the scope

ceph osd set noout            # every OSD in the cluster
ceph osd unset noout
# only this host's OSDs
for id in $(ceph osd ls-tree ceph-osd-07); do ceph osd add-noout osd.$id; done
ceph osd dump | grep -c noout
for id in $(ceph osd ls-tree ceph-osd-07); do ceph osd rm-noout osd.$id; done
SituationDecision
PSU swap or reboot, engineer on siteper-OSD noout, wait
Repair time unknownno flag; let the interval run
Remaining tolerance is one failure domainlet recovery run regardless of repair time
Cluster above 75% usedassess capacity before allowing recovery
Host confirmed deadno flag; recovery is the correct outcome
High write rate on the affected poolswaiting loses value quickly

When waiting stops paying

ceph config get osd osd_min_pg_log_entries   # 250
ceph config get osd osd_max_pg_log_entries   # 10000
A returning OSD replays the PG log if its copy is still within the
retained window. Past that, it copies whole PGs. The window is counted in
log entries, not in minutes.
watch -n 30 'ceph -s | grep -E "degraded|recovery|misplaced"'

Quiz

Knowledge check · 4 questions

  1. Q1. What determines whether a returning OSD replays its PG log rather than copying whole PGs?

  2. Q2. Setting noout cluster-wide also prevents an unrelated OSD elsewhere in the cluster from being marked out.

  3. Q3. Decide whether to set noout after a host failure.

    A host with 12 OSDs holding 41 TiB raw is unreachable. The data centre reports a failed PSU with a replacement arriving in roughly four hours. The cluster is at 68% used and the pools take a steady 4000 writes per second.

  4. Q4. Why is per-OSD noout preferable to the cluster-wide flag?

Passing score: 75%. Answers are checked in this browser.

Production discipline

Decide the wait-or-recover question against repair time, remaining tolerance, and write rate — not against the ten-minute default alone. Scope the suppression with ceph osd add-noout rather than the global flag, and tie clearing it to the same change window that set it.

Cross-course references

  • Kubernetes: pod eviction timeouts make the same bet on how long a node will be absent
  • Linux: a global maintenance flag left set becomes the next incident