Модуль 2 · Как работает Prometheus · Макаров М. Н.

Модуль 2 · как работает prometheus · сбор метрик

Глава 2.5

2.5

Pull-модель:
запрос идёт от сервера

В предыдущих главах запрос шёл от Prometheus к приложению. Такой порядок называется pull-моделью. В этой главе он сравнивается с обратным порядком — push. Разобрано, кто начинает обмен, откуда взялась pull-модель, что она даёт и чем ограничена. В конце показано, как поступают, когда pull не подходит.

Категория
Способ сбора
Уровень
Средний
Опирается на
Главы 2.2–2.4
Результат
Выбор способа сбора для сервиса, задачи или устройства

§1Два способа доставки метрик

Во всех предыдущих главах обмен начинал сервер: Prometheus отправлял запрос, приложение отвечало. Это не единственный возможный порядок. Числа появляются в приложении, а хранятся на сервере мониторинга, и доставить их можно двумя способами. Различаются способы тем, кто делает первый шаг.

Сравнение из жизни
Показания счётчика воды

Первый способ. Жилец раз в месяц передаёт показания в управляющую компанию.

Второй способ. Контролёр обходит квартиры по списку и записывает показания.

Когда жилец уехал, в первом случае компания не получает письма, и причина ей неизвестна. Во втором случае у контролёра записано, в какую квартиру он не попал.

Метрики

Push. Приложение отправляет числа на сервер мониторинга.

Pull. Сервер обходит приложения по списку target и забирает числа.

Когда приложение остановилось, при push сервер не получает данных, и причина ему неизвестна. При pull на сервере записано, какой target не ответил: ряд up равен 0.

У способов есть названия. Когда числа отправляет приложение, это push-модель: в приложении записан адрес сервера, и оно отправляет данные по своему расписанию. Так работают StatsD, Graphite, InfluxDB в обычной настройке и протокол OTLP из OpenTelemetry. Когда числа забирает сервер, это pull-модель: на сервере записаны адреса приложений, и он опрашивает их по своему расписанию. Так работает Prometheus: scrape из главы 2.4 устроен по этой модели.

В сравнении со счётчиком воды разница проявилась в момент, когда жилец уехал. Следующий раздел показывает тот же момент по шагам.

§2Push и pull по шагам

Две схемы показывают одну ситуацию: проходят два обмена данными, затем приложение аварийно завершается. До остановки схемы различаются только направлением стрелок. Содержательное различие появляется на последнем шаге, поэтому сравните, какие сведения есть у сервера после остановки приложения.

Pushприложение отправляет само
Приложение Сервер мониторинга в конфигурации: адрес сервера POST · значения метрик записать то, что пришло POST · значения метрик процесс упал: отправок нет тишина: упал или нет событий?
  1. Адрес сервера мониторинга записан в настройках приложения.
  2. Приложение отправляет числа по своему расписанию: по таймеру или после события.
  3. Сервер записывает то, что пришло.
  4. Следующая отправка.
  5. Приложение аварийно завершилось. Отправок больше нет.
  6. Данные на сервер не приходят. По одному отсутствию данных причину определить нельзя: приложение остановилось или у него нет новых чисел.
PullPrometheus запрашивает сам
Prometheus Приложение в конфигурации: список target GET /metrics 200 OK · текущие значения up = 1, записать отсчёты GET /metrics процесс упал: порт закрыт connection refused up = 0: target недоступен
  1. У Prometheus есть список target.
  2. По расписанию Prometheus отправляет запрос GET /metrics.
  3. Приложение отвечает текущими числами.
  4. Prometheus записывает числа и up = 1.
  5. Следующий scrape по расписанию.
  6. Приложение аварийно завершилось. Его порт закрыт.
  7. Запрос завершается ошибкой соединения.
  8. Prometheus записывает up = 0. Известно, какой target недоступен и с какого момента.

При push сервер после остановки ничего не получает и не может отличить остановленное приложение от приложения, у которого нет новых чисел. При pull сервер отправляет запрос, получает ошибку соединения и записывает up = 0. На сервере записаны адрес, который не ответил, и момент, с которого это началось.

