Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Service Discovery: обнаружение целей
service_discovery

Service Discovery: обнаружение целей

Динамическое обнаружение целей в Docker и файловых конфигурациях

Service Discovery: автоматическое обнаружение целей

«В динамическом мире статическая конфигурация — это технический долг»

#Проблема статической конфигурации

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

scrape_configs: - job_name: 'node' static_configs: - targets: - 'server1:9100' - 'server2:9100' - 'server3:9100'

Проблема: в динамической среде (Docker, Kubernetes, облака) цели постоянно меняются:

  • Контейнеры запускаются и останавливаются
  • Поды Kubernetes перемещаются между нодами
  • Автоскейлинг добавляет и удаляет серверы

Решение: Service Discovery (SD) — автоматическое обнаружение целей.


#Как работает Service Discovery

┌─────────────────────────────────────────────────────────────┐
│                      Prometheus                              │
│                                                              │
│  ┌────────────────────────────────────────────────────────┐ │
│  │  Service Discovery                                     │ │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐               │ │
│  │  │ Docker   │ │ K8s      │ │ Consul   │               │ │
│  │  │ SD       │ │ SD       │ │ SD       │               │ │
│  │  └──────────┘ └──────────┘ └──────────┘               │ │
│  └────────────────────────────────────────────────────────┘ │
│                           │                                   │
│                           ▼                                   │
│              ┌─────────────────────────┐                     │
│              │  Relabeling             │                     │
│              │  (фильтрация и лейблы)  │                     │
│              └─────────────────────────┘                     │
│                           │                                   │
│                           ▼                                   │
│              ┌─────────────────────────┐                     │
│              │  Targets для скрапинга  │                     │
│              └─────────────────────────┘                     │
└─────────────────────────────────────────────────────────────┘

Процесс:

  1. SD подключается к источнику (Docker API, Kubernetes API, Consul)
  2. Получает список доступных целей
  3. Применяет relabeling (фильтрация, добавление лейблов)
  4. Обновляет список целей для скрапинга

#Docker Service Discovery

Автоматическое обнаружение контейнеров Docker.

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

scrape_configs: - job_name: 'docker' docker_sd_configs: - host: unix:///var/run/docker.sock refresh_interval: 5s filters: - name: label values: ['prometheus_scrape'] relabel_configs: - source_labels: [__meta_docker_container_name] target_label: container - source_labels: [__meta_docker_container_label_prometheus_job] target_label: job - source_labels: [__meta_docker_container_port_number] target_label: __address__

Разбираем:

