Prometheus advanced: Recording rules
Recording rules предварительно вычисляют дорогие PromQL-выражения и сохраняют результаты как новые метрики. Дашборды читают готовые данные вместо пересчёта при каждом запросе — это разница между дашбордом, который загружается за 1 секунду, и дашбордом, который грузится 10 секунд.
Базовый Prometheus хорошо работает до определённого масштаба. Когда дашбордов много, запросы сложные, а данных миллиарды точек, начинаются проблемы: дашборды грузятся медленно, alerting lag растёт. Recording rules и federation решают это без смены стека.
Key Takeaways
- Recording rules предвычисляют дорогие запросы (rate, quantile) — дашборды читают готовое за microseconds вместо seconds
- Соглашение по именованию
level:metric:operationsпомогает понять что за метрика и как посчитана- Federation: глобальный Prometheus собирает только recording rules, не сырые метрики — данные остаются в регионах
- Thanos добавляет долгосрочное хранение в S3 и дедупликацию реплик без изменения Prometheus
remote_writeв Grafana Mimir или VictoriaMetrics — альтернатива Thanos для мультитенантного хранения
Recording Rules
Recording rules предварительно вычисляют дорогие выражения и сохраняют как новую метрику. Дашборд читает готовые данные вместо пересчёта:
# prometheus-rules.yaml
groups:
- name: api_aggregations
interval: 1m # пересчитывать каждую минуту
rules:
# P99 latency по сервису (дорогой запрос с histogram_quantile)
- record: job:http_request_duration_seconds:p99
expr: >
histogram_quantile(0.99,
sum by (job, le) (
rate(http_request_duration_seconds_bucket[5m])
)
)
# P50 latency
- record: job:http_request_duration_seconds:p50
expr: >
histogram_quantile(0.50,
sum by (job, le) (
rate(http_request_duration_seconds_bucket[5m])
)
)
# Rate запросов по статусу
- record: job:http_requests_total:rate5m
expr: sum by (job, status) (rate(http_requests_total[5m]))
# Error rate в процентах
- record: job:http_errors:rate5m_ratio
expr: >
sum by (job) (rate(http_requests_total{status=~"5.."}[5m]))
/
sum by (job) (rate(http_requests_total[5m]))
# CPU usage по namespace
- record: namespace:container_cpu_usage:rate5m
expr: >
sum by (namespace) (
rate(container_cpu_usage_seconds_total{container!=""}[5m])
)
Соглашение по именованию: level:metric:operations. Это позволяет быстро понять что за метрика и как она посчитана.
# В конфиге Prometheus
rule_files:
- /etc/prometheus/rules/*.yaml
Alerting Rules
groups:
- name: api_alerts
rules:
# Использует recording rule -- быстро
- alert: HighErrorRate
expr: job:http_errors:rate5m_ratio > 0.05
for: 5m # должно выполняться 5 минут перед срабатыванием
labels:
severity: critical
team: backend
annotations:
summary: "High error rate on {{ $labels.job }}"
description: "Error rate {{ $value | humanizePercentage }} for {{ $labels.job }}"
runbook: "https://runbooks.internal/high-error-rate"
- alert: P99LatencyHigh
expr: job:http_request_duration_seconds:p99 > 1.0
for: 5m
labels:
severity: warning
annotations:
summary: "P99 latency > 1s for {{ $labels.job }}"
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
for: 5m
labels:
severity: warning
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is crash looping"
Federation
Federation — механизм агрегации данных с нескольких Prometheus в один глобальный:
# global-prometheus.yaml
scrape_configs:
- job_name: federate
scrape_interval: 1m
honor_labels: true
metrics_path: /federate
params:
match[]:
- '{job="api"}'
- 'job:http_requests_total:rate5m' # только recording rules
- 'job:http_request_duration_seconds:p99'
- 'namespace:container_cpu_usage:rate5m'
static_configs:
- targets:
- prometheus-eu-west:9090
- prometheus-us-east:9090
- prometheus-ap-south:9090
Глобальный Prometheus собирает только агрегированные данные (recording rules), не все сырые метрики. Сырые данные остаются в региональных инстансах — это снижает трафик в 100-1000 раз.
Thanos для долгосрочного хранения
Prometheus хранит данные локально, обычно 15 дней. Thanos расширяет это до лет через S3-совместимое хранилище:
# thanos-sidecar добавляется к каждому Prometheus
containers:
- name: thanos-sidecar
image: thanosio/thanos:v0.34.0
args:
- sidecar
- --tsdb.path=/prometheus
- --objstore.config-file=/etc/thanos/s3.yaml
- --prometheus.url=http://localhost:9090
volumeMounts:
- name: prometheus-data
mountPath: /prometheus
# /etc/thanos/s3.yaml
type: S3
config:
bucket: prometheus-long-term
endpoint: s3.eu-central-1.amazonaws.com
region: eu-central-1
access_key: ${AWS_ACCESS_KEY_ID}
secret_key: ${AWS_SECRET_ACCESS_KEY}
Thanos Querier объединяет данные из всех Prometheus и S3 в единый endpoint, дедуплицирует реплики:
thanos query \
--store=prometheus-eu-west:10901 \
--store=prometheus-us-east:10901 \
--store=thanos-store-gateway:10901 # исторические данные из S3
Remote Write
Альтернатива Thanos — remote write в Grafana Mimir, VictoriaMetrics или Cortex:
remote_write:
- url: https://mimir.internal/api/v1/push
queue_config:
max_samples_per_send: 5000
max_shards: 30
capacity: 10000
write_relabel_configs:
# Отправлять только важные метрики (снизить объём)
- source_labels: [__name__]
regex: "(job:|namespace:|alert).*"
action: keep
# Удалить шумные лейблы
- action: labeldrop
regex: "(pod_template_hash|controller_revision_hash)"
VictoriaMetrics как замена Thanos — проще в операции, лучше сжатие данных:
# VictoriaMetrics single node (до 10M samples/sec)
docker run -v /victoria-metrics-data:/storage \
-p 8428:8428 \
victoriametrics/victoria-metrics \
-retentionPeriod=12 # 12 месяцев
Оптимизация производительности
Cardinality — главная причина проблем с Prometheus. Высокая cardinality (миллионы уникальных label combinations) убивает производительность:
# Плохо: user_id как label -- миллионы уникальных значений
http_requests_total{user_id="12345", path="/api/v1"}
# Хорошо: агрегировать по endpoint, не по пользователю
http_requests_total{path="/api/v1", method="POST", status="200"}
# Найти метрики с высокой cardinality
curl http://prometheus:9090/api/v1/query \
--data 'query=topk(10, count by (__name__)({__name__=~".+"}))'
Scrape интервалы: не все метрики нужно собирать каждые 15 секунд:
scrape_configs:
- job_name: "kubernetes-pods"
scrape_interval: 15s # application metrics
- job_name: "node-exporter"
scrape_interval: 60s # infrastructure metrics -- реже
- job_name: "slow-jobs"
scrape_interval: 5m # batch jobs
Итог
Recording rules — первый инструмент при проблемах с производительностью Prometheus. Предвычисленные метрики делают дашборды быстрыми и снижают нагрузку на Prometheus. Federation разделяет данные по регионам без потери глобальной видимости. Thanos или VictoriaMetrics решают долгосрочное хранение за разумные деньги.
Для команд, которые только начинают: одна хорошая recording rule для p99 latency и error rate — уже 80% пользы от этой статьи.