CephCXXIV · Production Reference ArchitectureProduction Reference Architecture
The monitoring stack that ships with the design
What you'll learn
- Deploy the monitoring stack with retention that outlives an incident
- Choose alert conditions from Ceph health checks rather than raw metrics
- Derive each threshold from the time required to act on it
- Keep metrics and alerting available when the cluster is not
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
Ceph degrades gracefully, which means it will run for weeks in a state that is quietly consuming your remaining redundancy. Alerting is what converts that silence into a ticket, and the thresholds decide whether the ticket arrives while there is still time to act on it.
The stack
ceph mgr module enable prometheus
ceph config set mgr mgr/prometheus/scrape_interval 15
ceph orch apply node-exporter --placement='*'
ceph orch apply prometheus --placement="1 node1"
ceph orch apply alertmanager --placement="1 node1"
ceph orch apply grafana --placement="1 node1"
ceph orch ls --service_type prometheus
# specs/prometheus.yaml — retention has to outlive the investigation
service_type: prometheus
placement:
hosts: [node1]
spec:
retention_time: "30d"
retention_size: "50GB"
Fifteen days of retention loses the baseline for any incident whose question is whether this month looks like last month.
Alert on health checks, not on raw metrics
| Health check | Severity | Delay | Why that delay |
|---|---|---|---|
MON_DOWN with quorum lost | critical | 0 | the cluster is not writable |
MON_DOWN, quorum held | warning | 5 min | a reboot takes about that long |
OSD_DOWN, single | warning | 10 min | one OSD is inside the redundancy budget |
OSD_HOST_DOWN | critical | 2 min | a failure domain has left |
PG_AVAILABILITY | critical | 1 min | IO is blocked right now |
PG_DEGRADED | warning | 30 min | expected during any recovery |
OSD_NEARFULL | critical | 0 | the warning arrives too late to be the first signal |
POOL_NEARFULL | warning | 1 h | procurement has a lead time |
SLOW_OPS | warning | 5 min | bursts are normal, sustained is not |
MON_CLOCK_SKEW | warning | 10 min | it precedes quorum instability |
RECENT_CRASH | warning | 0 | a crash is never expected |
PG_NOT_DEEP_SCRUBBED | warning | 1 day | silent corruption goes undetected |
CRASH_ID=2026-08-18T02:11:04.128Z_9f2c
ceph health detail
ceph crash ls-new
ceph crash info ${CRASH_ID}
Health checks already encode Ceph’s own judgement about what is abnormal. Alerting on them gives you names that match the documentation and the mailing list, which matters at three in the morning.
Thresholds derived from time to fix
ceph osd dump | grep -E 'full_ratio'
# full_ratio 0.95 backfillfull_ratio 0.9 nearfull_ratio 0.85
ceph osd set-nearfull-ratio 0.82
ceph osd df | sort -rnk 17 | head -5
Growth 2% of capacity per week. Procurement, delivery, racking and
burn-in: 8 weeks. To have 8 weeks of runway you must be alerted at 16
percentage points below the point where you stop, so the capacity alert
fires around 70%, not at the 85% nearfull ratio.
| Threshold | Set by | Not set by |
|---|---|---|
| Capacity warning | procurement lead time and growth rate | a round number |
| OSD down delay | how long a reboot takes | patience |
| Slow ops window | normal burst duration | alert fatigue |
| Scrub age | the recovery point you accept for silent corruption | the default |
Keeping the view when the cluster is gone
# scrape the cluster Prometheus from an external one
# - job_name: ceph-federate
# honor_labels: true
# metrics_path: /federate
# params: { 'match[]': ['{job=~"ceph.*"}'] }
# static_configs: [{ targets: ['node1:9095'] }]
curl -s http://node1:9095/federate --data-urlencode 'match[]={job=~"ceph.*"}' | head
Alertmanager notifications must leave by a path that does not traverse the cluster. A cluster-hosted Alertmanager on the host that just died sends nothing at all.
Quiz
Knowledge check · 4 questions
Q1. Why should the capacity alert fire around 70% rather than at the default 0.85 nearfull ratio?
Q2. A cluster reporting 80% average utilisation is safely below the 0.85 nearfull ratio.
Q3. Review the alerting configuration on a cluster that has just had an unnoticed outage.
A host was down for nine days before anyone noticed. Prometheus retains 15 days. Alertmanager runs on the same host as Prometheus, on node1. The only alert configured is on overall cluster health not being OK.
Q4. Why alert on Ceph health check names rather than on raw Prometheus metrics?
Passing score: 75%. Answers are checked in this browser.
Production discipline
Derive each threshold from how long the corresponding fix takes, and write that reasoning down next to the rule — a threshold with no stated basis gets relaxed the first time it is inconvenient. Put metrics retention and at least one Alertmanager receiver outside the cluster, because the outages worth alerting on are the ones that take the dashboard with them.
Cross-course references
- Kubernetes: alert on the condition the controller reports, not on the metric you rebuilt from scratch
- Linux: filesystem monitoring has the same lead-time arithmetic behind its thresholds