CephLXXV · Prometheus MetricsPrometheus Metrics
Writing Ceph alerting rules
What you'll learn
- Write alerting rules with appropriate thresholds and durations
- Include annotations that help a responder
- Route by severity
- Test rules before relying on them
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
An alert’s value is decided by whether the responder knows what to do when it fires. Threshold, duration, and annotations all serve that.
A complete rule
- alert: CephOSDLatencyOutlier
expr: |
topk(1, ceph_osd_apply_latency_ms) > 50
and on() (avg(ceph_osd_apply_latency_ms) < 15)
for: 15m
labels:
severity: ticket
component: ceph
cluster: '{{ $labels.cluster }}'
annotations:
summary: "{{ $labels.ceph_daemon }} apply latency {{ $value | humanize }}ms"
description: >
{{ $labels.ceph_daemon }} shows apply latency of
{{ $value | humanize }}ms while the cluster average is well below.
A single slow OSD sets the cluster p99. Check the device SMART data
and the host before considering replacement.
runbook_url: "https://runbooks.example.com/ceph/osd-latency-outlier"
query: "ceph osd perf | sort -k2 -rn | head -5"
Six things: the condition, the duration, the routing labels, a summary, a description with context, and the command that starts the investigation.
Choosing thresholds and durations
| Alert | Threshold basis | for |
|---|---|---|
| OSD full | the ratio itself | 1m |
| PGs inactive | any non-zero | 5m |
| Degraded, not recovering | zero recovery | 15m |
| Latency outlier | multiple of the cluster average | 15m |
| Nearfull | the ratio | 30m |
| Scrub overdue | Ceph’s own check | 6h |
The for duration should exceed the condition’s normal transient
duration. Peering is sub-second, so 5 minutes is generous; a nearfull
reading can fluctuate, so 30 minutes avoids noise.
Relative rather than absolute thresholds
# absolute — needs tuning per cluster and breaks after hardware changes
expr: ceph_osd_apply_latency_ms > 50
# relative — adapts to the cluster
expr: |
ceph_osd_apply_latency_ms
> 5 * avg(ceph_osd_apply_latency_ms)
A relative threshold survives a hardware refresh; an absolute one has to be revisited and usually is not.
Routing
route:
routes:
- matchers: [ component="ceph", severity="critical" ]
receiver: pagerduty
group_wait: 30s
- matchers: [ component="ceph", severity="page" ]
receiver: pagerduty
active_time_intervals: [ business_hours ]
- matchers: [ component="ceph", severity="ticket" ]
receiver: ticketing
group_interval: 1h
Testing rules
promtool check rules ceph-alerts.yml
promtool test rules ceph-alerts-test.yml
# a unit test
evaluation_interval: 1m
tests:
- interval: 1m
input_series:
- series: 'ceph_pg_total'
values: '100+0x20'
- series: 'ceph_pg_active'
values: '100+0x5 95+0x15'
alert_rule_test:
- eval_time: 12m
alertname: CephPGsInactive
exp_alerts:
- exp_labels: { severity: critical }
An alert that has never been tested is an alert whose behaviour is unknown, and the first time it is exercised is during an incident.
Quiz
Knowledge check · 4 questions
Q1. Why do relative alert thresholds survive a hardware refresh where absolute ones do not?
Q2. A cluster whose OSDs have all degraded together can pass a relative latency check while every device is slow.
Q3. Improve an alert that fires without helping.
An alert "CephOSDLatencyHigh" fires monthly with the message "OSD latency high". Responders consistently spend the first fifteen minutes working out which OSD and what to check.
Q4. What six elements make a complete alerting rule?
Passing score: 75%. Answers are checked in this browser.
Production discipline
Put the first diagnostic command or a runbook link in every alert
annotation — it removes the slowest part of a 03:00 response. Prefer
relative thresholds that compare each OSD against its peers, with a loose
absolute backstop for the uniformly-degraded case, and unit-test rules
with promtool before relying on them.
Cross-course references
- Kubernetes: alert annotations carrying kubectl commands serve the same purpose
- Linux: any alert without a stated next action costs response time