CephLXXIX · Slow OpsSlow Ops
Slow ops originating at the client
What you'll learn
- Recognise client-side causes of apparent cluster slowness
- Establish that the client is the source
- Diagnose the specific client-side cause
- Distinguish client from cluster definitively
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
A substantial share of “Ceph is slow” reports originate above Ceph. The cluster’s own metrics look healthy, which makes the investigation frustrating until the client is checked.
What the cluster sees
A slow client produces no SLOW_OPS at all: operations arrive at the OSD
and complete normally. The cluster is healthy because it is.
ceph -s
ceph osd perf | sort -k2 -rn | head -3
ceph health detail
All clean, while the client reports poor performance. That combination is the signal.
Establishing the client is the source
# from a second, independent client host
fio --name=probe --ioengine=rbd --pool=rbd-vms --rbdname=probe \
--rw=randread --bs=4k --iodepth=16 --runtime=60 --time_based
| Result | Conclusion |
|---|---|
| Second client fast | the first client is the source |
| Second client also slow | the cluster or the shared path |
One test, ten minutes, and half the possibilities are eliminated.
The client-side causes
| Cause | Evidence |
|---|---|
| CPU saturation | mpstat, top -H on the client |
| CPU steal on a VM | mpstat steal column |
| Memory pressure or swap | free -g, vmstat |
| Single-threaded workload | low queue depth, low utilisation everywhere |
| Client cache misconfiguration | rbd config image ls |
| Objecter throttle reached | op_active at the limit |
| Client network path | interface counters, retransmits |
| Guest filesystem issues | fragmentation, mount options |
# librbd client state
ceph --admin-daemon /var/run/ceph/ceph-client.*.asok perf dump objecter | \
python3 -c '
import sys,json; d=json.load(sys.stdin)["objecter"]
print("op_active:", d.get("op_active"), "op_laggy:", d.get("op_laggy"))'
ceph config get client objecter_inflight_ops
op_active sitting at the configured limit means the client is
throttling itself.
The definitive distinction
# 1. cluster-side latency, from the cluster's own view
ceph osd perf | awk 'NR>1 {s+=$2; n++} END {print "avg", s/n, "ms"}'
# 2. client-observed latency
fio ... --percentile_list=50:99
# 3. the gap
A large gap between the two is time spent above the OSDs — in the client, its queueing, or the network. A small gap means the cluster is the delay.
# and check the client is not simply idle
mpstat -P ALL 1 5
iostat -x 1 5 # inside the guest, for RBD
Quiz
Knowledge check · 4 questions
Q1. A client reports poor performance while the cluster shows healthy OSD latency and no SLOW_OPS. What does this combination indicate?
Q2. CPU steal on a client VM is visible in the guest's CPU utilisation figures.
Q3. Triage a performance complaint.
A team reports that Ceph is slow for their application. Cluster health is HEALTH_OK, OSD latency is normal, and no slow ops are reported.
Q4. What does `op_active` sitting at `objecter_inflight_ops` indicate?
Passing score: 75%. Answers are checked in this browser.
Production discipline
Run the same test from a second client host before investigating the cluster — a healthy cluster with a slow client is the signature of a client-side cause, and the second test confirms it in one step. Check CPU steal explicitly on virtualised clients; it produces storage-like symptoms and appears nowhere in storage metrics.
Cross-course references
- Kubernetes: a slow pod on a contended node presents as a slow backend
- Linux: application-side scheduling delay is routinely misattributed to I/O