Этим различия не исчерпываются. Из того, кто начинает обмен, следует ещё несколько свойств, и они собраны в таблице.

ВопросPushPull
Где записан адрес другой стороныВ приложении записан адрес сервераНа сервере записаны адреса приложений
Кто задаёт время передачиПриложениеСервер: scrape_interval
Как узнают об остановке приложенияПо отсутствию данных. Нужна отдельная проверкаПо неуспешному scrape: up = 0
Кто управляет нагрузкой на серверПриложения. Тысяча приложений может отправить данные одновременноСервер. Он распределяет опросы по интервалу
Какое соединение должно быть разрешеноОт приложения к серверуОт сервера к каждому приложению
Задача, которая работает 3 секундыУспевает отправить результатМожет завершиться до первого scrape

В двух строках таблицы упомянуты соединения и адреса. Следующий раздел разбирает эти направления отдельно.

§3Направление запроса и данных

Слово pull означает «тянуть», и из-за него кажется, что всё движется в одну сторону. Направлений два. Запрос идёт от Prometheus к приложению, а данные идут обратно, от приложения к Prometheus. При этом соединение одно, как в телефонном звонке в справочную: человек звонит и задаёт вопрос, ответ слышит в том же разговоре, и справочная ему не перезванивает.

Запрос и ответ в одном соединенииодин scrape
открывает соединениеPrometheus
принимает соединениеapi:8000
получает числаPrometheus
отвечает по тому же соединениюapi:8000

Соединение открывает Prometheus, а приложение его только принимает. Отсюда два практических следствия. Первое касается сети: сетевой экран между ними должен разрешать одно соединение, от Prometheus на порт приложения. Второе касается безопасности: порт приложения принимает входящие соединения, а на странице /metrics видны внутренние числа сервиса. Поэтому этот порт не открывают в интернет, и метрики отдают на внутреннем адресе сети.

Подробнее: защита страницы /metrics

Страницу можно закрыть шифрованием и проверкой доступа. В задании Prometheus для этого есть параметры scheme: https, tls_config, basic_auth и authorization.

Устройство pull разобрано. Прежде чем оценивать его преимущества и ограничения, следующий раздел рассказывает, откуда оно взялось.

§4Откуда взялась pull-модель

Pull-модель Prometheus повторяет устройство системы Borgmon — внутренней системы мониторинга компании Google, описанной в главе 10 книги Google «Site Reliability Engineering» (2016). Программы Google отдавали свои числа по адресу /varz обычным текстом: в каждой строке название и значение. Пример из книги:

Страница /varz из главы о BorgmonSite Reliability Engineering, гл. 10
% curl https://webserver:80/varz
http_requests 37
errors_total 12

Сходство с Prometheus есть не только в странице. По описанию в книге, Borgmon опрашивал /varz через заданные интервалы — в Prometheus это scrape_interval. Список target он получал из службы имён — в Prometheus это service discovery. Опросы он распределял по интервалу, и для каждого target записывал переменную «удался ли опрос» — в Prometheus это ряд up. В той же главе книги Prometheus назван среди открытых систем, похожих на Borgmon.

до 2012
Borgmon в Google

Внутренняя система с опросом по HTTP. По книге SRE, основа мониторинга Google почти 10 лет.

2012
Prometheus в SoundCloud

Открытая система с тем же способом сбора и метками.

2014
Текстовый формат

Формат из главы 2.3 появился в апреле 2014 года.

2016
CNCF

Prometheus принят в фонд Cloud Native Computing Foundation вторым после Kubernetes.

В Google эта модель работала почти десять лет. Следующие два раздела разбирают, что она даёт и чем ограничена.

§5Что даёт pull

Создатели Prometheus объясняют выбор pull в разделе вопросов и ответов документации:

«Pulling over HTTP offers a number of advantages: You can start extra monitoring instances as needed, e.g. on your laptop when developing changes. You can more easily and reliably tell if a target is down. You can manually go to a target and inspect its health with a web browser.»

