Модуль 2 · Как работает Prometheus · Макаров М. Н.

Модуль 2 · как работает prometheus · сбор метрик

Глава 2.2

2.2

Target: куда обращаться
за метриками

Prometheus обращается к приложению за метриками по адресу из своих настроек. В этой главе разобрано, что такое target, из каких частей складывается адрес запроса и что означают слова job и instance. Отдельно разобрано, почему адрес localhost работает на компьютере и не работает в контейнере.

Категория
Настройка сбора
Уровень
Средний
Опирается на
Глава 2.1: части системы; основы Docker
Результат
Правильный адрес target для своего окружения

§1Понятие target

В главе 2.1 сервер Prometheus обращался к приложению и забирал у него числа. Чтобы обратиться, нужен адрес, и сервер берёт его из своего списка. Этот список похож на список квартир у контролёра, который снимает показания счётчиков воды: в квартиру, которой нет в списке, контролёр не придёт. Так же Prometheus не опрашивает программу, адреса которой в его списке нет. Одна строка этого списка называется target.

Targetцель сбора · один адрес

Адрес, по которому Prometheus регулярно запрашивает метрики. Обычно один target — это одна запущенная программа.

В настройках target записывают в виде хост:порт, например api:8000 или localhost:8000.

Список хранится в файле настроек prometheus.yml в формате YAML; правила этого формата собраны в главе 2.7. На стенде модуля этот файл занимает восемь строк, и target в нём один.

stand/prometheus.ymlрабочая конфигурация
global:
  scrape_interval: 15s
  scrape_timeout: 10s

scrape_configs:
  - job_name: api
    static_configs:
      - targets: ['api:8000']

Файл читается сверху вниз. Раздел global задаёт настройки для всех заданий сразу: опрашивать раз в 15 секунд и ждать ответа не дольше 10 секунд. Эти два числа разбирает глава 2.4. Раздел scrape_configs содержит список заданий сбора, на стенде задание одно, и оно названо api. Внутри задания в строке targets записан адрес: хост api и порт 8000.

В файле записано только api:8000. Запрос же уходит на полный адрес, и следующий раздел показывает, откуда берутся остальные его части.

§2Как собирается адрес запроса

На письме внутри города пишут улицу и дом. Страну и город почта подставляет сама, потому что письмо отправлено из этого же города. Адрес target устроен так же: в настройках пишут хост и порт, а начало http:// и конец /metrics Prometheus подставляет сам. Запрос уходит на адрес из трёх частей.

Полный адрес запроса на стендетри части
http://Протокол. Подставляется сам
api:8000Хост и порт. Записаны в targets
/metricsПуть. Подставляется сам

Вручную записана только средняя часть. Две другие можно изменить отдельными параметрами задания: протокол — параметром scheme, путь — параметром metrics_path. Путь меняют, когда программа отдаёт метрики по другому адресу. Например, сервисы на Spring Boot отдают их по пути /actuator/prometheus.

Из этого устройства следуют две частые ошибки. Первая — записать в targets полный адрес http://api:8000/metrics. Prometheus такой файл не принимает, и программа проверки promtool check config сообщает: "http://api:8000/metrics" is not a valid hostname. Вторая ошибка — не указать порт. Тогда Prometheus берёт порт по умолчанию: 80 для http и 443 для https. На стенде для target api получился адрес http://api/metrics, а приложение работает на порту 8000, поэтому запрос не прошёл.

Где посмотреть собранный адрес

Собранный адрес виден в веб-интерфейсе Prometheus на странице Status → Target health, в колонке Endpoint. Стрелка рядом с метками раскрывает список Discovered labels.

Target health в Prometheus 3.5: target http://api:8000/metrics, метки instance и job, ниже раскрытый список Discovered labels
Status → Target health, раскрыт список Discovered labels · стенд модуля

В раскрытом списке стоят служебные метки. Их имена начинаются с двух подчёркиваний. В них Prometheus хранит части адреса и настройки опроса: __scheme__ — протокол, __address__ — хост и порт, __metrics_path__ — путь, __scrape_interval__ и __scrape_timeout__ — частоту опроса и время ожидания. Служебные метки нужны только до начала опроса, в сохранённые данные они не попадают.

В сохранённых данных остаются две обычные метки: job и instance. На снимке они стоят над служебными, и следующий раздел объясняет, что они означают.

§3Job и instance

На стенде программа одна, но в настоящей работе один сервис запускают в нескольких копиях. Копии делят между собой нагрузку, и если одна остановится, остальные продолжат работать. У каждой копии свой адрес, поэтому для Prometheus это разные target. Чтобы не потерять связь между ними, нужны два уровня названий: одно для сервиса в целом и одно для каждой копии.

Сравнение из жизни
Сеть кофеен

У сети одно название и несколько точек по разным адресам. Выручку считают по всей сети или по одной точке.

Сервис и его копии

Job — название сервиса. Instance — одна копия по своему адресу. Запросы считают по всему сервису или по одной копии.

Instance и jobэкземпляр и задание

