PROM 05: Прием метрик по push модели

Описание:

Всем привет!

В прошлых заданиях мы успешно настроили Prometheus и подключили к нему все три уровня мониторинга - системный, сервисный и уровень приложения. К настоящему моменту у нас имеется практически полная картина происходящего в нашей инфраструктуре. Но, как мы помним, Prometheus работает по pull модели, то есть ходит на экспортеры по http-протоколу и собирает с них метрики. Но как же быть, если наше приложение работает не постоянно и его невозможно подключить к Prometheus? Сегодня с этим и будем разбираться.

С реальным кейсом это может выглядеть очень просто: вы мониторите всю инфраструктуру и получаете данные со всех работающих компонентов. Но в реальности чаще всего случается так, что часть логики вынесена на периодическую обработку. Например, по cron'ам - ночью запускается скрипт, который обсчитывает все данные за день и генерирует некий отчет. Или же это может быть скрипт, который считает, сколько пользователь израсходовал трафика за день и списывает с него деньги. Согласитесь, что оставлять такой компонент без мониторинга не лучшее решение - скрипт не отработал, никто об этом не узнал, компания недосчиталась денег.

Но в данном случае проблема усугубляется тем, что скрипт, запускаемый по крону, не может быть добавлен, как цель мониторинга Prometheus, поскольку он не запущен бОльшую часть времени. Да и работать он может 5 секунд - период, за который Prometheus не успеет собрать с него данные. Для решения этой проблемы существует специальный экспортер - push gateway, который принимает метрики по push модели и отдает их Prometheus в привычном ему виде. Итак, сегодня мы:

установим push gateway;

попробуем отправить туда наши метрики;

разберемся с тем, как pushgateway обрабатывает метрики;

подключим наш экспортер к Prometheus.

Best Practice: Важно отметить, что push gateway должен использоваться именно для получения метрик с короткоживущих задач. Например приложений, запускаемых по планировщику cron. Не стоит использовать pushgateway для работы по push модели и слать в него огромное количество метрик. Лучше переписать свое приложение и подключить к нему библиотеку Prometheus, как мы делали в предыдущем задании. Если же вы мигрируете с решения на базе statsd, то самый красивый вариант - использовать statsd exporter, на который вы сможете переключить все свои приложения и, по сути, "бесшовно" переключиться на Prometheus. Подробнее о том, в каких случаях стоит использовать pushgateway, можно почитать здесь.

Установка push gateway

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

root@prom:/opt# wget https://github.com/prometheus/pushgateway/releases/download/v1.4.0/pushgateway-1.4.0.linux-amd64.tar.gz
root@prom:/opt# tar zxf pushgateway-1.4.0.linux-amd64.tar.gz
root@prom:/opt# mv pushgateway-1.4.0.linux-amd64 pushgateway

Best Practice: Как уже упоминалось ранее, в контексте Prometheus и других экспортеров, в production среде мы рекомендуем запускать pushgateway с помощью docker: docker run -d -p 9091:9091 prom/pushgateway. В данном практикуме мы отступаем от этого правила, поскольку подразумеваем, что не все слушатели знакомы с docker.

Итак, pushgateway установили, пришла пора его запустить. Но перед этим пробежимся по основным опциям, которые вы можете использовать при запуске:

--web.config.file="" Экспериментальная опция, позволяющая указать путь к конфигурации для включения TLS при обработке запросов.

--web.listen-address=":9091" - адрес, на котором pushgateway будет ожидать входящих подключений.

--web.telemetry-path="/metrics" - путь, по которому будут доступны метрики для Prometheus.

--web.enable-lifecycle - разрешает выключать pushgateway через запрос API.

--web.enable-admin-api - включает административный API, с помощью которого на данный момент можно только удалить все метрики.

--persistence.file="" - файл, в котором pushgateway будет сохранять полученные метрики. По умолчанию они хранятся в памяти и теряются при рестарте.

--persistence.interval=5m - как часто следует сохранять метрики в файл.

Итак, давайте попробуем запустить pushgateway:

root@prom:/opt/pushgateway# ./pushgateway
level=info ts=2021-05-12T21:59:55.775Z caller=main.go:85 msg="starting pushgateway" version="(version=1.4.0, branch=HEAD, revision=007ba874bead1b9ad2253d89e3adeb16a73fd012)"
level=info ts=2021-05-12T21:59:55.775Z caller=main.go:86 build_context="(go=go1.15.7, user=root@410bc05a48f6, date=20210122-23:54:24)"
level=info ts=2021-05-12T21:59:55.779Z caller=main.go:139 listen_address=:9091
level=info ts=2021-05-12T21:59:55.784Z caller=tls_config.go:191 msg="TLS is disabled." http2=false

