Skip to main content
RunBook Academy

CephLXVI · Capacity ForecastingCapacity Forecasting

Measuring growth and computing lead time

Intermediate⏱ ~17 mincephprometheus

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

Not yet marked complete on this device.

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

WeakStrong
“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

  1. Q1. Why can a forecast built on raw used bytes under-predict exhaustion?

  2. Q2. "We are at 71% utilisation" is sufficient information for a capacity decision.

  3. 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.

  4. 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