Instance — один адрес, с которого собираются метрики. Обычно это одна запущенная программа. Метка instance равна её адресу хост:порт.

Job — группа instance с одним назначением, например все копии одного сервиса. Метка job равна названию задания job_name.

Документация Prometheus показывает это на примере сервиса api-server, запущенного в четырёх копиях на двух машинах. В файле настроек это одно задание с четырьмя адресами.

prometheus.ymlодин job, четыре instance
  - job_name: api-server
    static_configs:
      - targets:
          - '1.2.3.4:5670'
          - '1.2.3.4:5671'
          - '5.6.7.8:5670'
          - '5.6.7.8:5671'

На схеме те же четыре адреса разложены по машинам.

Один job и четыре instanceдокументация Prometheus
job="api-server"
машина 1.2.3.4

instance="1.2.3.4:5670"

instance="1.2.3.4:5671"

машина 5.6.7.8

instance="5.6.7.8:5670"

instance="5.6.7.8:5671"

На каждой машине работают две программы на разных портах. Поэтому instance — это хост и порт вместе: одного хоста для различения программ недостаточно. Каждое число каждой копии получит метку job="api-server" и свою метку instance. По этим меткам запрос складывает значения всего сервиса или выбирает одну копию.

На стенде модуля всё проще: в задании api один instance, api:8000. Все target одного задания в интерфейсе называются scrape pool, и на странице Target health они показаны одним блоком.

Status → Target health: scrape pool api, 1/1 up, target http://api:8000/metrics в состоянии UP
Задание api на стенде: один instance, состояние UP

Адрес api:8000 пока записан без объяснения. Следующий раздел объясняет, почему на стенде записан он, а привычный localhost не работает.

§4Адрес зависит от места Prometheus

Приложение стенда открывается в браузере по адресу localhost:8020. Кажется, что тот же адрес подойдёт и для Prometheus. На стенде он не подходит. Причина в том, что слово localhost означает разное в зависимости от того, кто его читает.

Сравнение из жизни
«Квартира 5» в разных домах

Записка «зайди в квартиру 5» ведёт в разные квартиры. Жилец первого дома придёт в квартиру 5 своего дома, жилец второго дома — в квартиру 5 своего.

localhost в разных местах

Слово localhost означает «тот компьютер, на котором я запущен». Для программы на компьютере это компьютер. Для программы в контейнере это её собственный контейнер.

У каждого контейнера Docker своя сеть: свой localhost и свои порты. На стенде контейнеров два, приложение и Prometheus. Они описаны в файле compose.yaml и объединены в одну сеть Docker Compose. Внутри этой сети контейнеры находят друг друга по именам сервисов, поэтому приложение доступно по имени api.

Компьютер, сеть Compose и два контейнерастенд модуля
Компьютер

Браузер и терминал работают здесь. Приложение открывается как localhost:8020, Prometheus — как localhost:9092.

Сеть Docker Compose
контейнер api

Приложение работает на порту 8000. Адрес внутри сети: api:8000.

контейнер prometheus

Сервер работает на порту 9090. Его localhost — этот контейнер.

По схеме видно, почему у одного приложения два адреса. Строка ports: ['127.0.0.1:8020:8000'] в compose.yaml открывает порт 8000 контейнера на компьютере под номером 8020, и этим адресом пользуется браузер. Prometheus находится внутри сети и обращается к приложению напрямую: по имени api и внутреннему порту 8000. Если записать ему localhost:8000, он обратится к собственному контейнеру, где на этом порту ничего не работает.

Какой адрес работает из какого места

Это рассуждение можно проверить для других сочетаний. В блоке ниже выберите, где запущен Prometheus и какой адрес записан в настройках. Результаты с пометкой «проверено» получены на стенде.

Где работает Prometheus и какой target записанвыберите оба варианта
Prometheus работает
Target в prometheus.yml
PrometheusTargetРезультат
В сети Composeapi:8000UP
В сети Composelocalhost:8000DOWN: connection refused
Вне сетиhost.docker.internal:8020UP
На компьютереlocalhost:8020UP

Все сочетания сводятся к одному правилу: адрес target записывают таким, каким он доступен из места, где запущен Prometheus. Если Prometheus работает в одной сети Compose с приложением, это имя сервиса и внутренний порт: api:8000. Если он запущен на компьютере без Docker, это порт, открытый на компьютере: localhost:8020. Если он работает в контейнере вне сети приложения, это имя компьютера, видимое из контейнера: host.docker.internal:8020.

На стенде адрес один, и он записан вручную. Следующий раздел показывает, что делают, когда адресов много и они меняются.

§5Откуда берётся список target

В маленькой фирме список сотрудников пишут на листе бумаги. В большой компании люди приходят и уходят каждый день, и список берут из системы отдела кадров. Со списком target так же. Когда программ мало и адреса постоянные, их записывают в файл вручную: на стенде это параметр static_configs. Когда копии сервиса появляются и исчезают каждые несколько минут, вручную список не поддержать, и его берут из внешней системы.