Отлично, pushgateway запустился, поэтому пора начинать отправлять наши метрики.

Отправка метрик в pushgateway

Отправка базовых метрик

Для начала стоит сказать, что pushgateway имеет встроенный веб интерфейс, попасть на который можно используя порт 9091 (по умолчанию). Мы будем использовать консоль для работы с ним. Итак, pushgateway предоставляет простой API, с помощью которого вы можете отправлять в него метрики. После получения метрик, pushgateway может отдать их Prometheus серверу по endpoint'у /metrics. Давайте попробуем создать нашу первую метрик с помощью curl. Допустим наш крон скрипт запускается раз в час и списывает деньги со счетов пользователей. Тогда мы можем отправлять в pushgateway информацию о количестве обработанных пользователей. Или общую сумму списания:

root@prom:/opt# echo "cron_app_processed_users 112" | curl --data-binary @- http://localhost:9091/metrics/job/cron_app
root@prom:/opt# echo "cron_app_payed_sum 13423" | curl --data-binary @- http://localhost:9091/metrics/job/cron_app

В данном примере мы отправили две метрики - cron_app_processed_users - количество обработанных пользователей со значением 112 и cron_app_payed_sum - общая сумма списания в размере 13423. Мы так же использовали опцию --data-binary, которая никак не изменяет переданные ей данные из stdin, а просто передает их в POST запросе.

Также стоит упомянуть важный момент, касающийся url для отправки. Мы использовали путь /metrics/job/cron_app. В данном случае job - это label, а cron_app - его значение. Помните в scrape_config для Prometheus мы выставляли опцию job, которая в метриках отображалась в виде тега? Собственно это и есть именно тот тег. По данному тегу pushgateway будет группировать ваши метрики. Это очень удобно при работе с большим количеством кронов или других короткоживущих задач. Вы можете видеть сгруппированные метрики по ним.

Давайте теперь попробуем посмотреть, как наши метрики будут отдаваться Prometheus:

root@prom:/opt# curl http://localhost:9091/metrics
# TYPE cron_app_payed_sum untyped
cron_app_payed_sum{instance="",job="cron_app"} 13423
# TYPE cron_app_processed_users untyped
cron_app_processed_users{instance="",job="cron_app"} 112

... skipped ...

# HELP push_failure_time_seconds Last Unix time when changing this group in the Pushgateway failed.
# TYPE push_failure_time_seconds gauge
push_failure_time_seconds{instance="",job="cron_app"} 0
# HELP push_time_seconds Last Unix time when changing this group in the Pushgateway succeeded.
# TYPE push_time_seconds gauge
push_time_seconds{instance="",job="cron_app"} 1.6208582543334155e+09

... skipped ...

Собственно, данные метрики выглядит абсолютно аналогично любым метрикам Prometheus. Мы видим наши метрики, которые мы отправили с помощью curl, а также два важных дополнительных параметра, которые добавляет pushgateway - push_failure_time_seconds - timestamp, когда запись метрик в эту группу (job=cron_app) провалилась. И вторая метрика - push_time_seconds - timestamp, когда была произведена последняя успешная запись в данную группу. Благодаря этим метрикам, вы можете отслеживать, когда последний раз скрипт вообще что-то прислал и, если он пытался записать значения, но ему не удалось этого сделать. На пустой тег instance можете пока не обращать внимания - мы поговорим о ним чуть позже.

Дополнительные параметры при отправке метрик

Помимо базового варианта отправки метрик мы также можем использовать расширенный вариант - с указанием типа передаваемой метрики:

root@prom:/opt# cat <<EOF | curl --data-binary @- http://localhost:9091/metrics/job/cron_app
# TYPE cron_app_payed_sum gauge
cron_app_payed_sum 15487
# TYPE cron_app_processed_users gauge
# HELP cron_app_processed_users Processed Users Counter.
cron_app_processed_users 238
EOF

В данном примере мы отправили те же самые метрики, что и раньше, но указали их тип в комментарии. Подробнее про типы данных в Prometheus мы поговорим в задании про promql, сейчас главное понять, что вы можете указывать тип передаваемых данных.

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

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

root@prom:/opt# cat <<EOF | curl --data-binary @- http://localhost:9091/metrics/job/cron_app
cron_app_users{type="corp"} 64
cron_app_users{type="man"} 47
EOF

То есть мы указали тег напрямую в нашей метрике. Давайте посмотрим, что получилось с нашими метриками:

root@prom:/opt# curl http://localhost:9091/metrics

