В начале не было ничего. И создал DevOps кластер Kubernetes и сказал, что это есть хорошо. Но пришли злые программисты и начали требовать информацию о том, сколько ресурсов потребляют их контейнеры.

Привет, Хабр! Меня зовут Юра, я DevOps-инженер команды разработчиков платформы контейнеризации dBrain. В этой статье рассмотрим различия между статической и динамической конфигурацией в vmagent от Victoria Metrics (как мы собирали свой универсальный стек системы мониторинга, читайте здесь).

Если имеешь маленький кластер, то хочется схитрить и сделать его обслуживание быстрым и легким, но как говорится, всегда есть нюанс. Когда наши кластеры состояли всего из нескольких нод, конфигурация для сбора метрик была статической. Это казалось удобным и простым, но все рано или поздно приходится пересматривать.

Начнем с технической части. Стек Victoria Metrics в кластерной версии выглядит следующим образом: vmagent, vminsert, vmselect, vmstorage, vmalert, vmauth (опционально).

Конечно, найдутся те, кто спросит: “А как же vmgateway, vmrestore, vmbackup, vmmanager и прочие vm’ы”? Мы им ответим, что шекели не бесконечные и их нужно экономить.

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

  • vmagent - сбор, релейблинг и пересылка метрик;

  • vminsert - прием метрик (если хотите отказоустойчивость, то репликация и запись в базу);

  • vmselect - чтение из базы метрик;

  • vmstorage - база метрик;

  • vmalert - алертинг и рекординг (легальный способ сделать мультиретеншен, но об этом в следующих статьях);

  • vmauth - auth прокси.

Этого набора компонентов достаточно для покрытия уймы требований к стеку мониторинга. Осталось только заставить их работать сообща.

Статическая или динамическая конфигурация?

Сегодня разберем vmagent. Статическая конфигурация:

- job_name: foo
  static_configs:
  - targets: ["x.x.x.1:8429"]

Простейшая джоба для сбора метрик с vmagent с условным адресом x.x.x.1. Выглядит круто: три строки - и готово. Здесь я, конечно, согласен. А если у нас появится еще парочка vmagent’ов? Мы просто добавим их в конфигурацию. Допустим, появился vmagent-1 и vmagent-2.

- job_name: foo
  static_configs:
  - targets: ["x.x.x.1:8429", "x.x.x.2:8429", "x.x.x.3:8429"]

Что ж, ничего сложного пока нет. Идем дальше. С тремя vmagent’ами справились, но как быть с пользовательской нагрузкой?

Добавим джобу и для пользовательской нагрузки:

- job_name: client-1
  static_configs:
  - targets: ["x.x.x.y:8429"]
- job_name: client-2
  static_configs:
  - targets: ["x.x.x.z:8429"]
- job_name: foo
  static_configs:
  - targets: ["x.x.x.1:8429", "x.x.x.2:8429", "x.x.x.3:8429"]

Тоже кажется, что проблем нет. Подумаешь, пару секций, все же здорово, зачем нам хваленая динамическая конфигурация?

Тогда смоделируем более приближенную к реальной ситуацию. Например, нужно мониторить поды, которые при рестартах меняют свои ip, скажем, их будет 20. Что же делать в этой ситуации? Ответ один: переходить на динамическую конфигурацию - kubernetes_sd_config.

Статическая конфигурация хороша, когда целей немного и адреса не меняются. К плюсам статической конфигурации можно отнести простоту и удобство. Нужно добавить на тестовом окружении стороннюю точку сбора метрик, временный сервер для тестов, url на проверку? Добро пожаловать в статическую конфигурацию.

При настройке мониторинга внутри Kubernetes будем разбираться с динамической конфигурацией. Суть проста. Берем целевой ресурс (сервисы, поды, ноды или что-нибудь другое из доступных опций конфига) и фильтруем по заданным правилам. Выполняем несколько магических манипуляций с релейблингом, редактируем адреса - и готово: получаем только нужные нам для сбора цели.

Для разнообразия вставлю список vmagent динамических конфигураций:

  • azure_sd_configs is for scraping the targets registered in Azure Cloud. See these docs.

  • consul_sd_configs is for discovering and scraping targets registered in Consul. See these docs.

  • consulagent_sd_configs is for discovering and scraping targets registered in Consul Agent. See these docs.

  • digitalocean_sd_configs is for discovering and scraping targets registered in DigitalOcean. See these docs.

  • dns_sd_configs is for discovering and scraping targets from DNS records (SRV, A and AAAA). See these docs.

  • docker_sd_configs is for discovering and scraping Docker targets. See these docs.

  • dockerswarm_sd_configs is for discovering and scraping Docker Swarm targets. See these docs.

  • ec2_sd_configs is for discovering and scraping Amazon EC2 targets. See these docs.

  • eureka_sd_configs is for discovering and scraping targets registered in Netflix Eureka. See these docs.

  • file_sd_configs is for scraping targets defined in external files (aka file-based service discovery). See these docs.

  • gce_sd_configs is for discovering and scraping Google Compute Engine targets. See these docs.

  • http_sd_configs is for discovering and scraping targets provided by external http-based service discovery. See these docs.

  • kubernetes_sd_configs is for discovering and scraping Kubernetes targets. See these docs.

  • kuma_sd_configs is for discovering and scraping Kuma targets. See these docs.

  • nomad_sd_configs is for discovering and scraping targets registered in HashiCorp Nomad. See these docs.

  • openstack_sd_configs is for discovering and scraping OpenStack targets. See these docs.

  • static_configs is for scraping statically defined targets. See these docs.

  • yandexcloud_sd_configs is for discovering and scraping Yandex Cloud targets. See these docs.

