Skip to main content
RunBook Academy

CephLXXX · Blocked OperationsBlocked Operations

Blocked by insufficient available copies

Advanced⏱ ~18 minceph

What you'll learn

  • Recognise a min_size violation
  • Establish which PGs and which pools are affected
  • Evaluate the options for restoring I/O
  • Weigh the durability trade of lowering min_size

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

A PG below min_size blocks I/O to the data it holds. It is the most common cause of a genuine Ceph outage and the response involves a durability decision.

Recognising it

ceph -s
ceph health detail | grep -E 'PG_AVAILABILITY|PG_DEGRADED'
ceph pg dump pgs | awk '$10 !~ /active/ {print $1, $10, $15}' | head
pg 3.1f is stuck inactive+undersized+degraded, acting [12,2147483647,2147483647]

The 2147483647 entries are the NONE sentinel: those positions in the acting set have no OSD. One surviving copy on a min_size=2 pool means the PG cannot serve I/O.

ceph osd pool get rbd-vms size
ceph osd pool get rbd-vms min_size

Establishing the scope

# which PGs?
ceph pg dump pgs | awk '$10 ~ /inactive|down|incomplete/ {print $1}' | wc -l

# which pools?
ceph pg dump pgs | awk '$10 ~ /inactive|down|incomplete/ {split($1,a,"."); print a[1]}' | \
  sort -u | while read id; do
    ceph osd pool ls detail | grep "^pool $id " | awk '{print $3}'
  done

# which OSDs would restore them?
ceph pg 3.1f query | python3 -c '
import sys,json; d=json.load(sys.stdin)
print("up:", d.get("up"), "acting:", d.get("acting"))
for s in d.get("recovery_state", [])[:1]:
    print(s.get("name"), s.get("blocked_by"))'

blocked_by names the OSDs the PG is waiting for, which is the shortest path to restoring it.

The options

OptionEffectRisk
Restore the missing OSDsfull recoverynone, if they can be restored
Restore one missing OSDreaches min_size, I/O resumesnone
Lower min_size to 1I/O resumes with one copyany error on that copy loses data
Mark the OSDs lostallows peering to proceeddata on them is discarded
Restore from backupfull data recoverydata loss since the backup
# preferred: bring the OSDs back
FSID=$(ceph fsid)
systemctl start "ceph-$FSID@osd.31"
ceph osd in 31

Lowering min_size

ceph osd pool set rbd-vms min_size 1
# ... I/O resumes ...
# and afterwards, without fail:
ceph osd pool set rbd-vms min_size 2

The trade is explicit: I/O resumes immediately, and the surviving copy has no redundancy — a read error on it loses that data with nothing to recover from, and a scrub inconsistency has no majority.

Record before doing it:
  pool, previous min_size, time changed, who authorised, restoration condition

Marking OSDs lost

ceph osd lost 31 --yes-i-really-mean-it

This tells the cluster the OSD’s data is gone permanently, allowing PGs to peer without it. Any writes that existed only on that OSD are lost. It is a last resort and is not reversible.

Quiz

Knowledge check · 4 questions

  1. Q1. Why does Ceph block I/O below `min_size` rather than serving from fewer copies?

  2. Q2. Marking an OSD lost lets its PGs peer again by asserting that writes held only on that OSD will never return.

  3. Q3. Restore I/O to a blocked pool.

    A pool with size=3, min_size=2 has PGs with one surviving copy after two OSDs failed. I/O to those PGs is blocked. One of the failed OSDs may be recoverable; the other is not.

  4. Q4. What does the value 2147483647 in an acting set mean?

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

Production discipline

Restore a missing OSD rather than lowering min_size where the OSD can be recovered in an acceptable time — it resumes I/O with no durability trade. When lowering is necessary, record the pool, the previous value, the authorisation, and the restoration condition before making the change.

Cross-course references

  • Kubernetes: refusing to serve from a quorum-less replica set follows the same reasoning
  • Linux: a RAID array refusing to assemble degraded beyond tolerance is the analogue