Skip to main content
RunBook Academy

CephCIV · Multi-Tenancy in PracticeMulti-Tenancy in Practice

What happens when a tenant hits their limit

Advanced⏱ ~18 mincephradosgw-admin

What you'll learn

  • Describe the behaviour at each quota layer
  • Alert before the limit rather than at it
  • Respond to a tenant at their limit
  • Choose limits that fail gracefully

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

Quotas behave very differently by layer, and the RADOS pool quota is the one that fails hardest.

Behaviour at each layer

LayerAt the limitClient sees
Pool quota (max_bytes)writes blockedRBD I/O hangs; RADOS writes block
CephFS subvolume quotawrites refusedEDQUOT — disk quota exceeded
RGW user or bucket quotawrites refusedHTTP 403 QuotaExceeded
RBD image sizewrites beyond the end refusedthe filesystem sees a full device
ceph osd pool get-quota tenant-acme
ceph df detail | grep -A2 tenant-acme
The pool quota is the harsh one: for RBD, a blocked write is a hung
I/O, and a guest filesystem in uninterruptible wait does not report
"quota exceeded" — it stops.
ceph -s
ceph health detail | grep -i -E 'quota|full'

Alerting before the limit

The alert that matters fires at a threshold below the limit, not at it.
- alert: TenantPoolQuotaApproaching
  expr: |
    (ceph_pool_bytes_used / on(pool_id) ceph_pool_quota_bytes) > 0.80
    and on(pool_id) ceph_pool_quota_bytes > 0
  for: 30m
  labels: { severity: warning }
  annotations:
    summary: "Pool {{ $labels.name }} is above 80% of its quota"
- alert: TenantPoolQuotaCritical
  expr: |
    (ceph_pool_bytes_used / on(pool_id) ceph_pool_quota_bytes) > 0.95
    and on(pool_id) ceph_pool_quota_bytes > 0
  for: 10m
  labels: { severity: critical }
# a manual sweep of every quota'd pool
ceph df detail --format json | python3 -c '
import sys,json
for p in json.load(sys.stdin)["pools"]:
    q = p.get("stats", {}).get("quota_bytes") or 0
    u = p.get("stats", {}).get("stored", 0)
    if q:
        print("%-24s %6.1f%%  %8.1f / %8.1f TiB" %
              (p["name"], 100.0*u/q, u/1024**4, q/1024**4))'

Responding to a tenant at their limit

ceph osd pool get-quota tenant-acme
ceph df detail | grep tenant-acme
SituationResponse
Growth was expectedraise the quota; capacity exists
Growth was not expectedinvestigate before raising
The cluster has no headroomraising the quota moves the problem
The tenant can delete datalet them; the block clears
The tenant is stuck in hung I/Oraise the quota to unblock, then investigate
ceph osd pool set-quota tenant-acme max_bytes $((15 * 1024**4))
Raising a pool quota takes effect immediately and unblocks hung writes,
which makes it the fastest way to end an incident — and the reason to
have an approval path agreed in advance rather than during one.

Choosing limits that fail gracefully

Prefer a limit whose breach produces an error over one that produces a
hang.
PreferenceWhy
RBD image size as the tenant limitthe guest filesystem reports full
CephFS subvolume quotaEDQUOT is a normal error applications handle
RGW quota403 is a normal S3 response
Pool quota as a backstop onlyit hangs I/O; use it above the per-tenant limits
Set the pool quota as a cluster-protecting ceiling and enforce the
tenant's actual limit at the layer that returns an error.

Quiz

Knowledge check · 4 questions

  1. Q1. What does a guest filesystem experience when its RBD pool reaches its quota?

  2. Q2. A tenant limit belongs above the pool layer, because that is where exhaustion produces an error a client can act on.

  3. Q3. Design tenant limits that fail gracefully.

    Tenants receive RBD storage. The current design enforces each tenant's capacity with a pool quota on their pool.

  4. Q4. Why should a quota alert fire below the limit rather than at it?

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

Production discipline

Set the tenant’s effective limit at a layer that returns an error — RBD image size, subvolume quota, or RGW quota — and keep the pool quota as a cluster-protecting ceiling above it. A pool at quota hangs RBD I/O rather than erroring, and guests cannot handle that.

Cross-course references

  • Kubernetes: a limit that OOM-kills differs from one that rejects admission
  • Linux: a limit that blocks is operationally worse than one that errors