С чего начать Первые шаги трек · 15 ступеней
Linux Labs

node_exporter: метрики машины для Prometheus

12 мин Ubuntu 24.04 · node_exporter 1.7

Экспортёр Prometheus для самой машины: отдаёт по HTTP на :9100 метрики процессора, памяти, дисков, сети и служб.

Шпаргалка

8 команд Версия для печати
  • sudo systemctl enable --now prometheus-node-exporter включить
  • systemctl status prometheus-node-exporter жива ли служба
  • ss -tlnp | grep 9100 где слушает
  • curl -s localhost:9100/metrics | less всё, что отдаёт
  • curl -s localhost:9100/metrics | grep -c '^node_' число значений
  • curl -s localhost:9100/metrics | grep MemAvailable одна метрика
  • curl -s localhost:9100/metrics | promtool check metrics формат
  • sudo systemctl restart prometheus-node-exporter после правки ARGS

Обзор

node_exporter — экспортёр Prometheus для самой машины. Он читает /proc, /sys и состояние systemd и отдаёт по HTTP на порту 9100, путь /metrics, текущие значения: процессор, память, диски, файловые системы, сеть, нагрузку, состояние служб. Сам он ничего не хранит и никуда не отправляет: Prometheus приходит за метриками по расписанию (prometheus).

В Ubuntu это пакет prometheus-node-exporter: служба с тем же именем, программа /usr/bin/prometheus-node-exporter, пользователь prometheus. На учебной машине пакет стоит, служба выключена:

bash
sudo systemctl enable --now prometheus-node-exporter

Экспортёр готов отвечать через секунду-две после запуска.

Формат экспозиции

Ответ /metrics — текст. У каждой метрики две строки-комментария и строки значений:

text
$ curl -s localhost:9100/metrics | grep MemAvailable
# HELP node_memory_MemAvailable_bytes Memory information field
  MemAvailable_bytes.
# TYPE node_memory_MemAvailable_bytes gauge
node_memory_MemAvailable_bytes 2.95616512e+08

Первая строка в выводе одна, здесь она перенесена.

Строка Что в ней
# HELP имя текст что измеряет метрика
# TYPE имя тип counter, gauge, histogram, summary или untyped
имя{метки} значение одно значение: ряд со своим набором меток

Значение — число с плавающей точкой, часто в экспоненциальной записи: 2.95616512e+08 — 295 616 512 байт, около 282 МиБ. У метрик с метками строк значений несколько:

text
node_filesystem_avail_bytes{device="/dev/vda4",fstype="ext4",
  mountpoint="/"} 5.361012736e+09

Имя говорит о единицах: _bytes, _seconds; _total — счётчик (promql). Префикс node_ — метрики машины, go_ и process_ — самого экспортёра. На учебной машине ответ — около 1900 строк: примерно 270 метрик и 1300 значений node_*.

Главные метрики

Метрика Что значит
node_cpu_seconds_total секунды процессора с загрузки по ядрам (cpu) и режимам (mode: idle, user, system, iowait…)
node_load1, node_load5, node_load15 средняя нагрузка за 1, 5 и 15 минут
node_memory_MemAvailable_bytes память, которую можно занять без вытеснения; рядом MemTotal, MemFree и другие поля /proc/meminfo
node_filesystem_avail_bytes свободно на файловой системе для обычных пользователей, как столбец Avail у df
node_filesystem_size_bytes размер файловой системы
node_disk_read_bytes_total, node_disk_written_bytes_total прочитано и записано на диск (device)
node_network_receive_bytes_total, node_network_transmit_bytes_total принято и отправлено через интерфейс (device)
node_systemd_unit_state 1 у текущего состояния юнита (name, state), 0 у остальных
node_boot_time_seconds время загрузки в unix-секундах
node_uname_info версия ядра и имя машины в метках, значение 1

