CephXLVIII · RGW TroubleshootingRGW Troubleshooting
When the pools behind RGW are the problem
What you'll learn
- Map gateway errors to pool conditions
- Identify which pool a failing operation depends on
- Respond to full and slow pools
- Verify pool health from the gateway's perspective
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
Why this matters in production
The gateway reports HTTP errors; the cause is frequently a pool beneath it. Mapping the failing operation to the pool it depends on is what turns a 500 into a specific capacity or latency problem.
Which operation depends on which pool
| Operation | Pools involved |
|---|---|
PUT small object | data, index, meta |
PUT multipart | data, index, non-ec |
GET | data |
LIST | index |
DELETE | index, plus gc |
| Create bucket | meta, index |
| Create user | meta |
So a deployment where GET works and PUT fails points at the index or
non-ec pool rather than the data pool.
Pool conditions and their gateway symptoms
| Pool condition | Gateway symptom |
|---|---|
| Data pool full | PUT fails 500; GET works |
| Index pool full | all writes fail; GET works |
| Index pool slow | LIST and PUT slow; transfers fine |
| non-ec pool missing or full | multipart fails; small PUT works |
| Meta pool full | user and bucket operations fail |
| PGs inactive in any pool | operations touching it hang or 500 |
Checking
ceph -s
ceph df | grep rgw
ceph health detail | grep -i full
radosgw-admin zone get --rgw-zone=default | \
jq -r '.placement_pools[].val | {index_pool, storage_classes, data_extra_pool}'
for p in $(ceph osd pool ls | grep rgw); do
printf '%-40s ' "$p"
ceph osd pool stats "$p" | tail -1
done
Responding to a full pool
# where is the fullness?
ceph osd df | sort -k17 -rn | head
# rebalance before anything else
ceph osd reweight-by-utilization 110
ceph balancer status
# reclaim: garbage collection may be behind
radosgw-admin gc list --include-all | jq 'length'
radosgw-admin gc process --include-all
# reclaim: incomplete multipart uploads
radosgw-admin bucket list | jq -r '.[]' | while read b; do
radosgw-admin bucket check --bucket="$b" 2>/dev/null | grep -i multipart
done
Garbage collection lagging is a common and easily-missed cause: deleted objects are queued for removal and the queue can grow faster than it drains, so capacity does not return.
ceph config get client.rgw rgw_gc_max_concurrent_io
ceph config get client.rgw rgw_gc_processor_period
Verifying from the gateway’s perspective
ceph config set client.rgw debug_rgw 10
ceph config set client.rgw debug_rados 5
# reproduce the failing operation
ceph config set client.rgw debug_rgw 1
The gateway log shows which RADOS operation failed and against which pool, which settles the mapping definitively.
Quiz
Knowledge check · 4 questions
Q1. Multipart uploads fail while small PUTs and GETs succeed. Which pool should you check?
Q2. Capacity is reclaimed immediately when S3 objects are deleted.
Q3. Investigate a pool that stays full after a large cleanup.
A team deleted 30 TB of objects to relieve a nearfull data pool. A day later the pool utilisation is unchanged and writes are still failing. The objects no longer appear in listings.
Q4. Why are RGW object deletions asynchronous?
Passing score: 75%. Answers are checked in this browser.
Production discipline
Map the failing operation to the pools it depends on before investigating; which operations work is as informative as which fail. Check the garbage collection backlog whenever capacity does not return after a deletion — it is the most common reason a cleanup appears to have done nothing.
Cross-course references
- Kubernetes: finalizers deferring actual deletion produce the same gone-but-not-freed behaviour
- Linux: unlinked files held open by a process behave identically from a capacity perspective