# TYPE cron_app_payed_sum gauge
cron_app_payed_sum{instance="",job="cron_app"} 15487
# HELP cron_app_processed_users Processed Users Counter.
# TYPE cron_app_processed_users gauge
cron_app_processed_users{instance="",job="cron_app"} 238
# TYPE cron_app_users untyped
cron_app_users{instance="",job="cron_app",type="corp"} 64
cron_app_users{instance="",job="cron_app",type="man"} 47

... skipped ...

Как видно из вывода, у нас появилась новая метрика с разными тегами.

Разделение метрик по группам

Помимо добавления label'ов напрямую в метриках, вы можете добавлять теги через URL. Например вот так:

root@prom:/opt# echo 'test_app_processed{type="users"} 12' | curl --data-binary @- http://localhost:9091/metrics/job/test_app/instance/db1

В данном случае мы добавили новую метрику test_app_processed с тремя тегами. Один тег type=users, который был задан напрямую в метрике, два других были указаны через URL: job=test_app и instance=db1. Давайте посмотрим, как будет выглядеть данная метрика в формате Prometheus:

root@prom:/opt# curl -s http://localhost:9091/metrics

... skipped ...
# TYPE test_app_processed untyped
test_app_processed{instance="db1",job="test_app",type="users"} 12

У нашей метрики появились все теги, которые мы указали. Разница в этих двух способах указания тегов достаточно проста - при задании тегов через URL - pushgateway будет разделять полученные метрики по группам, а если мы указали теги у метрики в теле запроса, то они будут принадлежать одной группе. Визуально разделение по группам хорошо будет видно в веб-интерфейсе Pushgateway (http://localhost:9091/):

Если вернуться к нашему примеру, то сейчас у нас есть две группы метрик:

job=cron_app - туда входят следующие метрики: cron_app_payed_sum, cron_app_processed_users, cron_app_users.

job=test_app, instance=db1 - туда входят следующие метрики: test_app_processed{type=users}.

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

root@prom:/opt# echo 'test_app_processed{type="users"} 14' | curl --data-binary @- http://localhost:9091/metrics/job/test_app/instance/db2

Теперь у нас есть две группы метрик: job=test_app,instance=db1 и вторая группа - job=test_app,instance=db2. Если мы вдруг удалили сервер db1, то мы можем удалить всю группу метрик, которая относится к нему:

root@prom:/opt# curl -X DELETE http://localhost:9091/metrics/job/test_app/instance/db1

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

Подключение pushgateway к Prometheus

Наконец-то мы добрались до самого интересного места. В целом здесь все достаточно просто, но есть нюансы. Pushgateway подключается аналогично любым другим экспортерам. Всего лишь необходимо добавить немного конфигурации:

- job_name: 'pushgateway'
honor_labels: true
static_configs:
- targets: ['localhost:9091']

Интерес здесь представляет параметр honor_labels: true. Давайте вспомним как Prometheus собирает метрики. В первую очередь он обращается по http к экспортеру по пути /metrics, откуда забирает все метрики с их тегами. После этого он добавляет свои внутренние теги - job, который указан в конфигурации job_name, а так же instance - endpoint, с которого эти метрики были собраны. В нашем же случае мы сами выставляем эти теги в pushgateway. Поскольку он может собирать данные с разных сервисов, мы напрямую передаем название задачи (job) и имя instance - db1. Так вот данная опция honor_labels: true запрещает Prometheus заменять данные теги своими собственными, а требует использовать те, которые были указаны в pushgateway.

Итоги

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

На этом все, в следующем занятии начнем разбираться с темой autodiscovery.

Полезные ссылки:

When to use pushgateway

Pushing Metrics

PushGateway

Job and instance labels

Задание:

В этом задании вам будет необходимо запустить pushgateway, создать несколько метрик внутри него и добавить его мониторинг в prometheus. На подготовленной виртуальной машине уже установлен Prometheus.

Критерии оценки выполнения задания:

Установите pushgateway на подготовленной виртуальной машине.

1.1. Исполняемый файл pushgateway должен находиться внутри отдельной директории /opt/pushgateway.

1.2. Pushgateway должен быть запущен на порту 9991.

1.3. Pushgateway должен быть запущен как сервис c помощью systemd и быть описан в файле /etc/systemd/system/pushgateway.service.

Отправьте в pushgateway метрики разделенные две группы:

группа job=test1,instance=app1 с метрикой time_run 3.14

группа job=test1,instance=app2 с метрикой time_run 6.18

тип метрик должен быть gauge

Настройте Prometheus:

3.1. Prometheus должен собирать все метрики c pushgateway без перезаписи тегов job и instance.