Skip to main content
RunBook Academy

CephLXXV · Prometheus MetricsPrometheus Metrics

Scrape configuration and reliability

Intermediate⏱ ~17 minprometheusceph

What you'll learn

  • Write a robust Ceph scrape configuration
  • Handle manager failover and multiple clusters
  • Monitor the scrape itself
  • Diagnose scrape failures

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

A scrape that silently stops working leaves every alert built on it inactive, and nothing fires to say so. The scrape itself needs monitoring.

The configuration

scrape_configs:
  - job_name: 'ceph-prod'
    scrape_interval: 30s
    scrape_timeout: 25s
    honor_labels: true
    static_configs:
      - targets:
          - 'ceph-mgr-01.example.com:9283'
          - 'ceph-mgr-02.example.com:9283'
          - 'ceph-mgr-03.example.com:9283'
        labels:
          cluster: 'prod-ceph-01'
    metric_relabel_configs:
      - source_labels: [__name__]
        regex: 'ceph_rbd_.*'
        action: drop
ElementPurpose
Multiple targetssurvives manager failover
cluster labeldistinguishes clusters
scrape_timeout below the intervalavoids overlapping scrapes
honor_labelspreserves labels the exporter sets
metric_relabel_configsdrops unwanted high-cardinality families

Handling multiple clusters

  - job_name: 'ceph-dr'
    static_configs:
      - targets: ['dr-mgr-01:9283', 'dr-mgr-02:9283']
        labels:
          cluster: 'dr-ceph-01'

A separate job per cluster keeps the labelling explicit and lets each cluster have its own interval and relabelling if needed.

Monitoring the scrape

up{job=~"ceph.*"}
scrape_duration_seconds{job=~"ceph.*"}
scrape_samples_scraped{job=~"ceph.*"}
- alert: CephScrapeDown
  expr: up{job=~"ceph.*"} == 0
  for: 5m
  labels: { severity: page }
  annotations:
    summary: "Ceph metrics scrape failing for {{ $labels.cluster }}"
    description: >
      No Ceph metrics are being collected. Every Ceph alert is inactive
      while this persists.

- alert: CephScrapeSlow
  expr: scrape_duration_seconds{job=~"ceph.*"} > 15
  for: 15m
  labels: { severity: ticket }

- alert: CephMetricsMissing
  expr: absent(ceph_health_status)
  for: 5m
  labels: { severity: page }

The absent() alert catches the case where the target is up but returning nothing useful, which up == 0 does not.

Diagnosing failures

# from the Prometheus side
curl -s 'http://prometheus:9090/api/v1/targets' | python3 -c '
import sys,json; d=json.load(sys.stdin)
for t in d["data"]["activeTargets"]:
    if "ceph" in t["labels"].get("job",""):
        print(t["labels"]["instance"], t["health"],
              round(t.get("lastScrapeDuration",0),2), t.get("lastError",""))'
ErrorCause
connection refusedmodule not enabled, or manager down
context deadline exceededgeneration slower than the timeout
up == 1 but no ceph_ metricsscraping a standby with error behaviour
Intermittent failuresmanager failover, or load
# from the Ceph side
# MGR is the active manager's address, as printed by `ceph mgr services`:
MGR=192.0.2.21

ceph mgr module ls | grep -A2 prometheus
ceph mgr services
curl -s "http://$MGR:9283/metrics" | head -3

Quiz

Knowledge check · 4 questions

  1. Q1. What does `absent(ceph_health_status)` catch that `up == 0` does not?

  2. Q2. If no Ceph alerts are firing, the cluster is healthy.

  3. Q3. Audit Ceph monitoring reliability.

    A team wants confidence that their Ceph alerting would actually fire. The alerts have been in place for a year and none has ever fired.

  4. Q4. Why should each Ceph cluster have its own scrape job rather than one job with many targets?

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

Production discipline

Alert on up{job=~"ceph.*"} == 0 and absent(ceph_health_status) together — every Ceph alert depends on the scrape, and silence is indistinguishable from health without them. Test the full alert path with a benign triggered condition rather than assuming it works.

Cross-course references

  • Kubernetes: monitoring the monitoring stack is the same dead-man requirement
  • Linux: a heartbeat check is what distinguishes silence from health