CephLXVI · Capacity ForecastingCapacity Forecasting
Measuring growth and computing lead time
What you'll learn
- Measure growth rate from cluster data
- Compute the date capacity will be exhausted
- Work backwards to an order date
- Present the figures so a decision follows
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
“We are at 71%” is not actionable. “We will be at the nearfull threshold on 14 November and procurement takes eight weeks, so the order must be placed by 19 September” is a decision that makes itself.
Measuring growth
# a simple daily record
date +%F,$(ceph df --format json | python3 -c '
import sys,json; d=json.load(sys.stdin)
print(d["stats"]["total_used_raw_bytes"])') >> /var/log/ceph-capacity.csv
From Prometheus, the same over a window:
rate(ceph_cluster_total_used_raw_bytes[14d]) * 86400
That is bytes per day. Both sources are useful — the CSV survives a monitoring outage and the Prometheus series supports projection queries.
Computing the exhaustion date
days remaining = available capacity / daily growth
avail=$(ceph df --format json | python3 -c '
import sys,json; d=json.load(sys.stdin)
print(max(p["stats"]["max_avail"] for p in d["pools"]))')
growth=4398046511104 # 4 TiB/day, measured
python3 -c "print(f'{$avail / $growth:.0f} days remaining')"
The available figure should be MAX AVAIL, not raw available, and the
target should be the threshold you intend to act at rather than the full
ratio.
Working backwards to an order date
exhaustion date 14 November
minus safety margin (2w) 31 October
minus rack and burn-in (1w) 24 October
minus delivery (4w) 26 September
minus procurement (4w) 29 August ← the order must be placed by here
Each subtraction is a real elapsed period, and the sum is usually longer than people assume. Writing them out is what makes the order date defensible.
Presenting it
| Weak | Strong |
|---|---|
| “We’re at 71% and growing” | “At 4 TB/day we reach nearfull on 14 November” |
| “We need more storage” | “The order must be placed by 29 August to land before we reach nearfull” |
| “It’s getting full” | “We have 96 days of capacity and a 71-day lead time” |
The final framing — days of capacity against days of lead time — is the one that survives being repeated to someone who was not in the room.
# the two numbers, computed
echo "capacity days: $(( avail / growth ))"
echo "lead time days: 71"
Quiz
Knowledge check · 4 questions
Q1. Why can a forecast built on raw used bytes under-predict exhaustion?
Q2. "We are at 71% utilisation" is sufficient information for a capacity decision.
Q3. Turn a utilisation figure into an order date.
A cluster is at 68% with 140 TB of MAX AVAIL, growing at 1.2 TB/day. Procurement takes 4 weeks, delivery 4 weeks, and racking and burn-in a further week.
Q4. What durations must be subtracted from the exhaustion date to reach an order date?
Passing score: 75%. Answers are checked in this browser.
Production discipline
Express capacity as days remaining against days of lead time rather
than as a percentage; it is the framing that carries a decision and stays
correct as both numbers move. Measure growth against MAX AVAIL rather
than raw used bytes so balance drift is included in the forecast.
Cross-course references
- Kubernetes: cluster capacity planning uses the same lead-time subtraction
- Linux: any capacity plan reduces to remaining time versus acquisition time