Привет всем,

В этой заметке хотелось бы показать пример, как можно извлекать данные из командной оболочки (Bash) и отдавать их в Prometheus.

Представим на нас упала таска, по заданию которой требуется извлекать значения из файлов с переменными и слать алерт в мессенджер при случаи изменения этих значений.

Более опытные из нас, наверное пошли бы по пути написания небольшого скрипта, который бы полностью решал бы эту задачу.

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

*--> Bash --> Pushgateway --> Prometheus

Пропустим установку прометеус, так как на текущем проекте он у меня уже активно используется и установим Pushgateway.

Установка Pushgateway

Идем на github проекта и качаем последний релиз на сервер.

root@monitoring:/tmp# wget https://github.com/prometheus/pushgateway/releases/download/v1.6.0/pushgateway-1.6.0.linux-amd64.tar.gz

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

root@monitoring:/tmp# tar -zxvf pushgateway-1.6.0.linux-amd64.tar.gz 
root@monitoring:/tmp# cp pushgateway-1.6.0.linux-amd64/pushgateway /usr/local/bin/

Запускать будем через системного пользователя, поэтому добавляем нового юзера:

root@monitoring:/tmp# useradd -c "Pushgateway system user" -U --system -s /bin/false pushgateway

Теперь остается написать systemd-юнит, для запуска приложения:

root@monitoring:/tmp# vim /etc/systemd/system/pushgateway.service
---
[Unit]
Description=Prometheus Pushgateway
Wants=network-online.target
After=network-online.target

[Service]
User=pushgateway
Group=pushgateway
Type=simple
ExecStart=/usr/local/bin/pushgateway --web.listen-address=127.0.0.1:9091

[Install]
WantedBy=multi-user.target

Сохраняемся и релодим systemd.

Далее запускаем сервис:

root@monitoring:/tmp# systemctl daemon-reload
root@monitoring:/tmp# systemctl enable --now pushgateway

Если вы читаете это, то возможно уже знаете что у нас есть две модели доставки метрик в prometheus - Pull/Push. По Pull модели прометей работает уже по умолчанию, и этот способ рекомендуется как предпочтительным.

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

Так вот для реализации push модели в prometheus есть некий посредник, который слушает порт и принимает запросы со стороны своих клиентов. А далее prometheus уже традиционным способом спуллит все изменения.

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

Теперь давайте в конфигурации prometheus пропишем новый job для pushgateway:

root@monitoring:/tmp# vim /etc/prometheus/prometheus.yml 
---
  - job_name: 'Pushgateway'
    honor_labels: true
    static_configs:
    - targets: 
      - 'localhost:9091'

И перезапускаем прометей:

root@monitoring:/tmp# systemctl restart prometheus

Сервис pushgateway запущен на localhost, проксировать запросы на нему будет через nginx.

root@monitoring:~# vim /etc/nginx/conf.d/pushgateway.conf 
---
server {
  listen 8080;
  
  allow 10.10.11.0/24;
  deny all;
	
  location / {
    proxy_pass http://127.0.0.1:9091;
  }
}

Далее просто перезапускаем nginx.

Теперь если мы обратимся к серверу через браузер, то обнаружим такой вот ui: pushgateway-webui.png

Отправляем данные на Pushgateway

На стороне серверной части все готово, давайте теперь попробуем отправить какую либо метрику через curl.

Со своего ноута я кидаю запрос:

tony@t420:~/Gitlab/nixhub.ru$ echo "simple_metric 1.1" | curl --data-binary @- http://10.8.1.7:8080/metrics/job/test-job/instance/test-instance

Смотрим в webui отображение метрики: pushgateway-webui.png

Отлично, наша рандомная метрика отобразилась на push-гейте.

Bash-скрипт и отправка данных

Приступаем к решению основной части нашего задания. Теперь нам требуется написать скриптец, который будет парсить определенные параметры из файла и отправлять из на pushgateway.

Собственно сам скриптец:

#!/bin/bash

SEARCH_PATH=$1

RESULT=$(grep -E "define\('MAINTENANCE_PROCESS', .*?\)" $SEARCH_PATH | grep -oP '\(\K[^\)]+' | sed -e "s/'//g" | sed -e "s/,//g" | awk '{print $2}')

if [ "$RESULT" == "true" ]; then 
	echo "maintenance_plan_check 1" | curl --data-binary @- http://10.0.1.253:8080/metrics/job/maintenance_plan/instance/$(hostname)
else
	echo "maintenance_plan_check 0" | curl --data-binary @- http://10.0.1.253:8080/metrics/job/maintenance_plan/instance/$(hostname)
fi

Этот скриптец через grep парсит нужную мне переменную из файла, далее выдергивает из этой переменной ее значение.

Ну и затем выполняется условие, результатом которого отправляется целочисленное значение 0/1.

Данный скрипт, по сути описательный. И не стоит его воспринимать, как что то более чем пример. =)

Можем запустить несколько раз сценарий, что бы проверить отображение данных в прометеус. Затем я этом скриптец ставлю в крон выполнение каждые 5-7 минут:

root@tomita-u20-trunk:~# vi /etc/crontab 
---
*/5 * * * *     root    bash maintance_notify.sh /path/to/file/conf.php

Далее идем в графану, что бы просмотреть данные. В графане через эксплорер метрик выдергиваем нашу метрику: pushgateway-grafana.png

Обратите внимание на значение полей job, instance - они у меня прописаны от балды. В реально же жизни стоит подойти к этом серьезнее.

Отправка нотификакий

Как научить прометеус отправлять уведомления я показывал в прошлых заметках. В этом поинте просто добавим новое правило алертинга уже к существующим. Все правила у меня описаны в конфигурационном файле - alerts.yml. Открываем его, и в конце добавляем:

root@monitoring:~# vi /etc/prometheus/alerts.yml 
---
  - alert: Maintenance plan enabled
    expr: maintenance_plan_check == 1
    for: 3m
    labels:
      severity: "warning"
    annotations:
      summary:
        "Maintenance plan was been enabled on {{ $labels.instance }}."                                                                         

Это правило сработает, если значение метрики maintenance_plan_check будет равно 1. И тогда алерт будет отправлен.

На этом можно считать задачку решенной. =)