Сколько памяти можно занять — MemAvailable. MemFree — память, не занятая ничем; кэш файлов в неё не входит, хотя ядро отдаёт его по первому требованию. На учебной машине MemFree — около 13 МиБ, MemAvailable — около 280. Про нагрузку и память подробнее — load-average и memory-swap.

Коллекторы

Коллектор — часть экспортёра, которая читает один источник: meminfo — /proc/meminfo, filesystem — смонтированные файловые системы, netdev — интерфейсы, systemd — юниты, textfile — файлы со своими метриками. На учебной машине включено больше сорока. Какие и удался ли последний сбор — метрика node_scrape_collector_success:

bash
curl -s localhost:9100/metrics | grep '^node_scrape_collector_success'

0 у коллектора значит, что источник прочитать не удалось; причина — в журнале службы. Включить или выключить коллектор — ключи --collector.<имя> и --no-collector.<имя> (см. «Конфигурация»).

Коллектор filesystem отдаёт node_filesystem_* не для всех точек монтирования. Пропускает он то, что подходит под --collector.filesystem.mount-points-exclude, на учебной машине по умолчанию:

text
^/(dev|proc|run|sys|mnt|media|var/lib/docker/.+|
  var/lib/containers/storage/.+)($|/)

Выражение здесь перенесено. Том, смонтированный в /mnt/… или /media/…, в метрики не попадает вовсе: рядов для него нет, и правило с его mountpoint пусто (node-exporter). Типы файловых систем отсекает --collector.filesystem.fs-types-exclude (tmpfs в списке нет, proc, sysfs, overlay, squashfs есть). Свой список — ключом в ARGS, он заменяет значение по умолчанию.

textfile — свои метрики файлом

Коллектор textfile читает файлы *.prom из /var/lib/prometheus/node-exporter при каждом запросе к /metrics и отдаёт их строки вместе со своими. Так скрипт без своего HTTP-сервера сообщает Prometheus, например, время последней удачной резервной копии:

text
$ echo 'lab_backup_last_success_timestamp_seconds 1792640000' \
    | sudo tee /var/lib/prometheus/node-exporter/backup.prom
$ curl -s localhost:9100/metrics | grep lab_backup
# HELP lab_backup_last_success_timestamp_seconds Metric read from
  /var/lib/prometheus/node-exporter/backup.prom
# TYPE lab_backup_last_success_timestamp_seconds untyped
lab_backup_last_success_timestamp_seconds 1.79264e+09

Строки # HELP и # TYPE в файле необязательны: без них экспортёр пишет свои, тип — untyped. Каталог принадлежит root, писать в него нужно через sudo.

Конфигурация

9

Ключи запуска

Настроек в файле у экспортёра нет — только ключи командной строки. Служба берёт их из переменной ARGS в /etc/default/prometheus-node-exporter; в пакете она пустая (ARGS=""), то есть всё по умолчанию:

bash
# /etc/default/prometheus-node-exporter
ARGS="--web.listen-address=127.0.0.1:9100 --no-collector.zfs"

После правки — sudo systemctl restart prometheus-node-exporter. reload здесь не годится: см. node-exporter. Все ключи с описаниями — prometheus-node-exporter --help.

Адрес и порт

По умолчанию экспортёр слушает порт 9100 на всех адресах машины:

text
$ ss -tlnp | grep 9100
LISTEN 0  4096  *:9100  *:*  users:(("prometheus-node",pid=1178,fd=3))

Адрес и порт задаёт ключ --web.listen-address. Его ставят в ARGS файла /etc/default/prometheus-node-exporter или в дополнении службы (sudo systemctl edit prometheus-node-exporter → файл /etc/systemd/system/prometheus-node-exporter.service.d/override.conf, где строка ExecStart= заменяет команду запуска). Где ключ задан на самом деле:

  • systemctl cat prometheus-node-exporter — юнит вместе с дополнениями, у каждого файла — строка # /путь;
  • systemctl status prometheus-node-exporter — в строке CGroup под номером процесса видна вся команда с ключами;
  • ss -tlnp | grep prometheus-node — какой порт слушает сейчас.

