Когда Prometheus один, вопросов почти нет. Когда их пять, по одному на кластер, хочется видеть общую картину, но тянуть все сырые метрики в один сервер дорого и бессмысленно. Федерация решает эту задачу: глобальный Prometheus периодически забирает у локальных только нужные серии. Разберём настройку без лишней кардинальности.
Две модели: федерация и remote write
Федерация работает по pull-модели: глобальный сервер сам обращается к эндпоинту /federate каждого локального Prometheus и получает срез метрик в текстовом формате. Remote write работает наоборот: локальный сервер отправляет поток samples в удалённое хранилище. Первый вариант проще в изолированных сетях и не требует открывать приёмник, второй лучше подходит для полного архива и больших объёмов.
Практическое правило: федерация для агрегатов и дежурных панелей, remote write или специализированное хранилище для долгого хранения и детального разбора.
Что именно отдаёт /federate
Эндпоинт принимает один или несколько параметров match[] с селекторами PromQL и возвращает текущие значения подходящих серий. Это не произвольный запрос: функции, агрегация и сортировка там не работают. Поэтому все вычисления нужно делать заранее через recording rules, а федерация лишь забирает готовые ряды.
curl -s 'http://prom-cluster-a:9090/federate?match[]={__name__=~"job:.*"}' | head
curl -s 'http://prom-cluster-a:9090/federate?match[]=up&match[]=node_load1' | head
Если не передать ни одного match[], сервер вернёт ошибку 400. Это защита от случайной выгрузки всей базы.
Подготовка источника: external_labels
Каждый локальный Prometheus должен помечать свои данные именем кластера. Это делается через external_labels в глобальном блоке. Метка добавляется ко всем сериям и помогает потом группировать панели и алерты.
global:
scrape_interval: 30s
external_labels:
cluster: eu-west-1
environment: production
scrape_configs:
- job_name: node
static_configs:
- targets: ['localhost:9100']
Не путайте external_labels с метками job и instance: первые описывают сам сервер, вторые — цель опроса. Если у вас несколько окружений, добавьте и environment. Тогда один и тот же job в разных кластерах не смешается в графиках.
Recording rules для агрегатов
Федерация хороша тогда, когда отдаёт десятки серий, а не сотни тысяч. Создайте правила, которые считают rate, сумму и квантили на месте, и федерайте только результат.
groups:
- name: federation-aggregates
interval: 30s
rules:
- record: job:http_requests:rate5m
expr: sum by (job, cluster) (rate(http_requests_total[5m]))
- record: job:http_request_duration:p95
expr: histogram_quantile(0.95,
sum by (le, job, cluster) (rate(http_request_duration_seconds_bucket[5m])))
Проверьте правила через promtool check rules и убедитесь, что ряды действительно появились в локальном Prometheus. Если выражение возвращает пустоту, федерация тоже ничего не получит, и глобальный сервер будет выглядеть здоровым, но пустым.
Настройка глобального Prometheus
На принимающей стороне достаточно обычного scrape_config с metrics_path /federate и списком match[]. Значение honor_labels: true критично: без него конфликтующая метка cluster превратится в exported_cluster, и разделение по кластерам станет неудобным.
scrape_configs:
- job_name: federation
honor_labels: true
metrics_path: /federate
scrape_interval: 30s
scrape_timeout: 20s
params:
match[]:
- '{__name__=~"job:.*"}'
- '{__name__="up"}'
static_configs:
- targets:
- prom-cluster-a:9090
- prom-cluster-b:9090
labels:
tier: edge
Метка tier из static_configs добавится к сериям, но при honor_labels: true конфликт с меткой источника решится в пользу источника. Это ожидаемое поведение: именно так сохраняются cluster и environment. Если метку нужно перезаписать, выставьте honor_labels: false.
Сколько данных и как не утонуть
Федерация одного и того же набора серий с десяти кластеров умножает кардинальность на десять. Поэтому не федерайте сырые node_* и http_* без необходимости. Начните с малого: up, правила уровня job, несколько ключевых бизнес-метрик. Дальше расширяйте осознанно.
Ограничители защищают сервер:
- sample_limit обрывает сбор при превышении числа samples;
- metric_relabel_configs выбрасывает лишние метки;
- cluster и instance нужны для навигации, их лучше сохранить;
- высококардинальные метки вроде request_id стоит убрать.
sample_limit: 50000
metric_relabel_configs:
- source_labels: [__name__]
regex: 'go_.*'
action: drop
Помните, что federation забирает текущий срез, а не историю. Если локальный сервер недоступен в момент опроса, в глобальном будет разрыв, а up покажет 0. Для дежурства этого достаточно, для аудита — нет.
Проверка и диагностика
Сначала проверьте конфигурацию и перезагрузите сервис. Затем посмотрите на страницу /targets: цель federation должна быть в состоянии UP, а в деталях видно число собранных samples. Если цель DOWN, читайте ошибку в том же интерфейсе и в журнале systemd.
promtool check config /etc/prometheus/prometheus.yml
curl -X POST http://localhost:9090/-/reload
systemctl status prometheus --no-pager
journalctl -u prometheus -n 50 --no-pager
Для проверки данных выполните в глобальном Prometheus запрос count by (cluster) (up{job=»federation»}). Если кластеров меньше, чем ожидалось, ищите расхождение в метках. Пустой результат при рабочей цели чаще всего означает неверный match[] или отсутствие recording rules на источнике.
Ещё одна частая причина — рассинхронизация времени. Prometheus отбрасывает samples, которые слишком сильно отличаются от текущего времени, поэтому на всех узлах должен работать chrony или systemd-timesyncd. Проверьте offset через chronyc tracking и сравните часы на источнике и приёмнике.
Безопасность федерации
Эндпоинт /federate не имеет встроенной авторизации на уровне путей, поэтому не публикуйте Prometheus в интернет. Правильный вариант — отдельная сеть мониторинга, firewall и TLS. Начиная с версии 2.24 Prometheus умеет читать web.config.file с basic auth и TLS, что закрывает вопрос для межкластерной связи.
tls_server_config:
cert_file: /etc/prometheus/server.crt
key_file: /etc/prometheus/server.key
basic_auth_users:
federation: $2y$10$replace_with_bcrypt_hash
Пароль в конфиге источника задаётся в scrape_config через basic_auth или bearer_token_file. Храните его в файле с правами 600 и не коммитьте в git. Если кластеры в разных сетях, настройте маршрутизацию и правила firewall, а не полагайтесь на «сложный» URL.
Итог
Федерация Prometheus — это обмен агрегатами, а не копия всей базы. Пометьте кластеры через external_labels, посчитайте нужные ряды recording rules, включите honor_labels на приёмнике и ограничьте объём через match[] и sample_limit. Проверяйте цель на /targets, следите за временем и не выставляйте Prometheus в интернет. Тогда несколько кластеров действительно помещаются в одно окно.