Skip to main content
RunBook Academy

CephXXII · PG InvestigationPG Investigation

Cluster-wide PG state: pg stat, pg dump, health detail

Intermediate⏱ ~16 mincephjq

What you'll learn

  • Read the summary line from ceph pg stat
  • Filter ceph pg dump for specific PG states
  • Use ceph health detail to enumerate stuck PGs
  • Choose the right level of detail for the question at hand

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

During an incident you need three different things at three different moments: a number (“is it getting better?”), a list (“which ones?”), and a reason (“why these?”). Reaching for pg dump when you wanted a count buries you in output; reaching for pg stat when you needed the list leaves you guessing.

The count

ceph pg stat
# 4096 pgs: 3987 active+clean, 102 active+recovering+degraded, 7 active+remapped+backfilling;
# 184 TiB data, 552 TiB used, 411 TiB / 963 TiB avail; 1.2 MiB/s rd, 44 MiB/s wr

One line, refreshable, ideal in a watch. The question it answers is “is the degraded count falling?” — and if it is not falling over several minutes, you escalate to the list.

The list

# every PG not in active+clean
ceph pg dump_stuck

# specific stuck categories
ceph pg dump_stuck inactive
ceph pg dump_stuck unclean
ceph pg dump_stuck stale
ceph pg dump_stuck undersized
ceph pg dump_stuck degraded

dump_stuck is the right first list because it already filters. The full pg dump is enormous — every PG in the cluster — and is worth it only when you need fields dump_stuck omits:

ceph pg dump --format json | \
  jq -r '.pg_map.pg_stats[] | select(.state | test("backfill_toofull")) |
         "\(.pgid)  \(.state)  up=\(.up)  acting=\(.acting)"'

The three stuck categories mean different things:

CategoryMeaningUrgency
inactivenot serving I/Ohighest — clients are blocked
uncleannot fully replicatedhigh — durability reduced
staleno report from the primaryinvestigate the primary OSD

The triage

ceph health detail
HEALTH_WARN Degraded data redundancy: 41213/18442104 objects degraded (0.223%), 102 pgs degraded
[WRN] PG_DEGRADED: Degraded data redundancy: 41213/18442104 objects degraded (0.223%), 102 pgs degraded
    pg 7.1a is active+recovering+degraded, acting [12,47]
    pg 7.3d is active+recovering+degraded, acting [12,83]
    pg 7.55 is active+recovering+degraded, acting [12,91]

This is the most useful of the three during an incident because it groups by reason, not by PG, and because the acting sets are right there. In the output above, osd.12 appears in every line — that is your answer, and it took one command.

Quiz

Knowledge check · 4 questions

  1. Q1. You need to know which specific PGs are not serving client I/O right now. Which command is the most direct?

  2. Q2. A PG reported as stale means its data has been confirmed lost.

  3. Q3. Triage a large-scale degradation efficiently.

    `ceph -s` shows 380 PGs degraded and 11 PGs inactive after what should have been a routine host reboot. You have a paging alert and a hundred PG ids in front of you.

  4. Q4. Why is `ceph health detail` usually more useful than `ceph pg dump` during an active incident?

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

Production discipline

Keep a watch -n 5 'ceph pg stat' running in one pane during any recovery so the trend is always visible, and use the other pane for lists and detail. The trend line is what tells you whether an intervention helped; snapshots of state do not. Save the health detail output at the start of an incident — the reason grouping is the clearest record of what the cluster looked like before you touched it.

Cross-course references

  • Kubernetes: kubectl get pods --field-selector status.phase!=Running is the same filter-first instinct
  • Linux: dmesg | grep -c for a count then the full log for detail is the identical escalation