Cntrl+C, Cntrl +V из официальной документации.

Вернемся к нашему старому примеру с vmagent, переведем статическую конфигурацию в динамическую.

Статическая конфигурация:

- job_name: foo
  static_configs:
  - targets: ["vmagent:8429"]

Динамическая:

- job_name: monitoring
  kubernetes_sd_configs:
  - role: pod
  relabel_configs:
  - source_labels: [ __meta_kubernetes_pod_annotation_monitoring_scrape ]
    action: keep
    regex: "true"

О чудо, проблема со скейлингом и плавающими адресами решена. Каждый под, который содержит аннотацию monitoring/scrape: true, будет помечен как цель для сбора.

Навешиваем аннотацию на все поды Victoria Metrics и радуемся жизни? Не так быстро.

Внимательные читатели уже видят проблему. Если мы пометим этой аннотацией все компоненты мониторинга, а не только vmagent, то возникнет проблема с портами и путями сбора метрик - где-то /metrics, где-то actuator/prometheus и т.д.

Давайте решать это как раз с помощью манипуляций над релейблингом. На этом стейдже мы можем не только фильтровать, но и править :) Добавим в наши аннотации два компонента - поле, содержащее порт, и путь сбора метрик.

Приведу сразу готовую конфигурацию, но отмечу, что есть много вариантов сделать такую джобу, вплоть до regex по имени сервиса из неймспейса мониторинга и сбор по endpoint’ам на порте, помеченном для мониторинга. У нас же просто конфиг для подов с аннотацией:

- job_name: monitoring
  kubernetes_sd_configs:
  - role: pod
  relabel_configs:
  - source_labels: [ __meta_kubernetes_pod_annotation_monitoring_scrape ]
    action: keep
    regex: "true"

  - source_labels: [__address__, __meta_kubernetes_pod_annotation_port]
    action: replace
    regex: ([^:]+)(?::\d+)?;(\d+)
    replacement: $1:$2
    target_label: __address__

  - source_labels: [__meta_kubernetes_pod_node_name]
    target_label: hostname

  - source_labels: [__meta_kubernetes_namespace]
    action: replace
    target_label: kubernetes_namespace

  - source_labels: [__meta_kubernetes_pod_name]
    action: replace
    target_label: kubernetes_pod_name

  - source_labels: [__meta_kubernetes_pod_annotation_metric_path]
    action: replace
    target_label: __metrics_path__
    regex: (.+)

Теперь разберем по частям что, куда и зачем.

- source_labels: [ __meta_kubernetes_pod_annotation_monitoring_scrape ]
    action: keep
    regex: "true"

Данную часть мы уже разобрали - это фильтр. Остаются только поды с аннотацией. Но где же мы решаем проблему с портами? Тут все просто, нужно немного магии. Следите за руками, как говорится :)

- source_labels: [__address__, __meta_kubernetes_pod_annotation_port]
    action: replace
    regex: ([^:]+)(?::\d+)?;(\d+)
    replacement: $1:$2
    target_label: __address__

Здесь есть внутренне поле __address__, которое как раз и отвечает за адрес:порт. При помощи нехитрой регулярки (или хитрой, если не знать регулярки) мы вытаскиваем из адреса непосредственно порт и заменяем его на тот, который был в аннотации пода.

Идем дальше.

- source_labels: [__meta_kubernetes_pod_node_name]
    target_label: hostname

  - source_labels: [__meta_kubernetes_namespace]
    action: replace
    target_label: kubernetes_namespace

  - source_labels: [__meta_kubernetes_pod_name]
    action: replace
    target_label: kubernetes_pod_name

Здесь из меты Kubernetes мы просто проставляем лейбл хостнейма, неймспейса и названия пода на метрику.

Потом тем же способом, что и с адресом, во внутреннюю переменную __metrics_path__ пишем то, что было в аннотации пути сбора.

- source_labels: [__meta_kubernetes_pod_annotation_metric_path]
    action: replace
    target_label: __metrics_path__
    regex: (.+)

Таким образом, с помощью одной джобы мы всегда будем собирать метрики с компонентов стека Victoria Metrics. При этом не важно поменялись ли адреса или стало больше или меньше реплик какого-нибудь сервиса. У нас всегда будет актуальная конфигурация.

Чем хороша динамическая конфигурация? Да просто это удобно, ведь сокращается количество действий для поддержания ее в актуальном состоянии и еще много прочих плюшек. А избавление от кейсов, когда разработчики что-то изменили, а тебе приходится руками менять пути, адреса, количество - всегда хорошо. Экономьте свое время и занимайтесь полезными вещами.

И небольшой бонус в конце - ссылка на сообщество Victoria Metrics. Здесь много интересного о системе мониторинга, а участники сообщества могут помочь решить вопрос по мониторингу просто так, за плюсик в карму.

Комментарии (0)