#docker_sd_configs

  • host — адрес Docker daemon (unix socket или tcp://)
  • refresh_interval — как часто обновлять список целей

#filters

Фильтрует контейнеры перед добавлением:

filters: - name: label values: ['prometheus_scrape']

Только контейнеры с лейблом prometheus_scrape=true будут добавлены.

#relabel_configs

Преобразует метаданные контейнера в лейблы Prometheus:

- source_labels: [__meta_docker_container_name] target_label: container

_meta лейблы (автоматически добавляются Docker SD):

  • __meta_docker_container_name — имя контейнера
  • __meta_docker_container_label_* — лейблы контейнера
  • __meta_docker_container_port_number — порт
  • __meta_docker_network_ip — IP адрес в сети

#Пример: Docker Compose с SD

#docker-compose.yml

version: '3.8' services: prometheus: image: prom/prometheus:v2.52.0 container_name: prometheus ports: - "9090:9090" volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml - /var/run/docker.sock:/var/run/docker.sock:ro command: - '--config.file=/etc/prometheus/prometheus.yml' restart: unless-stopped api: image: myapp/api:latest labels: - prometheus_scrape=true - prometheus_job=api - prometheus_port=8000 ports: - "8000:8000" worker: image: myapp/worker:latest labels: - prometheus_scrape=true - prometheus_job=worker - prometheus_port=9000

#prometheus.yml

global: scrape_interval: 15s scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'docker' docker_sd_configs: - host: unix:///var/run/docker.sock refresh_interval: 5s filters: - name: label values: ['prometheus_scrape'] relabel_configs: # Используем лейбл prometheus_job как имя job - source_labels: [__meta_docker_container_label_prometheus_job] target_label: job # Порт из лейбла prometheus_port - source_labels: [__meta_docker_container_label_prometheus_port] target_label: __address__ # Имя контейнера как лейбл - source_labels: [__meta_docker_container_name] target_label: container

Как работает:

  1. Prometheus подключается к Docker socket
  2. Находит контейнеры с лейблом prometheus_scrape=true
  3. Для каждого контейнера:
    • Берёт порт из prometheus_port лейбла
    • Устанавливает job из prometheus_job
    • Добавляет лейбл container с именем
  4. Скрапит метрики с /metrics эндпоинта

Преимущество: добавьте новый контейнер с лейблами — Prometheus автоматически начнёт его скрапить.


#File Service Discovery

SD из JSON-файлов.

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

scrape_configs: - job_name: 'node' file_sd_configs: - files: - '/etc/prometheus/targets/node.json' refresh_interval: 5m relabel_configs: - source_labels: [__address__] target_label: instance

#Файл targets/node.json

[ { "targets": ["server1:9100", "server2:9100"], "labels": { "env": "production", "datacenter": "us-east", "team": "backend" } }, { "targets": ["server3:9100"], "labels": { "env": "staging", "datacenter": "eu-west", "team": "frontend" } } ]

Формат:

  • targets — список адресов
  • labels — лейблы для всех target в группе

Преимущества:

  • Можно обновлять без перезапуска Prometheus
  • Легко генерировать скриптами
  • Подходит для средних инфраструктур

#Генерация файла скриптом

#!/usr/bin/env python3 import json import boto3 # Пример: генерация из AWS EC2 ec2 = boto3.client('ec2') instances = ec2.describe_instances( Filters=[{'Name': 'tag:Environment', 'Values': ['production']}] ) targets = [] for reservation in instances['Reservations']: for instance in reservation['Instances']: targets.append({ "targets": [f"{instance['PrivateIpAddress']}:9100"], "labels": { "env": "production", "instance_id": instance['InstanceId'], "az": instance['Placement']['AvailabilityZone'] } }) with open('/etc/prometheus/targets/node.json', 'w') as f: json.dump(targets, f, indent=2)

Запускайте скрипт по cron каждые 5 минут.


#HTTP Service Discovery

SD из HTTP-эндпоинта.

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

scrape_configs: - job_name: 'consul' http_sd_configs: - url: 'http://consul:8500/v1/health/service/prometheus' refresh_interval: 5s

Источники:

  • Consul
  • Custom API
  • Сервис регистрации

#Kubernetes Service Discovery

Автоматическое обнаружение подов и сервисов в Kubernetes.

#Скрапинг подов

scrape_configs: - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod kubeconfig_file: /etc/prometheus/kubeconfig selectors: - role: pod label: prometheus.io/scrape=true relabel_configs: # Порт из аннотации - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port] action: replace target_label: __address__ regex: (.+) replacement: $1 # Path из аннотации - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] action: replace target_label: __metrics_path__ regex: (.+) # Имя пода как лейбл - source_labels: [__meta_kubernetes_pod_name] target_label: pod # Namespace как лейбл - source_labels: [__meta_kubernetes_namespace] target_label: namespace

Аннотации в поде:

apiVersion: v1 kind: Pod metadata: name: myapp annotations: prometheus.io/scrape: "true" prometheus.io/port: "8080" prometheus.io/path: "/metrics" spec: containers: - name: app image: myapp:latest ports: - containerPort: 8080

_meta_kubernetes лейблы:

  • __meta_kubernetes_pod_name — имя пода
  • __meta_kubernetes_namespace — namespace
  • __meta_kubernetes_pod_label_* — лейблы пода
  • __meta_kubernetes_pod_annotation_* — аннотации пода
  • __meta_kubernetes_pod_ip — IP пода

#Relabeling: преобразование метаданных

Relabeling — мощный механизм преобразования метаданных перед скрапингом.

#Основные действия

actionОписание
replaceЗаменить значение лейбла (по умолчанию)
keepОставить target только если regex совпадает
dropОтбросить target если regex совпадает
labelmapСоздать лейблы из matching meta-лейблов
labeldropУдалить лейблы по regex

#Примеры

Фильтрация по лейблу:

relabel_configs: - source_labels: [__meta_docker_container_label_prometheus_scrape] action: keep regex: "true"

Только контейнеры со prometheus_scrape=true будут добавлены.

Изменение адреса:

relabel_configs: - source_labels: [__meta_docker_container_ip, __meta_docker_container_port] separator: ':' target_label: __address__

Добавление статического лейбла:

relabel_configs: - target_label: env replacement: production

Labelmap — копирование всех лейблов:

relabel_configs: - action: labelmap regex: __meta_docker_container_label_(.+) replacement: $1

Копирует все лейблы контейнера в лейблы Prometheus.


#Metric Relabeling

metric_relabel_configs применяется к метрикам после сбора (перед хранением).

#Пример: отбросить лишние метрики

metric_relabel_configs: - source_labels: [__name__] regex: 'go_.*' action: drop

Отбрасывает все метрики, начинающиеся с go_ (внутренние метрики Go runtime).

#Пример: оставить только нужные

metric_relabel_configs: - source_labels: [__name__] regex: 'node_(cpu|memory|disk|net)_.*' action: keep

Сохраняет только ключевые метрики Node Exporter.

#Пример: переименовать метрику

metric_relabel_configs: - source_labels: [__name__] regex: 'http_requests(.*)' target_label: __name__ replacement: 'api_requests$1' action: replace

Переименовывает http_requests_total в api_requests_total.


#Best practices Service Discovery

#1. Используйте фильтрацию

Не скрапьте всё подряд. Фильтруйте по лейблам:

filters: - name: label values: ['prometheus_scrape']

#2. Добавляйте информативные лейблы

relabel_configs: - source_labels: [__meta_docker_container_name] target_label: container - source_labels: [__meta_docker_container_label_com_docker_compose_service] target_label: service - source_labels: [__meta_docker_network_ip] target_label: instance

#3. Разделяйте job по типам

# Отдельно для API - job_name: 'docker-api' filters: - name: label values: ['prometheus_job=api'] # Отдельно для воркеров - job_name: 'docker-worker' filters: - name: label values: ['prometheus_job=worker']

#4. Настройте refresh_interval

  • Docker: 5-10s (контейнеры часто меняются)
  • File SD: 1-5m (серверы меняются реже)
  • Kubernetes: 5-30s (поды перемещаются)

#5. Используйте metric_relabel для экономии

Отбрасывайте ненужные метрики для экономии места:

metric_relabel_configs: - source_labels: [__name__] regex: 'go_.*|process_.*' action: drop

#Отладка SD

#Проверка обнаруженных целей

В Prometheus UI:

  1. Status → Service Discovery
  2. Увидите список всех обнаруженных целей
  3. Зелёные = активны, серые = отфильтрованы

#Проверка лейблов

В Prometheus UI:

  1. Status → Targets
  2. Кликните на target
  3. Увидите все лейблы (включая _meta*)

#Логирование

Добавьте в Prometheus:

global: log_level: debug

Или через командную строку:

prometheus --log.level=debug

Далее: Best practices: как не наступить на грабли