Цель статьи
Для закрепления материала о 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 сам собирает все данные с целевого объекта, для этого есть разные способы:
- Приложение может быть написано так, что само отдает метрики в нужном формате.
- Используются готовые экспортеры. Например, есть экспортеры для MySQL, Nginx или машины с GNU/Linux.
- Pushgateway. Применяется, когда нет возможности использовать Pull-запросы для снятия метрик стандартными средствами. Применяется, например, при выполнении задач в crontab.
Так как приём и обработка данных происходит в самом Prometheus, он является центральным звеном всей схемы мониторинга, где происходит вся настройка. Формат получаемых метрик в Prometheus — ключ-значение, это важно запомнить.
Из дополнительных инструментов присутствуют:
- Alertmanager – для оповещения, его данная статья не коснётся.
- Data visualization – простой способ визуализации из коробки, из внешних можно использовать Grafana.
- Service discovery – динамическое обнаружение сервисов, также в данной статье не рассматривается.
А также присутствует PromQL – собственный язык запросов для извлечения метрик из базы данных.
Практика
С минимальным знанием основ можно приступать к практическим задачам для более глубокого погружения в Prometheus.
Объектом мониторинга в данном материале будет сервер с GNU/Linux. В системе командой ps aux можно вывести список работающих процессов с дополнительными данными по использованию CPU и Memory. Этот вывод можно использовать, например, при анализе проблем с сервером или ПО на нём, чтобы понимать, что происходило с процессами в момент проблемы для её решения.
Например, общая картина будет выглядеть в итоге примерно так:
Схема работы следующая:
- process-exporter отдаёт согласно своего конфига список процессов в системе и прочие метрики, которые может собирать в определенном формате;
- prometheus выступает в роли агрегатора данных и делает pull запросов, забирая уже готовые данные у process-exporter;
- 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 – используемая память в разделе подкачки.
По каждому типу памяти будут настроены панели на дашборде:
- 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 конкретным процессом с точностью до секунды: