Skip to main content
RunBook Academy

CephCIV · Multi-Tenancy in PracticeMulti-Tenancy in Practice

Tenant onboarding as a repeatable procedure

Advanced⏱ ~18 mincephrbd

What you'll learn

  • Define what onboarding creates
  • Establish naming conventions that survive scale
  • Script the procedure
  • Verify a tenant before handing it over

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

Tenants provisioned by hand differ from one another in ways that surface months later as inconsistent quotas, orphaned entities, and pools nobody can attribute.

What onboarding creates

ObjectPer tenant
A pool, or a namespace within a shared poolone
A cephx entity scoped to itone, or one per environment
A quotaon the pool or namespace
An application tagso ceph df and health checks attribute correctly
A register entryowner, purpose, review date
Monitoring labelsso per-tenant dashboards exist from day one
ceph osd pool create tenant-acme 128
ceph osd pool application enable tenant-acme rbd
ceph osd pool set-quota tenant-acme max_bytes $((10 * 1024**4))
ceph auth get-or-create client.tenant-acme \
  mon 'profile rbd' \
  osd 'profile rbd pool=tenant-acme' \
  mgr 'profile rbd pool=tenant-acme'

Naming conventions

A convention that survives scale encodes:
  the tenant
  the environment
  the service type
PatternExample
<tenant>-<env>-<type>acme-prod-rbd
Entity matching the poolclient.acme-prod-rbd
Namespace formpool shared-rbd, namespace acme-prod
ceph osd pool ls | sort
ceph auth ls --format json | python3 -c '
import sys,json
for e in json.load(sys.stdin)["auth_dump"]:
    if e["entity"].startswith("client."): print(e["entity"])' | sort
A convention lets a script answer "which entities belong to acme" and
"which pools have no owner", which is what makes offboarding possible.

Scripting it

#!/bin/bash
# onboard-tenant.sh <tenant> <env> <quota-tb> <pg-num>
set -euo pipefail
T=$1; E=$2; Q=$3; PG=$4
POOL="${T}-${E}-rbd"
ENT="client.${T}-${E}-rbd"

ceph osd pool create "$POOL" "$PG"
ceph osd pool application enable "$POOL" rbd
ceph osd pool set-quota "$POOL" max_bytes $(( Q * 1024**4 ))
rbd pool init "$POOL"

ceph auth get-or-create "$ENT" \
  mon 'profile rbd' \
  osd "profile rbd pool=$POOL" \
  mgr "profile rbd pool=$POOL"

echo "$ENT | $POOL | quota ${Q}TiB | created $(date -I)" \
  >> /secure/tenant-register.txt
bash onboard-tenant.sh acme prod 10 128
Scripting is not about saving time. It is about every tenant being
identical, so a later change can be applied to all of them.

Verifying before handover

POOL=acme-prod-rbd; ENT=client.acme-prod-rbd
ceph osd pool get "$POOL" all | head
ceph osd pool get-quota "$POOL"
ceph auth get "$ENT"
# the tenant key works for its own pool
ceph -n "$ENT" --keyring /tmp/t.keyring -s >/dev/null && echo "auth OK"
rbd -n "$ENT" --keyring /tmp/t.keyring -p "$POOL" ls && echo "pool access OK"
# and does not work for another tenant's pool
rbd -n "$ENT" --keyring /tmp/t.keyring -p other-prod-rbd ls 2>&1 | \
  grep -q -i 'denied\|permission' && echo "isolation OK" || echo "ISOLATION FAILURE"

Quiz

Knowledge check · 4 questions

  1. Q1. What is the main benefit of scripting tenant onboarding?

  2. Q2. A missing pool application tag costs something even on a cluster where every pool is working correctly.

  3. Q3. Design a tenant onboarding procedure.

    A cluster will host around forty tenants. Provisioning is currently done by hand from a wiki page.

  4. Q4. What should a tenant verification include beyond confirming access works?

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

Production discipline

Script tenant onboarding so every tenant has an identical shape — the value is not the provisioning time but every later change across all tenants becoming a loop. Enable the pool application tag at creation, and include a negative isolation test in the handover check.

Cross-course references

  • Kubernetes: namespace provisioning templates exist for the identical consistency reason
  • Linux: identical configuration is what makes fleet-wide change tractable