Пароля и шифрования нет: кто достучался до порта, тот видит метрики. --web.listen-address=127.0.0.1:9100 оставляет доступ только с самой машины — тогда Prometheus с другой машины получит connection refused. Если Prometheus живёт на другой машине, экспортёр слушает её внешний адрес, а порт в firewall открыт только для адреса Prometheus.

Метрики — только по пути /metrics. На любой другой путь экспортёр отвечает HTML-страницей с кодом 200, и Prometheus с неверным metrics_path пишет в lastError expected a valid start token, got "<" (prometheus).

Директива Что делает Пример
--web.listen-address ARGS Адрес и порт, на которых экспортёр ждёт Prometheus; без адреса — все адреса машины. --web.listen-address=127.0.0.1:9100
--web.telemetry-path ARGS Путь, по которому отдаются метрики. --web.telemetry-path=/metrics
--collector.<имя> ARGS Включить коллектор, выключенный по умолчанию. --collector.processes
--no-collector.<имя> ARGS Выключить коллектор, включённый по умолчанию. --no-collector.zfs
--collector.disable-defaults ARGS Выключить все коллекторы по умолчанию; нужные включают ключами --collector.<имя>. --collector.disable-defaults --collector.meminfo
--collector.textfile.directory ARGS Каталог с файлами *.prom, которые экспортёр отдаёт вместе со своими метриками. --collector.textfile.directory=/var/lib/prometheus/node-exporter
--collector.netdev.device-exclude ARGS Регулярное выражение сетевых интерфейсов, которых нет в node_network_*. --collector.netdev.device-exclude=^(lo|veth.*)$
--collector.filesystem.mount-points-exclude ARGS Регулярное выражение точек монтирования, для которых нет node_filesystem_*; /mnt и /media в нём по умолчанию. --collector.filesystem.mount-points-exclude=^/(dev|proc|run|sys)($|/)
--collector.systemd.unit-include ARGS Регулярное выражение юнитов, состояние которых попадает в node_systemd_unit_state. --collector.systemd.unit-include=(nginx|ssh)\.service

Ничего не найдено. Попробуй запрос короче.

Рецепты

4

Проверить экспортёр на самой машине

bash
systemctl is-active prometheus-node-exporter
ss -tlnp | grep 9100
curl -s localhost:9100/metrics | grep '^node_load1 '

active, строка LISTEN и значение node_load1 — экспортёр в порядке. Дальше смотри, собирает ли его Prometheus: prometheus.

Собирать вторую машину

На node2 включи экспортёр и проверь, что он слушает не только 127.0.0.1. На node1 добавь цель в задание node и перечитай конфиг:

yaml
scrape_configs:
  - job_name: node
    static_configs:
      - targets: ['localhost:9100', 'node2:9100']
bash
promtool check config /etc/prometheus/prometheus.yml
sudo systemctl reload prometheus

Через интервал сбора up{instance="node2:9100"} должен стать 1. Если 0 — lastError цели называет причину (prometheus).

Метрика из своего скрипта

Пиши во временный файл в том же каталоге и переименовывай: mv подменяет файл целиком, и экспортёр не прочитает его наполовину записанным.

bash
d=/var/lib/prometheus/node-exporter
m=backup_last_success_timestamp_seconds
echo "$m $(date +%s)" > "$d/backup.tmp"
mv "$d/backup.tmp" "$d/backup.prom"

Скрипт работает от root: каталог принадлежит ему. Файлы без расширения .prom экспортёр пропускает. Правило «копии нет больше суток» — time() - backup_last_success_timestamp_seconds > 86400 (promql).

Состояние службы в метриках

text
$ curl -s localhost:9100/metrics \
    | grep 'node_systemd_unit_state{name="ssh.service"'
node_systemd_unit_state{name="ssh.service",state="activating",
  type="notify"} 0
node_systemd_unit_state{name="ssh.service",state="active",
  type="notify"} 1