В ответе названы три преимущества, и каждое из них уже встречалось в модуле. Первое: можно запустить ещё один сервер мониторинга, например на своём ноутбуке, и в приложении для этого ничего не меняют. Второе: проще и надёжнее определить, что target не работает, — это ряд up и текст ошибки из главы 2.4. Третье: target можно открыть в браузере и проверить вручную, потому что браузер и curl получают тот же текст, что и Prometheus.

К этим трём на практике добавляются ещё два. Нагрузкой управляет сервер: он распределяет опросы по интервалу, и тысяча приложений не отправляет ему данные одновременно. Список target к тому же показывает, что должно работать. Target из списка, который не ответил, виден как DOWN, а при push приложение, которое ни разу не отправило данные, серверу неизвестно.

Проще становится и приложение. Ему не нужен адрес сервера мониторинга, не нужно хранить неотправленные данные и повторять отправку, когда сервер недоступен. Библиотека хранит числа в памяти и отдаёт их по запросу.

Все пять преимуществ следуют из того, что обмен начинает сервер. Из того же следуют и ограничения.

§6Ограничения pull

Ограничений три, и у каждого есть принятый способ его обойти.

Сервер должен иметь доступ к target. Если приложение находится в закрытой сети, куда входящие соединения запрещены, Prometheus его опросить не может. Документация советует в таком случае ставить Prometheus в ту же сеть, что и приложение.

Нужно знать список target. В облаке копии сервиса появляются и исчезают, и файл с адресами быстро устаревает. Эту задачу решает service discovery из главы 2.2: список берут из внешней системы.

Короткая задача завершается раньше scrape. Скрипт резервного копирования работает 40 секунд и завершается. При интервале 60 секунд scrape может не попасть в эти 40 секунд, и результат задачи в Prometheus не попадёт. Для этого случая есть отдельная программа, Pushgateway, и она разобрана ниже.

Как работает Pushgateway

Идея Pushgateway знакома по почтовому ящику в подъезде. Жилец уезжает до прихода контролёра и оставляет записку с показаниями в ящике, а контролёр забирает её при обходе. Короткая задача так же перед завершением отправляет числа в Pushgateway. Pushgateway работает постоянно, и Prometheus забирает числа оттуда при очередном scrape, как у обычного target.

Короткая задача и Pushgatewaypush и pull вместе
работает 40 секундЗадачаперед завершением отправляет результат
работает постоянноPushgatewayхранит последние полученные числа
опрашивает по расписаниюPrometheusзабирает числа как у обычного target

На схеме две стрелки направлены к Pushgateway с разных сторон: задача отправляет в него данные способом push, а Prometheus забирает их способом pull. Из-за этого посредника теряются три свойства pull, и документация их перечисляет.

Во-первых, появляется одна точка отказа: если через один Pushgateway отправляют данные много задач и он остановится, пропадут данные всех. Во-вторых, для задачи нет ряда up: этот ряд показывает доступность самого Pushgateway, а состояние задач по нему определить нельзя. В-третьих, данные не удаляются сами. Pushgateway хранит последние полученные числа и отдаёт их при каждом scrape, пока их не удалят вручную, так что числа удалённой копии сервиса остаются. При pull они исчезли бы вместе с копией.

Поэтому документация советует Pushgateway только в одном случае: для результата пакетной задачи, которая относится ко всему сервису и не привязана к одной машине. Пример — ночная очистка базы данных.

Подробнее: настройки для Pushgateway и другие решения

У метрик такой задачи не должно быть метки instance. Pushgateway передаёт метки job и instance других программ, поэтому в его задании включают honor_labels: true (глава 2.2, §6).

Для задач, привязанных к одной машине (cron, обновления), числа записывают в файл. Этот файл читает программа node exporter через свой textfile collector.

Для приложений в закрытой сети есть PushProx. Его клиент внутри закрытой сети держит соединение с посредником, и Prometheus опрашивает приложение через посредника.

