Перейти к содержанию

05 — Мониторинг: Grafana + Prometheus

Живёт на n1, ns monitoring, раскатан прямым kubectl apply -k из fairflow-crm/k3s/monitoring/ (без Argo). Логов там нет — только метрики (graylog умер вместе со старой n1).

Что URL NodePort Доступ
Grafana https://grafana.ff 30030 admin, пароль: get_cred("monitoring","GRAFANA_ADMIN_PASSWORD")
Prometheus https://prometheus.ff 30090 без авторизации, tailnet-only

Retention 90 дней, PVC 50Gi. TLS — внутренний CA, доступ только из tailnet.

Что уже собирается (12 целей)

job откуда что даёт
node n1 192.168.1.36:9100, n2 192.168.1.151:9100, станция 100.78.147.13:9100 CPU/RAM/диск/сеть/температуры хоста
cadvisor n1/n2 :30808 контейнеры по cgroup-id (без имён подов)
kubelet-cadvisor через прокси API-серверов n1/n2 контейнеры с pod/namespace/container
smartctl n1/n2 :9633 здоровье и температура NVMe
kube-state-metrics n1 in-cluster, n2 :30810 объекты k8s: поды, деплойменты, PVC, ноды

Известная дырка: цель cadvisor n2 (:30808) — down (DaemonSet не поднят). Не критично, контейнеры n2 видны через kubelet-cadvisor-n2.

Для скрейпа n2 из n1 нужен токен SA — на n1 он лежит в secret prometheus-n2-token (ns monitoring).

Дашборды

Папка «Fairflow» в Grafana: сводка n1/n2, Node Exporter Full (1860), K8S по кластерам (15661), kube-state-metrics (13332), лёгкий обзор хостов, самодиагностика Prometheus (3662).

Дашборды file-provisioned: JSON лежит в k3s/monitoring/grafana/dashboards/, в UI они read-only — правится JSON и раскатывается заново.

Как завести свой сервис в мониторинг

  1. Приложение отдаёт /metrics (Prometheus-формат).
  2. Добавить цель в k3s/monitoring/prometheus.yml — либо статикой по NodePort/tailnet-адресу, либо через kubernetes_sd по аннотациям подов (для сервисов внутри n1).
  3. Раскатать:
    rsync -a --delete k3s/monitoring root@nubble01:/root/deploy-apps/
    ssh n1 'kubectl apply -k /root/deploy-apps/monitoring --server-side --force-conflicts'
    
    --server-side обязателен: дашборд Node Exporter Full не влезает в аннотацию last-applied.
  4. Проверить, что цель поднялась:
    ssh n1 'curl -s http://localhost:30090/api/v1/targets' \
      | jq -r '.data.activeTargets[] | "\(.labels.job) \(.labels.host) \(.health)"'
    
  5. Завести дашборд (JSON в grafana/dashboards/) и алерты.

ПРАВИЛО: каждое новое окружение/сервис = свой scrape-target + свои дашборды и алерты. Без этого сервис считается недоделанным.

Грабли

  • Дашборды с grafana.com приносят datasource плейсхолдером с произвольным именем (${DS_PROMETHEUS}, ${VAR_DATASOURCE}, ${DS__VICTORIAMETRICS-PROD-ALL}…). Не заменишь на uid нашего datasource fairflow-prom — дашборд молча рисует «No data» и красит переменные красным. Замена регуляркой \$\{(DS|VAR)[^}]*\} (регистронезависимо) — обязательный шаг.
  • Два ConfigMap'а под дашборды (core и full) не случайно: Node Exporter Full ~230 КБ, вдвоём с kube-state-metrics они почти упираются в лимит объекта 1 МБ.
  • Цель на машине не из подсети нод (как станция nubble) прописывается по tailnet-адресу, и проверять доступность надо из пода Prometheus, а не с хоста n1: kubectl --context n1 exec -n monitoring deploy/prometheus -- wget -q -O /dev/null -T 5 http://<ip>:9100/metrics
  • node-exporter на станции слушает только tailnet-IP (в домашнюю LAN метрики не светятся). Побочка: если docker стартует раньше tailscaled, контейнер падает на bind и перезапускается сам.
  • kustomize плодит ConfigMap'ы с новым хешем при каждом изменении; старые сами не удаляются — чистить, сверяясь с .spec.volumes[*].configMap.name живых подов.