CephCIV · Multi-Tenancy in PracticeMulti-Tenancy in Practice
Operating CephFS subvolume tenancy over time
What you'll learn
- Manage subvolume lifecycle after creation
- Change a quota safely
- Handle snapshots per tenant
- Understand where CephFS quota enforcement actually happens
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
Subvolumes are easy to create and the operational questions arrive afterwards: growth, snapshots, and what happens at the limit.
Lifecycle after creation
ceph fs subvolume ls cephfs
ceph fs subvolume info cephfs acme-prod --group_name tenants
{
"bytes_quota": 5497558138880,
"bytes_used": 3211698176,
"path": "/volumes/tenants/acme-prod/<uuid>",
"mode": 16877,
"created_at": "2026-03-14 09:12:01"
}
# per-tenant usage across a group
ceph fs subvolume ls cephfs --group_name tenants --format json | python3 -c '
import sys,json,subprocess
for s in json.load(sys.stdin):
n = s["name"]
i = json.loads(subprocess.check_output(
["ceph","fs","subvolume","info","cephfs",n,"--group_name","tenants",
"--format","json"]))
q = i.get("bytes_quota") or 0
u = i.get("bytes_used") or 0
pct = (100.0*u/q) if isinstance(q,int) and q else 0
print("%-20s %8.1f GiB / %8.1f GiB %5.1f%%" %
(n, u/1024**3, (q/1024**3) if isinstance(q,int) else 0, pct))'
Changing a quota
ceph fs subvolume resize cephfs acme-prod 10995116277760 --group_name tenants
# removing the quota entirely
ceph fs subvolume resize cephfs acme-prod infinite --group_name tenants
| Change | Effect |
|---|---|
| Increasing | takes effect for clients as they refresh |
| Decreasing below current usage | existing data stays; new writes are refused |
infinite | no quota; the tenant is bounded only by the pool |
Decreasing below current usage does not delete anything. It stops
growth, which is usually what is wanted, and it does surprise a tenant
who expected an error at set time rather than at write time.
Snapshots per tenant
ceph fs subvolume snapshot create cephfs acme-prod snap-$(date +%Y%m%d) \
--group_name tenants
ceph fs subvolume snapshot ls cephfs acme-prod --group_name tenants
ceph fs subvolume snapshot info cephfs acme-prod snap-20260818 \
--group_name tenants
ceph fs subvolume snapshot rm cephfs acme-prod snap-20260701 --group_name tenants
Snapshot capacity is not free and is not counted against the subvolume
quota — it consumes pool capacity as the snapshotted data diverges.
ceph df detail
Where quota enforcement happens
CephFS quotas are enforced by the client, not by the MDS or the OSDs.
| Client | Enforces |
|---|---|
| Kernel client, recent | yes |
| ceph-fuse | yes |
| An old kernel client | may not |
| A client with a modified implementation | not necessarily |
ceph tell mds.0 client ls --format json | python3 -c '
import sys,json
for c in json.load(sys.stdin):
md = c.get("client_metadata", {})
print("%-18s %-14s %s" % (md.get("entity_id"), md.get("ceph_version","?")[:12],
md.get("hostname")))'
So a subvolume quota bounds a cooperating tenant. A pool quota, enforced
at the cluster, bounds any tenant.
Quiz
Knowledge check · 4 questions
Q1. Where are CephFS quotas enforced?
Q2. A tenant on a modest subvolume quota can occupy far more pool capacity than that quota suggests.
Q3. Reduce a tenant's CephFS quota.
A tenant's subvolume quota needs reducing from 10 TiB to 5 TiB. They currently use 7 TiB.
Q4. What bounds a non-cooperating tenant that a subvolume quota does not?
Passing score: 75%. Answers are checked in this browser.
Production discipline
Use a per-tenant pool with a pool quota where the boundary must hold regardless of client behaviour — CephFS subvolume quotas are enforced by the client. Track snapshot retention separately; snapshots consume pool capacity without counting against the subvolume quota.
Cross-course references
- Kubernetes: ResourceQuota is enforced by the API server, not the workload
- Linux: a limit the client enforces bounds cooperation, not capability