Pushgateway — один из случаев, когда в системе на основе pull используется push. Последний раздел собирает все такие случаи.

§7Push в экосистеме Prometheus

Основной способ сбора в Prometheus — pull, но передача данных способом push встречается в четырёх местах. Они перечислены в таблице; флаги запуска из неё проверены командой prometheus --help версии 3.5.0.

МеханизмКто кому отправляетДля чего
PushgatewayЗадача → Pushgateway. Prometheus опрашивает Pushgateway способом pullРезультаты коротких задач
remote_write в конфигурацииPrometheus → другое хранилищеДолгое хранение и объединение данных нескольких серверов
Флаг --web.enable-remote-write-receiverДругой Prometheus → этот PrometheusПриём данных от серверов, которые опрашивают свои target
Флаг --web.enable-otlp-receiverПриложение с OpenTelemetry → PrometheusПриём метрик по протоколу OTLP без страницы /metrics

Оба флага по умолчанию выключены. У данных, принятых через них, тот же недостаток, что был у push в §2: они не проходят scrape, для их источников нет ряда up, и доступность отправителя приходится проверять отдельно.

Какой способ выбрать

Материал главы сводится к порядку выбора. Если программа работает постоянно и находится в той же сети — веб-сервис, обработчик задач, база данных, — её опрашивают способом pull: через страницу /metrics или через exporter. Это основной случай, и к остальным переходят, только когда он невозможен.

Для пакетной задачи всего сервиса используют Pushgateway: без метки instance и с honor_labels: true в задании. Задача cron на одной машине записывает числа в файл, который читает node exporter. Для приложения в закрытой сети ставят Prometheus в ту же сеть или используют PushProx. Если в приложении уже есть OpenTelemetry, метрики принимают по протоколу OTLP, а доступность приложения проверяют отдельно.

§8Проверьте себя

Вопрос 1Между Prometheus и приложением стоит сетевой экран. Какое соединение он должен разрешить для pull?

  • Так было бы при push. В pull приложение соединений не открывает.

  • Верно. Prometheus открывает соединение, а данные приходят в ответе по нему же.

  • Ответ идёт по уже открытому соединению. Второго соединения нет.

Вопрос 2Какое преимущество pull названо в документации Prometheus?

  • Объём одинаковый: передаются те же значения. Документация этого не утверждает.

  • Верно. Это одно из трёх преимуществ из документации, вместе со вторым сервером мониторинга и проверкой в браузере.

  • Закрытая сеть — одно из ограничений pull (§6).

Вопрос 3Скрипт очистки базы запускается раз в сутки и работает 20 секунд. Как передать в Prometheus время его последнего успешного запуска?

  • Scrape может не попасть в 20 секунд работы. После завершения скрипта target будет DOWN до следующих суток.

  • Верно. Это пакетная задача всего сервиса — случай, для которого документация советует Pushgateway.

  • Prometheus логи не читает. Для логов нужны другие системы.

Вопрос 4Копия сервиса удалена. Что станет с её числами в Pushgateway?

  • Pushgateway не связан с работой копий и полученные числа не удаляет.

  • Верно. Документация называет это одним из недостатков Pushgateway.

  • Ряд up относится к самому Pushgateway. Для копий, которые в него писали, отдельного up нет.

Источники главы
  1. Prometheus. FAQ: Why do you pull rather than push? — prometheus.io/docs/introduction/faq
  2. Prometheus. When to use the Pushgateway — prometheus.io/docs/practices/pushing
  3. Beyer B. и др. Site Reliability Engineering. Глава 10. Practical Alerting from Time-Series Data — sre.google/sre-book/practical-alerting
  4. Prometheus. Overview — prometheus.io/docs/introduction/overview
  5. PushProx — github.com/prometheus-community/PushProx
  6. Флаги --web.enable-remote-write-receiver и --web.enable-otlp-receiver проверены в prometheus --help, образ prom/prometheus:v3.5.0
Метрики и наблюдаемость · Модуль 2 · Как работает Prometheus Автор: Макаров Максим Николаевич