…

Каждая строка вывода здесь перенесена. Служба не работает — node_systemd_unit_state{name="nginx.service",state="active"} == 0.

Неполадки

6

connection refused на порту 9100

curl localhost:9100/metrics отвечает Failed to connect, а цель в Prometheus — down с ошибкой:

text
Get "http://localhost:9100/metrics": dial tcp 127.0.0.1:9100:
  connect: connection refused

Порт никто не слушает. Проверь systemctl status prometheus-node-exporter, потом ss -tlnp | grep prometheus-node: экспортёр может слушать другой порт или только 127.0.0.1, а Prometheus идёт на внешний адрес.

context deadline exceeded

Prometheus не дождался ответа за scrape_timeout (10 секунд по умолчанию). Обычно пакеты молча отбрасывает файрвол на машине с экспортёром: connection refused пришёл бы сразу. Проверь правила firewall для порта 9100.

reload остановил экспортёр

text
$ sudo systemctl reload prometheus-node-exporter
$ systemctl is-active prometheus-node-exporter
inactive

В журнале — Deactivated successfully. Перечитывать экспортёру нечего: сигнал, который шлёт reload, его завершает. Ключи из ARGS применяет restart, остановленный экспортёр поднимает start.

Нет метрик node_network_*

curl -s localhost:9100/metrics | grep node_network_receive пуст, а rate(node_network_receive_bytes_total[1m]) ничего не возвращает. У машины с одной ВМ только интерфейс lo, а экспортёр его пропускает: --collector.netdev.device-exclude по умолчанию ^lo$. На машине с сетевым интерфейсом ряды есть, по одному на device.

Нет рядов для точки монтирования

node_filesystem_avail_bytes{mountpoint="/mnt/data"} пуст, хотя df том видит. Точка подходит под --collector.filesystem.mount-points-exclude — по умолчанию это /mnt, /media, /run и другие (node-exporter). Задай в ARGS своё выражение, например --collector.filesystem.mount-points-exclude=^/(dev|proc|run|sys)($|/), и перезапусти экспортёр. Какие точки он видит — curl -s localhost:9100/metrics | grep '^node_filesystem_size_bytes'.

node_textfile_scrape_error 1

Файл в каталоге textfile не разобран. Какой и почему — в журнале:

text
$ journalctl -u prometheus-node-exporter -o cat | grep textfile
… level=error collector=textfile msg="failed to collect textfile data"
  file=bad.prom err="failed to parse textfile data from
  \"/var/lib/prometheus/node-exporter/bad.prom\": text format parsing
  error in line 1: expected float as value, got \"metric\""

Строка значения — это имя, пробел и число: имя 42 или имя{метка="x"} 42. Остальные файлы каталога экспортёр отдаёт как обычно.

Опасно

1

Порт 9100 открыт всем

Метрики рассказывают о машине много: версию ядра, точки монтирования, список служб, сетевые интерфейсы. Экспортёр на *:9100 без файрвола на машине с публичным адресом отдаёт это любому. Ограничь доступ адресом прослушивания или правилом firewall.

Термины

1
экспортёр exporter
Программа, которая отдаёт метрики системы или службы по HTTP в текстовом формате Prometheus, обычно по пути /metrics. Для самой машины — node_exporter на порту 9100. Ещё встречается в: Prometheus: сбор метрик и правила алертов, PromQL: язык запросов Prometheus, Файрвол, Alertmanager: кому и сколько раз уходят алерты и ещё 1

См. также

  • prometheus — кто собирает эти метрики и как.
  • promql — как превратить их в скорости, доли и пороги.
  • system-monitoring — те же величины командами top, free, iostat.
  • firewall — открыть порт 9100 только для Prometheus.
  • ss — какой адрес и порт слушает экспортёр.
  • systemctl — enable --now, restart, status.
  • load-average — что значат node_load1 и соседи.
  • curl — запросить /metrics из терминала.
Загрузка…