Автоматическое получение списка называется service discovery — обнаружение сервисов. Источников несколько, и для каждого есть свой параметр задания. Параметр file_sd_configs читает адреса из файлов, которые пишет другая программа. Параметр dns_sd_configs берёт их из записей DNS, kubernetes_sd_configs — из Kubernetes, а параметры вида consul_sd_configs и ec2_sd_configs — из реестра сервисов или облака. Результат у всех способов одинаковый: список target со служебными метками из §2.

Своя метка для target

Вместе с адресом в настройках можно записать постоянную метку. Она появится на всех числах этого target. Например, метка env со значением dev отмечает, что программа работает в среде разработки, и потом по ней отбирают ряды в запросах.

prometheus.ymlметка env для target
    static_configs:
      - targets: ['api:8000']
        labels:
          env: dev
Подробнее: изменение меток до опроса

Внешняя система может добавить свои служебные метки. Например, Kubernetes добавляет __meta_kubernetes_pod_name с именем пода. До начала опроса метки можно изменить правилами relabel_configs: переименовать, скопировать в обычную метку или исключить target из списка. После этого все метки с __ удаляются.

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

§6Метки target и метки приложения

Приложение записывает свои метки в ответе: в главе 2.1 это были method и status. Prometheus добавляет свои: job, instance и метки из параметра labels. Обычно эти наборы не пересекаются. Но иногда приложение отдаёт метку с именем job или instance, и тогда у одного числа оказываются две метки с одним именем. Сохранить можно только одну.

Похожая ситуация бывает с посылкой. На коробке уже есть наклейка магазина с адресом, и служба доставки должна наклеить свою. Она либо оставляет старую наклейку рядом с пометкой, либо оставляет её единственной и свою не клеит. В Prometheus этот выбор делает параметр задания honor_labels.

Оба варианта проверены на стенде. Программа отдаёт одно число с метками job="nightly-report" и instance="worker-7", и её опрашивают два задания с разными значениями параметра.

Результат при двух значениях honor_labelsPrometheus 3.5.0
Ответ программы
batch_last_success_timestamp_seconds job="nightly-report" instance="worker-7" 1790640000
Сохранено при honor_labels: false · значение по умолчанию
job="default-labels" instance="echo2:8000" env="dev" exported_job="nightly-report" exported_instance="worker-7"
Сохранено при honor_labels: true
job="nightly-report" instance="worker-7"

Голубые плашки — метки из ответа программы. Оранжевые — метки, которые добавил Prometheus.

При значении по умолчанию под именами job и instance сохранены метки Prometheus, а метки приложения получили приставку exported_. Метки приложения сохранены, и видно, откуда пришло каждое значение. При honor_labels: true под этими именами сохранены метки приложения, а меток Prometheus на числе нет.

Поэтому для обычного приложения параметр оставляют выключенным. Его включают для программ, которые передают чужие метрики. Пример — Pushgateway из главы 2.5: он хранит числа других программ, и метки job и instance в его ответе описывают эти программы.

§7Проверьте себя

Вопрос 1Prometheus и приложение запущены в одной сети Compose, сервис приложения называется api, порт внутри контейнера 8000, на компьютере открыт как 8020. Какой target записать?

  • Этот адрес работает с компьютера. Внутри контейнера Prometheus localhost — сам контейнер, на стенде ошибка connection refused.

  • Верно. Контейнеры одной сети находят друг друга по имени сервиса, а внутри сети доступен порт контейнера 8000.

  • В targets пишут только хост и порт. Протокол и путь задаются параметрами scheme и metrics_path.

Вопрос 2Какой будет метка instance у чисел target api:8000, если её не задавать?

  • Верно. По умолчанию instance равна адресу из targets.

  • Полный адрес в метки не записывается. Он виден только в колонке Endpoint на странице Target health.

  • Prometheus записывает адрес так, как он указан в настройках.

Вопрос 3Приложение отдаёт число с меткой job="worker", задание называется api, honor_labels не указан. Какие метки получит число?

  • Так будет с honor_labels: true. По умолчанию под именем job сохраняется метка Prometheus.

  • Верно. Метка приложения сохраняется с приставкой exported_.

  • Ошибки нет: выбор определяет параметр honor_labels.

Вопрос 4Чем job отличается от instance?

  • Instance — это хост и порт вместе. Job к адресам не привязан.

  • Верно. Так эти понятия определены в документации Prometheus.

  • Обе метки ставит Prometheus: job из названия задания, instance из адреса target.

Источники главы
  1. Prometheus. Jobs and instances — prometheus.io/docs/concepts/jobs_instances
  2. Prometheus. Configuration: scrape_config, static_config, relabel_config — prometheus.io/docs/prometheus/latest/configuration/configuration
  3. Docker. Networking in Compose — docs.docker.com/compose/how-tos/networking
  4. Стенд модуля: Prometheus 3.5.0, Docker Desktop; опыты с адресами и honor_labels выполнены 29.09.2026
Метрики и наблюдаемость · Модуль 2 · Как работает Prometheus Автор: Макаров Максим Николаевич