Мониторинг процессов Linux: Process-exporter, Prometheus и Grafana

Цель статьи

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

Введение

Современные и новые решения всегда интересны для изучения и применения, особенно, когда привык к классическому Zabbix. Поэтому появление Prometheus и Grafana с её нескучными дашбордами вызвало интерес для первоначального ознакомления.

Prometheus является базой данных временных рядов (как InfluxDB, например), но с дополнительными инструментами для мониторинга. По сравнению с классическими реляционными базами данных, такие базы также работают с данными в таблицах, но все эти таблицы объединены временем, что позволяет им работать быстрее . Подходят такие решения для хранения различных метрик с привязкой ко времени и быстрых выборок.

Реальный кейс, который сподвигнул меня познакомиться с Prometheus – это относительно старый сервер с RHEL 6 и MySQL 5.6, на котором абсолютно рандомно по частоте возникновения, но примерно в одно и тоже время происходит утечка памяти и демон mysqld отстреливается oom killer`ом. При этом были применены различные практики по настройке как MySQL, так и сервера – проблема стала реже, но тем не менее имеет место быть. Для дальнейшего решения и более лучшего понимания, что происходит в процессах системы, было решено использовать process-exporter.

Можно по-старинке написать bash-скрипт, который каждую минуту будет складировать вывод ps aux, а можно использовать time series базы данных, что и будет рассмотрено в дальнейшем.

Теория

Prometheus сам собирает все данные с целевого объекта, для этого есть разные способы:

  1. Приложение может быть написано так, что само отдает метрики в нужном формате.
  2. Используются готовые экспортеры. Например, есть экспортеры для MySQL, Nginx или машины с GNU/Linux.
  3. Pushgateway. Применяется, когда нет возможности использовать Pull-запросы для снятия метрик стандартными средствами. Применяется, например, при выполнении задач в crontab.

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

Из дополнительных инструментов присутствуют:

  1. Alertmanager – для оповещения, его данная статья не коснётся.
  2. Data visualization – простой способ визуализации из коробки, из внешних можно использовать Grafana.
  3. Service discovery – динамическое обнаружение сервисов, также в данной статье не рассматривается.

А также присутствует PromQL – собственный язык запросов для извлечения метрик из базы данных.

Практика

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

Объектом мониторинга в данном материале будет сервер с GNU/Linux. В системе командой ps aux можно вывести список работающих процессов с дополнительными данными по использованию CPU и Memory. Этот вывод можно использовать, например, при анализе проблем с сервером или ПО на нём, чтобы понимать, что происходило с процессами в момент проблемы для её решения.

Например, общая картина будет выглядеть в итоге примерно так:

Схема работы следующая:

  1. process-exporter отдаёт согласно своего конфига список процессов в системе и прочие метрики, которые может собирать в определенном формате;
  2. prometheus выступает в роли агрегатора данных и делает pull запросов, забирая уже готовые данные у process-exporter;
  3. grafana посредством запросов забирает данные из prometheus, выстраивая нескучные графики с нужными метриками для наглядного представления.

Установка

Process-exporter (bare metal)

Process-exporter всего лишь работает на порту 9526 и отдаёт список процессов системы. Есть ещё Node Exporter, но об этом в другой раз.

В некоторых мануалах установка осуществляется посредством скачивания бинарника и запуска в фоне. Мне такой формат не нравится, поэтому я сразу создал systemd unit для удобного управления:

wget https://github.com/ncabatoff/process-exporter/releases/download/v0.6.0/process-exporter-0.6.0.linux-amd64.tar.gz
tar xvf process-exporter-0.6.0.linux-amd64.tar.gz && cp process-exporter-0.6.0.linux-amd64/process-exporter /usr/bin/

Перед запуском нужно сформировать конфиг. В нём прописано, что будет осуществляться выборка всех процессов в системе (именно такой кейс необходим мне):

cat > /etc/process-exporter.yml << EOF
process_names:
  - name: "{{.Comm}}"
    cmdline:
    - '.+'
EOF

Параметр Comm выше означает имя (basename) процесса, например, sshd.

cat > /etc/systemd/system/process-exporter.service << EOF
[Unit]
Description=Process Exporter for Prometheus

[Service]
User=root
Type=simple
ExecStart=/usr/bin/process-exporter --config.path /etc/process-exporter.yml --web.listen-address=:9256
KillMode=process
Restart=always

[Install]
WantedBy=multi-user.target
EOF

Prometheus (bare-metal)

Аналогично примеру выше, создается systemd unit:

wget https://github.com/prometheus/prometheus/releases/download/v2.17.0/prometheus-2.17.0.linux-amd64.tar.gz && tar xvf prometheus-2.17.0.linux-amd64.tar.gz 
cp prometheus-2.17.0.linux-amd64/prometheus /usr/bin/

Только здесь ещё создаётся пользователь:

useradd --no-create-home --shell /bin/false prometheus

Копирование конфига и необходимых файлов:

mkdir /etc/prometheus
cp -r prometheus-2.17.0.linux-amd64/consoles/ /etc/prometheus/consoles
cp -r prometheus-2.17.0.linux-amd64/console_libraries/ /etc/prometheus/console_libraries
cp -r prometheus-2.17.0.linux-amd64/prometheus.yml /etc/prometheus/prometheus.yml

mkdir /var/lib/prometheus
chown prometheus:prometheus /var/lib/prometheus
cat > /etc/systemd/system/prometheus.service << EOF
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
Group=prometheus
ExecStart=/usr/bin/prometheus \
    --config.file /etc/prometheus/prometheus.yml \
    --storage.tsdb.path /var/lib/prometheus/ \
    --web.console.templates=/etc/prometheus/consoles \
    --web.console.libraries=/etc/prometheus/console_libraries

[Install]
WantedBy=default.target
EOF

В конфиг /etc/prometheus/prometheus.yml дописать инстанс Process-exporter на порту 9526:

static_configs:
            - targets: ['localhost:9090', 'localhost:9526']
Установка в Docker

Установка Prometheus в Docker, в общем-то почти ничем не отличается от установки Bare-metal

CONTAINER_NAME=prometheus
CONTAINER_VERSION=v2.17.1
 
mkdir -p /data/${CONTAINER_NAME}/etc/prometheus
mkdir -p /data/${CONTAINER_NAME}/prometheus

cat << EOF > /data/${CONTAINER_NAME}/etc/prometheus/prometheus.yml
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
            - targets: ['localhost:9090', 'localhost:9526']
EOF

# Важно запустить контейнер от имени пользователя prometheus (или любого non-root)
useradd -rs /bin/false prometheus
chown -R $(id -u prometheus):$(id -g prometheus) /data/${CONTAINER_NAME}
 
docker run -d --name ${CONTAINER_NAME} -h ${CONTAINER_NAME} --user $(id -u prometheus):$(id -g prometheus) \
    -p 9090:9090 \
    -v /data/${CONTAINER_NAME}/etc/prometheus:/etc/prometheus \
    -v /data/${CONTAINER_NAME}/prometheus:/prometheus \
    prom/prometheus:${CONTAINER_VERSION} --config.file="/etc/prometheus/prometheus.yml" --storage.tsdb.path="/prometheus"

Grafana (bare-metal)

В данном случае Grafana 6.2 доступна из репозиториев:

yum install -y grafana
Установка в Docker
CONTAINER_NAME="grafana"
GLOBAL_DOMAIN="example.tld"

mkdir -p /data/${CONTAINER_NAME}/var/lib/grafana
chown -R 472:472 /data/${CONTAINER_NAME}/var/lib/grafana

docker run -d --name=${CONTAINER_NAME} \
 -p 3000:3000 \
 -h ${CONTAINER_NAME} \
 -v /data/${CONTAINER_NAME}/var/lib/grafana:/var/lib/grafana \
 -e "GF_SERVER_ROOT_URL=http://grafana.${GLOBAL_DOMAIN}" \
 -e "GF_SECURITY_ADMIN_PASSWORD=M0C3EAVZrl3" \
 grafana/grafana:6.7.1

Осталось запустить и поместить в автозагрузку все установленные выше сервисы (если используется bare-metal установка):

systemctl daemon-reload && for service in process-exporter prometheus grafana-server; do systemctl enable $service --now; done

Визуализация данных в Prometheus

Теперь, когда Prometheus и Process-exporter запущены, можно уже наблюдать за полученной информацией. Для этого надо просто зайти на IP-сервера по порту 9090, в разделе Status должно быть видно, что Process-exporter активен:

В разделе Graph можно выполнить запрос на получение данных в виде графика, например так:

А под графиком уже весь список процессов:

В режиме table список процессов просто получен списком:

Как видно, используется формат ключ:значение с применением меток (labels). Ключ – namedprocess_namegroup_num_procs, значение – кол-во процессов. При этом используются метки groupname, по которой можно делать выборки в дальнейшем – очень гибко.

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

В дальнейшем для рассмотрения будут использоваться следующие метрики по всем (и каждому) процессам в системе:

  • namedprocess_namegroup_cpu_seconds_total – cpu rate процессу
  • namedprocess_namegroup_num_procs – кол-во процессов
  • namedprocess_namegroup_memory_bytes – используемая память (virtual & resident)

Визуализация данных в Grafana

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

Для начала нужно подключить Data Source, т.е. выбрать Prometheus в кач-ве источника данных:

Если Prometheus находится за прокси, то по-хорошему нужно установить Basic Auth, например. В данном случае для упрощения авторизация не используется, в продакшене так, разумеется, лучше не делать.

После подключения источника, можно создавать Dashboard, а на нём Panel с непосредственным запросом, нажав Add Query:

Перед написанием запроса нужно добавить переменные – важная вещь для множественной выборки.

На пустом дашборде нажать шестеренку в правом верхнем углу:

Добавить переменную:

Ввести имя “processes” – его надо будет использовать при составлении запроса, выбрать источник данных – Prometheus и самое главное – это ввести запрос в формате label_values(namedprocess_namegroup_cpu_seconds_total,groupname). Тут всё просто – в переменную processes будут подставляться все значения из groupname, который является меткой (label) в метрике namedprocess_namegroup_cpu_seconds_total и содержит в себе непосредственно список процессов.

Также нужно выбрать Multi-value и Include All option и можно будет уже лицезреть список процессов:

Вторая переменная – это интервал, который также можно удобно использовать при составлении запросов. Тут нужно выбрать тип переменной Interval и указать необходимые значения (или оставить дефолтные):

Далее будет показана настройка панелей на дашборде согласно метрик, которые необходимы для мониторинга.

namedprocess_namegroup_num_procs

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

Пустой график редактируется:

Сам запрос выглядит так: namedprocess_namegroup_num_procs{groupname=~”$processes”}, где уже используется переменная. Это вовсе не обязательно и можно прибить жестко только нужные процессы, но в данном кейсе используются большие возможности и после ввода запроса данные уже можно посмотреть:

В следующем пункте настраивается сам график и об этом рассказывать особо нечего. Далее можно указать внятное имя панели:

namedprocess_namegroup_cpu_seconds_total

График будет показывать использование CPU тем или иным процессом за определённое время, т.е. усредненное значение. Работает так: берёт значения из /proc/[pid]/stat в разные промежутки времени, а именно из полей utime и stime, и делит на длительность промежутка. Таким образом вычисляется процент нагрузки на CPU данного процесса.

rate(namedprocess_namegroup_cpu_seconds_total{groupname=~"$processes"}[$interval])

Также тут надо указать, что значения по оси Х измеряются в миллисекундах:

Здесь в запросе используется функция rate(value[time]), которая определяет рост метрики за используемый временной интервал.

И ещё один график, но уже с подсчётом загрузки CPU в процентах:

Не забыть указать значение по оси Х в процентах:

namedprocess_namegroup_memory_bytes

Данная метрика отдает в байтах кол-во используемой памяти процессом (также через /proc/PID/stat|status):

namedprocess_namegroup_memory_bytes{groupname="(sd-pam)", instance="localhost:9256", job="process_exporter", memtype="resident"} 3436544
namedprocess_namegroup_memory_bytes{groupname="(sd-pam)", instance="localhost:9256", job="process_exporter", memtype="virtual"} 152453120
namedprocess_namegroup_memory_bytes{groupname="md5sum", instance="localhost:9256", job="process_exporter", memtype="swapped"} 0

Как видно, есть дополнительный label с типом памяти:

  • resident (ResidentSetSize) – используемая физическая память. Отображается как RSS в ps aux
  • virtual (VirtualSetSize) – используемая виртуальная память. Отображается как VSZ  или VSS в ps aux
  • swapped – используемая память в разделе подкачки.

По каждому типу памяти будут настроены панели на дашборде:

  1. RSS memory:
namedprocess_namegroup_memory_bytes{groupname=~"$processes", memtype="resident"}

В поле Unit единицы измерения bytes:

2. VSS

Аналогично графику RSS, только меняется метка в запросе:

namedprocess_namegroup_memory_bytes{groupname=~"$processes", memtype="virtual"}

3. swapped

Аналогично графику RSS, только меняется метка в запросе:

namedprocess_namegroup_memory_bytes{groupname=~"$processes", memtype="swapped"}

Теперь панель с графиками выглядит примерно так. Если легенда снизу не умещается, то при редактировании графика можно настроить размер:

Чтобы в переменной $processes не были все значения списка процессов при первом открытии графика, что вызывает задержки, нужно выбрать несколько процессов, например, так:

А при сохранении графика выбрать Save current variables:

Выкладываю свой настроенный шаблон для тех, кто не захочет разбираться со всеми настройками вручную.

Заключение

В дополнение к уже привычному Zabbix теперь можно использовать Prometheus и Gfarana для более детального анализа возникающих проблем на серверах и их оперативного устранения.

Для сравнения график CPU Usage в Zabbix для понимания общей картины утилизации:

И график по использованию CPU конкретным процессом с точностью до секунды:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *