linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • Симулятор
  • База знаний
  • Собеседование
Index
Categories
All entries
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
home/linux/kb/Observability и мониторинг/service-discovery-prometheus

kb/observability ── Observability и мониторинг ── advanced

Service discovery в Prometheus: k8s, Consul, file_sd, relabel

Prom discoverит targets через k8s API, Consul, file_sd (static). relabel_configs - до scrape (filter+rewrite labels). metric_relabel - после scrape (drop bad metrics). Без relabel - cardinality из k8s взрывается.

view as markdownaka: service-discovery, prometheus-sd, kubernetes-sd, consul-sd, relabel, relabel-configs

Зачем service discovery

Static config работает на 5 хостах. На 500, нет. В Kubernetes endpoints меняются каждую секунду (rollouts, autoscaling). Должен быть способ автоматически узнавать кого scrape'ать.

Решение, service discovery (SD): Prometheus говорит «дай мне все pods/services с такими-то labels», SD-mechanism возвращает список endpoint'ов. Prom их scrape'ает.

Поддерживается ~30 SD механизмов: kubernetes, consul, dns, ec2, azure, gce, file_sd, http_sd. Самые ходовые, k8s и consul.

Discovery → relabel → scrape

┌──────────────┐
│ SD mechanism │  возвращает targets c meta-labels
│ (k8s, etc)   │  __meta_kubernetes_pod_name, etc
└──────┬───────┘
       │ raw targets с __meta_* labels
       ▼
┌──────────────┐
│  relabel_    │  фильтр + трансформация labels
│  configs     │  action: keep/drop/replace/labelmap
└──────┬───────┘
       │ финальные targets
       ▼
┌──────────────┐
│  scrape      │  HTTP GET /metrics
└──────┬───────┘
       │ raw metrics
       ▼
┌──────────────┐
│  metric_     │  drop bad metrics, rewrite names
│  relabel_    │
│  configs     │
└──────┬───────┘
       │
       ▼
     TSDB

Critical insight: __meta_* labels отбрасываются после relabel. Если нужны в TSDB, explicit replace action.

Kubernetes SD

yaml
scrape_configs:
  - job_name: kubernetes-pods
    kubernetes_sd_configs:
      - role: pod              # pod | service | endpoints | endpointslices | node | ingress
    relabel_configs:
      # Только pods с annotation prometheus.io/scrape=true
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: 'true'
      # Берём порт из annotation prometheus.io/port
      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        regex: '([^:]+)(?::\d+)?;(\d+)'
        replacement: '$1:$2'
        target_label: __address__
      # Path из annotation prometheus.io/path (default /metrics)
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: '(.+)'
      # Все labels пода → metric labels с префиксом
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      # Convenience labels
      - source_labels: [__meta_kubernetes_namespace]
        target_label: namespace
      - source_labels: [__meta_kubernetes_pod_name]
        target_label: pod
      - source_labels: [__meta_kubernetes_pod_node_name]
        target_label: node

Result: каждый pod с prometheus.io/scrape=true annotation скрейпится. Все его k8s-labels копируются в metric labels.

Roles в kubernetes_sd

RoleЧто возвращаетКогда
nodeKubernetes nodes (kubelet)metric'и хоста, kubelet
podкаждый podapplication metrics
servicek8s Service объектыblackbox-probes к services
endpointsendpoints (legacy)замена service для kube-state-metrics
endpointslicesEndpointSlice (modern)k8s 1.21+, scale better
ingressIngress объектыcheck ingresses

Modern setup: endpointslices вместо endpoints (производительность на больших кластерах).

Consul SD

yaml
scrape_configs:
  - job_name: consul
    consul_sd_configs:
      - server: consul.example.com:8500
        tags: ['prometheus']      # только services с tag
    relabel_configs:
      - source_labels: [__meta_consul_service]
        target_label: service
      - source_labels: [__meta_consul_tags]
        target_label: tags

Consul популярен в non-k8s стеках (Nomad, classic VMs). Service registers себя в Consul, Prom через SD узнаёт.

file_sd, статика с гранулярностью

Когда нет k8s/Consul, но есть скрипт который знает кого scrape'ать:

yaml
scrape_configs:
  - job_name: file-discovery
    file_sd_configs:
      - files: ['/etc/prometheus/targets/*.json']
        refresh_interval: 30s

Файл:

json
[
  {
    "targets": ["host1:9100", "host2:9100"],
    "labels": {"env": "prod", "team": "infra"}
  },
  {
    "targets": ["dbhost:9187"],
    "labels": {"env": "prod", "team": "db"}
  }
]

Внешний инструмент (Ansible, terraform, chef) генерирует JSON. Prom auto-reload каждые 30s. Гибко и просто.

relabel actions

ActionЧто делает
replaceпишет в target_label значение regex.replace(source, replacement)
keepdrop target если source ~ regex НЕ матчится
dropdrop target если source ~ regex матчится
keepequalkeep если source == target
dropequaldrop если source == target
hashmodtarget_label = hash(source) % modulus (для sharding)
labelmapкопирует все labels matching regex (с переименованием)
labeldropудаляет labels matching regex
labelkeepоставляет только labels matching regex
lowercase / uppercasecase transform

keep и drop, самые ходовые для фильтрации. replace и labelmap, для shaping labels.

Sharding через hashmod

3 Prom скрейпят 1000 targets, делим поровну:

yaml
relabel_configs:
  - source_labels: [__address__]
    modulus: 3
    target_label: __tmp_hash
    action: hashmod
  - source_labels: [__tmp_hash]
    regex: '0'              # этот Prom, shard 0
    action: keep

Каждый Prom держит ~330 targets. Federation вверх агрегирует.

metric_relabel_configs, после scrape

Применяется к уже scrape'нным метрикам, до записи в TSDB.

yaml
scrape_configs:
  - job_name: ...
    metric_relabel_configs:
      # Drop high-cardinality метрики
      - source_labels: [__name__]
        regex: 'go_gc_pauses_seconds_bucket'
        action: drop
      # Drop конкретный label с user_id (cardinality)
      - regex: 'user_id'
        action: labeldrop
      # Rewrite metric name
      - source_labels: [__name__]
        regex: 'old_metric_name'
        replacement: 'new_metric_name'
        target_label: __name__

Используется для борьбы с cardinality-explosion от ill-behaved exporters. Лучше чинить в коде, но иногда нет доступа.

Best practices

  • Filter в SD-этапе, не на metric-этапе: keep/drop дешевле чем metric_relabel. Меньше нагрузка на target.
  • Convenient labels (namespace, pod, service), стабильные имена для всех jobs. Не __meta_kubernetes_* в queries.
  • Не копируй все pod labels через labelmap слепо, k8s навешивает controller-revision-hash, pod-template-hash etc. Cardinality. Whitelist через regex в labelmap:
    yaml
    - action: labelmap
      regex: __meta_kubernetes_pod_label_(app|version|component)
  • CI test relabel: promtool check config + конкретные dry-run через promtool (limited).

kube-state-metrics + node-exporter

Стандартный k8s monitoring stack:

  • node-exporter на каждой ноде → node_* метрики
  • kube-state-metrics одиночный → kube_* метрики о состоянии объектов k8s
  • cAdvisor в kubelet → container metrics
  • app metrics через annotation discovery

Все через k8s SD с разными relabel конфигами.

Когда что-то пошло не так

  • No targets in /targets, relabel keep слишком strict, не осталось. Уберай по одному правилу, проверяй UI.
  • Targets есть, но scrape error «401 Unauthorized», для kubelet-scrape нужен ServiceAccount + RBAC, или bearer_token_file: /var/run/secrets/.../token.
  • Cardinality explosion после rollout, labelmap copy'нул pod-template-hash. Whitelist labels.
  • Targets дублируются, одна и та же endpoint в нескольких roles. Используй deduplicating: один role + правильный selector.
  • Slow SD reload (5+ minutes), k8s API rate limit. Уменьши refresh_interval или используй endpointslices вместо endpoints.
  • __address__ неправильный port, k8s SD берёт первый declared port. Используй annotation override через replace.
  • Stale targets после k8s namespace delete, Prom держит до --query.lookback-delta (default 5m). Норма.

§ команды

bash
curl -s http://prometheus:9090/api/v1/targets | jq '.data.activeTargets[] | {scrapeUrl, labels}'

Все active targets с их финальными labels - после relabel

bash
curl -s http://prometheus:9090/api/v1/targets/metadata | jq '.data | length'

Сколько метрик описано в targets - предсказание объёма

bash
promtool check config /etc/prometheus/prometheus.yml

Валидация всего config: scrape_configs, relabel, rules

bash
curl -s http://prometheus:9090/api/v1/status/config | jq -r .data.yaml | grep -A 20 relabel

Live конфиг runtime - что Prom реально использует (после reload)

bash
kubectl get servicemonitor -A  # если используется prometheus-operator

ServiceMonitor CRD - декларативная замена scrape_configs в k8s

bash
consul catalog services -tags  # для consul SD

Все Consul services с tags - что Prom через consul_sd увидит

§ см. также

  • prometheus-basicsPrometheus: scrape, TSDB, PromQL и production-pitfallsPrometheus - сервер мониторинга: сам опрашивает приложения по HTTP, собирает числовые метрики, хранит во встроенной БД ~15 дней. По ним строят графики в Grafana и алерты через Alertmanager. Стандарт de-facto в Kubernetes.
  • kubernetes-services-and-ingressKubernetes Service и Ingress - сетевая публикация подовService - стабильный VIP перед группой подов (label selector). Типы: ClusterIP (внутри), NodePort (порт на каждой ноде), LoadBalancer (внешний LB облака), ExternalName (CNAME). Ingress - L7 reverse-proxy (nginx/traefik) для HTTP-роутинга.
  • cni-pluginsCNI plugins - сеть Kubernetes (calico, cilium, flannel)CNI - спека плагина: дай pod IP и сеть. Реализации: flannel (VXLAN L2-overlay), calico (BGP routing), cilium (eBPF в kernel). Каждая даёт NetworkPolicy для firewall'а между подами. IPAM - часть CNI, выделяет адреса.
  • kubelet-internalskubelet - архитектура агента ноды Kuberneteskubelet - демон на каждой ноде. Получает PodSpec через API, запускает контейнеры через CRI, монтирует volumes через CSI, следит за health. При pressure делает eviction. Image GC и cgroup-tree - тоже его.
  • cardinality-explosionCardinality explosion: как убить Prometheus и как чинитьCardinality = uniq(metric × labels). Каждый series ≈ 3 KB RAM, 10M series = 30 GB RAM, Prom OOM-цикл. Source: user_id-labels, пути с ID, dynamic version. Diag - topk по __name__. Cure - drop labels через relabel или нормализация в коде.
  • alerting-rules-alertmanagerAlertmanager: route tree, inhibit, dedup, on-callAlertmanager - принимает alerts от Prometheus, дедупит, группирует, роутит по route tree в PagerDuty/Slack/email. Inhibit suppress'ит зависимые alerts при upstream-падении. Silence на время maintenance. Шум убивает on-call.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки