VictoriaMetrics

Конспект доки

Cluster VictoriaMetrics

Фишки

Обзор архитектуры

Кластер состоит из следующих сервисов:

Каждый сервис может скейлиться независимо от остальных
Стораджи не знают друг о друге и никак друг с другом не коммуницируют, это упрощает авэйлабилити, расширяемость и обслуживаемость

Селекты поддерживают promql и могут быть использованы как prometheus datasource в графане

Naive_cluster_scheme.png

Мультитенантность

Тенанты определяются с помощью accountID или accountID:projectID, которые находятся внутри запроса

Cluster setup

Минимальный кластер это

Соответственно вышеуказанные флаги являются обязательными

vmauth или какой-либо http-loadbalancer ставится перед vmselect/vminsert нодами
Настроить балансер можно основываясь на url-format

Переменные окружения

Каждый флаг может быть задан через перменные окружения

Monitoring

Каждый компонент отдает метрики в prometheus-совместимом формате на эндпоинте /metrics
Есть официальный и неофициальный дашборды для графаны
Алерты рекомендуется брать из этого конфига

Readonly mode

Стораджи автоматом переходят в ридонли режим когда в -storageDataPath остается мало места, а именно когда его меньше чем указано в -storage.minFreeDiskSpaceBytes
Инсерты в таком случае перестают слать данные в этот сторадж и шлют их в оставшиеся

URL format

Урл для вставки выглядит так - http://<vminsert>:8480/insert/<accountID>/<suffix>, где:

Урл для запросов выглядит так - http://<vmselect>:8481/select/<accountID>/prometheus/<suffix>, где:

Урл для Graphite Metrics API - http://<vmselect>:8481/select/<accountID>/graphite/<suffix>, где все не интересно:

Урл с простым Web UI - http://<vmselect>:8481/select/<accountID>/vmui/

Screenshot_2021_02_02-12_49_03-2022-08-18-at-vmui.png

Урл со статистикой по запросам сквозь все неймспейсы - http://<vmselect>:8481/api/v1/status/top_queries

Screenshot_2021_02_02-12_49_03-2022-08-18-at-1crossnsstat.png

Урл для удаления тайм серий - http://<vmselect>:8481/delete/<accountID>/prometheus/api/v1/admin/tsdb/delete_series?match[]=<timeseries_selector_for_delete>. Это нельзя делать на регулярной основе, чисто чтобы исправлять ошибки когда заинджестил что-то не то
Пример удаления

vandud@macbook: ~ [0] ? curl -s 'http://mon-vm-01.g01.i-free.ru:8481/select/1/prometheus/api/v1/query_range?query=node_load1\{instance="mon-vm-03.g01.i-free.ru:9100"\}&start=1659557812.652&end=1659559128.166' | jq
{
  "status": "success",
  "isPartial": false,
  "data": {
    "resultType": "matrix",
    "result": [
      {
        "metric": {
          "__name__": "node_load1",
          "instance": "mon-vm-03.g01.i-free.ru:9100",
          "job": "monitoring"
        },
        "values": [
          [
            1659557812.652,
            "0.06"
          ],
          [
            1659558112.652,
            "0.04"
          ],
          [
            1659558412.652,
            "0.2"
          ],
          [
            1659558712.652,
            "0.01"
          ],
          [
            1659559012.652,
            "0.06"
          ]
        ]
      }
    ]
  }
}

vandud@macbook: ~ [0] ? curl -s 'http://mon-vm-01.g01.i-free.ru:8481/delete/1/prometheus/api/v1/admin/tsdb/delete_series?match[]=node_load1\{instance="mon-vm-03.g01.i-free.ru:9100"\}'

vandud@macbook: ~ [0] ? curl -s 'http://mon-vm-01.g01.i-free.ru:8481/select/1/prometheus/api/v1/query_range?query=node_load1\{instance="mon-vm-03.g01.i-free.ru:9100"\}&start=1659557812.652&end=1659559128.166' | jq
{
  "status": "success",
  "isPartial": false,
  "data": {
    "resultType": "matrix",
    "result": []
  }
}

vmstorage предоставляет следующие HTTP эндпоинты на 8482 порту:

Cluster resizing and scalability

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

Подробнее тут https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#cluster-resizing-and-scalability

Updating / reconfiguring cluster nodes

vmselect, vminsert и vmstorage можно апдейтнуть плавно. Для этого надо засылать им SIGINT после замены бинаря (это же касает обновления конфига)

Cluster availability

vmselect не поддерживает частичные ответы на эндпоинтах которые отдают сырые данные (например /api/v1/export*) потому что обычно ожидается что там будут полные данные
Для пущей надежности можно настроить data replication

Capacity planning

VictoriaMetrics использует меньше ресурсов чем конкурирующие решения (Prometheus, Cortex, etc)
Кол-во потребляемых ресурсов зависит от от профиля нагрузки (сколько таймсерий, какой churn rate, какого типа запросы прилетают, количество запросов, etc)
Рекомендуется строить тестовый кластер на продовых нагрузках и отлаживать это все по ходу дела (все сервисы кластера предоставляют метрики)

Количество диска для указанного -retentionPeriod так же можно понять по тестовому кластеру (например если на тестовом стенде за день набралось 10Gb данных, то если мы захотим хранить 100 дней то 10 надо умножить на 100, получится 1Тб диска)

Рекомендуется оставить свободными 50% памяти и процессора чтобы кластер мог безопасно переживать всплески нагрузки
Так же рекомендуется иметь в запасе 20% диска

Советы:

Resource usage limits

По умолчания компоненты кластера настроены на оптимальную работу при типичных нагрузках. В некоторых случаях может потребоваться ограничение потребления некоторых ресурсов. Далее будут рассмотрены флаги для ограничения потребления ресурсов:

Multi-level cluster setup

Одни vmselect'ы могут обращаться к другим vmselect'ам если они запущены с флагом -clusternativeListenAddr, то же самое с vminsert'ом

Replication and data safety

По умолчанию victoriametrics полагается на надежность хранилища которое выбрано для хранения данных и прописано в -storageDataPath, но так же она поддерживает репликацию на уровне приложения
С помощью ключа -replicationFactor=N на vminsert'ах можно задать количество хранимых копий сэмплов (на разных стораджах). Это гарантирует что все сохраненные данные будут оставаться доступными для запросов если вплоть до N-1 vmstorage'й будет недоступно (ReplicationFactor - 1 = UnavailableNodes)
Кластер должен содержать как минимум 2*N-1 стораджей, где N - фактор репликации

Кластер хранит таймстемпы с миллисекундным разрешением, поэтому флаг -dedup.minScrapeInterval=1ms может быть добавлен на vmselect'ы для дедуплицирования сэмплов получаемых со стораджей

Но надо помнить что реплика это не бэкап, поэтому не забывай про бэкапы

Репликация увеличивает потребление ресурсов, потому что vminsert'у нужно клать две копии в два разных стораджа, а vmselect'у нужно дедуплицировать полученные данные
Для сокращения этих издержек можно передать репликацию на уровень ниже (на систему хранения предоставляющую диск для ВМ)

Deduplication

VictoriaMetrics выбирает сэмпл с наибольшим таймстемпом из сэмплов попадающих в интервал заданный в -dedup.minScrapeInterval. То есть из таймсерии на каждый такой интервал выпадает один сэмпл (если спорный момент когда одинаковый таймстемп у двух сэмплов то выбирается случайный)
Рекомендуется задавать -dedup.minScrapeInterval равным scrape_interval и scrape_interval рекомендуется иметь одинаковым на всех таргетах

Флаг -dedup.minScrapeInterval должен быть проставлен и на vmselect'ах и на vmstorage'ах потому что vmselect пытается лить одну метрику в один сторадж (в идеальных условиях все сэмплы определенной таймсерии будут лежать на одном сторадже), но это поведение может нарушиться если мы будем добавлять/убирать стораджи, если какой-то сторадж будет временно недоступен (зарестартится или произойдет какая-то авария) или на нужном сторадже кончится место, тогда vminsert выберет другой сторадж для этой метрики и часть сэмплов будет на одной ноде, часть на другой

Backups

Рекомендуется периодически делать бэкапы из снапшотов чтобы защититься от пользовательских ошибок таких как случайное удаление данных
Для создания бэкапа:

  1. Создай снапшот через API
    root@mon-vm-02:~# curl -s http://localhost:8482/snapshot/create | jq
    {
      "status": "ok",
      "snapshot": "20220821113230-170D3C49F5660E08"
    }
    
  2. Преврати снапшот в бэкап с помощью утилиты vmbackup
    root@mon-vm-02:~# ./vmbackup-prod -storageDataPath /var/lib/vmstorage-data/ -snapshotName 20220821113230-170D3C49F5660E08 -dst fs:///tmp/test-vm-backup
    
    Получается бэкап storageDataPath
    root@mon-vm-02:~# du -hs /tmp/test-vm-backup/
    67M     /tmp/test-vm-backup/
    root@mon-vm-02:~# du -hs /var/lib/vmstorage-data/
    68M     /var/lib/vmstorage-data/
    
  3. Удали снапшот
    root@mon-vm-02:~# ls /var/lib/vmstorage-data/snapshots/
    20220821113215-170D3C49F5660E07
    root@mon-vm-02:~# curl -s http://localhost:8482/snapshot/delete?snapshot=20220821113215-170D3C49F5660E07 | jq
    {
      "status": "ok"
    }
    root@mon-vm-02:~# ls /var/lib/vmstorage-data/snapshots/
    root@mon-vm-02:~#
    

Все три пункта можно сделать одной командой

# ./vmbackup-prod -storageDataPath /var/lib/vmstorage-data/ -snapshot.createURL http://localhost:8482/snapshot/create -dst fs:///tmp/test-vm-backup2

Процесс бэкапирования не влияет на производительность кластера, поэтому бэкапы можно делать в любое удобное время

Чтобы восстановить из бэкапа нужно:

  1. Остановить сторадж
  2. Восстановить vmrestore-prod -src fs:///tmp/test-vm-backup -storageDataPath /var/lib/vmstorage-data/
  3. Запустить сторадж

Profiling

Все компоненты кластера предоставляют хендлеры для профайлинга

root@mon-vm-02:~# wget http://localhost:8480/debug/pprof/profile
--2022-08-21 16:02:16--  http://localhost:8480/debug/pprof/profile
Resolving localhost (localhost)... ::1, 127.0.0.1
Connecting to localhost (localhost)|::1|:8480... failed: Connection refused.
Connecting to localhost (localhost)|127.0.0.1|:8480... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/octet-stream]
Saving to: ‘profile’

profile                                        [ <=>                                                                                     ]   3.83K  --.-KB/s    in 0s

2022-08-21 16:02:46 (24.4 MB/s) - ‘profile’ saved [3919]

Грузится достаточно долго, этого пугаться не стоит
Далее полученный файл формата pprof можно как-то анализировать
Например:

root@mon-vm-02:~# go tool pprof -http=172.27.247.182:8080 profile # profile это имя файла который мы получили выше

Screenshot_2021_02_02-12_49_03-2022-08-21-pprof.png

vmalert

vmselect'у можно указать флаг -vmalert.proxyURL и тогда он сможет проксировать некоторые запросы на vmalert
Это нужно для Grafana Alerting UI и можно увидеть интрерфейс vmalert'a через vmselect
Screenshot_2021_02_02-12_49_03-2022-08-21-at-17fin.png


Описание доступных флагов у сервисов можно увидеть в хелпе по сервису

vmauth

vmauth это простой auth-proxy, router, и load balancer для VictoriaMetrics
Он читает креды из http-заголовка Authorization (поддерживаются Basic Auth, Bearer token и InfluxDB auth), матчит их с данными из конфига из флага -auth.config и проксирует входящие запросы на указанные в конфиге per-user url_prefix
-auth.config может указывать на локальный файл или на http url

Quick start

Минимально достаточно запустить

/path/to/vmauth -auth.config=/path/to/auth/config.yml

vmauth повиснет на 8427 порту и будет роутить приходящие запросы на основе auth.conf
Порт может быть изменен флагом -httpListenAddr
Релоадить конфиг можно отправив процессу SIGHUP сигнал - kill -SIGHUP $MAINPID или сделав запрос на эндпоинт /-/reload
Docker имаджи доступны тут - https://hub.docker.com/r/victoriametrics/vmauth/tags

Load balancing

Каждый url_prefix в auth.config может содержать один урл или список урлов
Ниже видно, что можно сразу урл, а можно список урлов

users:
- bearer_token: "YYY"
  url_prefix: "http://localhost:8428"

- username: "cluster-select-account-123"
  password: "***"
  url_prefix:
  - "http://vmselect1:8481/select/123/prometheus"
  - "http://vmselect2:8481/select/123/prometheus"

В случае если указан список, vmauth будет балансить запросы между указанными урлами в режиме round-robin
Это полезно для балансинга нагрузки между несколькими vmselect/vminsert

Auth config

-auth.config описывается следующим образом:

# Может быть указано произвольное количество username'ов
# Допустимо указывать несколько одинаковых имен пользователей, но пароли у них должны быть разные
# Такие username'ы могут различаться опцией 'name'

users:
  # Запросы с заголовками 'Authorization: Bearer XXXX' и 'Authorization: Token XXXX' будут проксироваться на http://localhost:8428
  # Например, http://vmauth:8427/api/v1/query отправится на http://localhost:8428/api/v1/query
- bearer_token: "XXXX"
  url_prefix: "http://localhost:8428"

  # Запросы с заголовком 'Authorization: Bearer YYY' будут проксироваться на http://localhost:8428
  # И к каждому проксируемому запросу будет добавляться заголовок `X-Scope-OrgID: foobar` 
- bearer_token: "YYY"
  url_prefix: "http://localhost:8428"
  headers:
  - "X-Scope-OrgID: foobar"

  # Пример использования пользователя
  # Все запросы к http://vmauth:8427 с Basic Auth (username:password) будут проксироваться на http://localhost:8428
- username: "local-single-node"
  password: "***"
  url_prefix: "http://localhost:8428"

  # Пример использования пользователя с extra_label team=dev.
  # Все запросы к http://vmauth:8427 с Basic Auth (username:password) будут проксировать на http://localhost:8428 с аргументом запроса extra_label=team=dev
  # Например, запрос к http://vmauth:8427/api/v1/query отправится на http://localhost:8428/api/v1/query?extra_label=team=dev
- username: "local-single-node"
  password: "***"
  url_prefix: "http://localhost:8428?extra_label=team=dev"

  # Пример конфига с пользователем под неймспейс в VictoriaMetrics cluster
  # Все запросы к http://vmauth:8427 с Basic Auth (username:password) будут балансироваться между указанными vmselect с указанием конкретного неймспейса
- username: "cluster-select-account-123"
  password: "***"
  url_prefix:
  - "http://vmselect1:8481/select/123/prometheus"
  - "http://vmselect2:8481/select/123/prometheus"

  # Аналогичное тому что выше но с vminsert'ами
- username: "cluster-insert-account-42"
  password: "***"
  url_prefix:
  - "http://vminsert1:8480/insert/42/prometheus"
  - "http://vminsert2:8480/insert/42/prometheus"

  # Единый пользователь для селектов и инсертов:
  # - Запросы к http://vmauth:8427/api/v1/query, http://vmauth:8427/api/v1/query_range и http://vmauth:8427/api/v1/label/<label_name>/values
  # будут проксироваться на следующие урлы в режиме round-robin:
  #     - http://vmselect1:8481/select/42/prometheus
  #     - http://vmselect2:8481/select/42/prometheus
  # - Запросы к http://vmauth:8427/api/v1/write будут проксироваться на http://vminsert:8480/insert/42/prometheus/api/v1/write с заголовком "X-Scope-OrgID: abc"
- username: "foobar"
  url_map:
  - src_paths:
    - "/api/v1/query"
    - "/api/v1/query_range"
    - "/api/v1/label/[^/]+/values"
    url_prefix:
    - "http://vmselect1:8481/select/42/prometheus"
    - "http://vmselect2:8481/select/42/prometheus"
  - src_paths: ["/api/v1/write"]
    url_prefix: "http://vminsert:8480/insert/42/prometheus"
    headers:
    - "X-Scope-OrgID: abc"

Пример:

root@mon-vm-01:~# cat /etc/victoriametrics/vmauth.yaml
users:
- username: "test-user"
  password: "test-password"
  url_prefix: "http://localhost:8481"

Запускаем:

./vmauth-prod -eula -auth.config=/etc/victoriametrics/vmauth.yaml

Запрос без указания user/pass:

(ifree-test-k8s:default) vandud@macbook: ~ [0] ? curl 'http://mon-vm-01.g01.i-free.ru:8427/select/0/prometheus/api/v1/query_range?query=1&start=2022-08-31T02:20:00Z&end=2022-08-31T02:22:00Z&step=1m'
missing `Authorization` request header

Запрос с указанием user/pass:

(ifree-test-k8s:default) vandud@macbook: ~ [0] ? curl -s -u test-user:test-password 'http://mon-vm-01.g01.i-free.ru:8427/select/0/prometheus/api/v1/query_range?query=1&start=2022-08-31T02:20:00Z&end=2022-08-31T02:22:00Z&step=1m'  | jq
{
  "status": "success",
  "isPartial": false,
  "data": {
    "resultType": "matrix",
    "result": [
      {
        "metric": {},
        "values": [
          [
            1661912400,
            "1"
          ],
          [
            1661912460,
            "1"
          ],
          [
            1661912520,
            "1"
          ]
        ]
      }
    ]
  }
}

Этот конфиг может содержать плейсхолдеры вида %{ENV_VAR} в которые будут подставлены соответствующие переменные окружения. Это может быть полезно для подстановки секретов в конфиг

Security

Подразумевается что все сервисы расположены в приватной сети и доступны снаружи только сквозь vmauth
Нужно обязательно включать https, потому что иначе пропадает смысл аутентификации через Basic Auth
Флаги -tls* позволяют это сделать

Как альтернатива можно поставить tls termination proxy перед vmauth

Рекомендуется защитить следующие эндпоинты через authKeys:

Задаем пароль

/usr/local/bin/vmauth -reloadAuthKey reloadpassword -auth.config=/etc/vmauth/auth.yml

И дергаем эндпоинт с этим паролем

curl http://mon-vm-02.g01.i-free.ru:8427/-/reload?authKey=reloadpassword

Monitoring

vmauth предоставляет множество метрик в Prometheus exposition формате на эндпоинте /metrics
Среди них есть метрика vmauth_user_requests_total с лейблом username значение которого равно значению поля username из конфига

Пример:

? curl -s http://mon-vm-01.g01.i-free.ru:8427/metrics | grep vmauth_user_requests_total
vmauth_user_requests_total{username="test-user"} 2

Можно перекрыть username в лейбле с помощью опции name для username:

root@mon-vm-01:~# cat /etc/victoriametrics/vmauth.yaml
users:
- username: "test-user"
  name: "not-test-user"
  password: "test-password"
  url_prefix: "http://localhost:8481"
  
root@mon-vm-01:~# curl -s http://mon-vm-01.g01.i-free.ru:8427/metrics | grep vmauth_user_requests_total
vmauth_user_requests_total{username="not-test-user"} 0

Эта метрика обнуляется после рестарта

Prifiling

vmauth предоставляет хэндлеры для сбора Go профилей:

Команда для сбора CPU профиля сперва ждет 30 секунд и только потом возращает результат Собранные профили можно проанализировать утилитой https://github.com/google/pprof Файлы профилей не содержат сенсетивной информации поэтому их можно без страха шарить кому-то

Advanced usage

vmauth имеет еще массу различных флагов, актуальную справку по которым можно увидеть запустив vmauth -help

vmagent

vmagent это маленький но мощный агент который поможет тебе собирать метрики из разных источников и сохранять их в VictriaMetrics или каком-то другом Prometheus-compatible хранилище с поддержкой Prometheus remote_write протокола
vmagent.png

Motivation

vmagent появился потому что пока существовало роскошное хранилище метрик victoriametrics, пользователям также был необходим производительный и не требовательный к ресурсам сборщик метрик который бы складывал метрики в victoriametrics (вместо прожорливого prometheus'а)

Features

Quick Start

Скачай подходящий vmutils-* отсюда https://github.com/VictoriaMetrics/VictoriaMetrics/releases и вытащи оттуда бинарь vmagent'a

Базово запустить можно так

./vmagent-prod -remoteWrite.url http://localhost:8480/insert/0/prometheus/api/v1/write -promscrape.config /etc/victoriametrics/vmagent/config.yml

Если скрейпить не надо, то можно запустить вообще с одной опцией

./vmagent-prod -remoteWrite.url http://localhost:8480/insert/0/prometheus/api/v1/write

Тогда агент сможет инджестить в себя пушинговые протоклы и пересылать данные дальше в указанное хранилище

How to push data to vmagent

vmagent поддерживает те же push-based протоколы что и VictoriaMetrics

Configuration update

чтобы vmagent смог перечитать cli-флаги он должен быть рестартанут
vmagent имеет несколько способов перезагрузить конфиги из -promscrape.config, -remoteWrite.relabelConfig и -remoteWrite.urlRelabelConfig:

Есть флаг -promscrape.configCheckInterval который позволяет указать vmagent'у что нужно периодически проверять не изменился ли конфиг и подгружать если изменился

Multitenancy

По умолчанию vmagent собирает данные без каких-либо tennant id и просто отправляет их в -remoteWrite.url
Подержка мультитенантности включается когда проставлен флаг -remoteWrite.multitenantURL
Этим флагом задается адрес vmselect'а, куда vmagent будет засылать метрики полученные через push-протокол или собранные с таргетов из конфига
API для пушинга доступен у агента на http://vmagent:8429/insert/<accountID>/..., полученные данные он перенаправит в <-remoteWrite.multitenantURL>/insert/<accountID>/prometheus/api/v1/write
Флаг -remoteWrite.multitenantURL может быть указан несколько раз, тогда агент зареплицирует данные во все указанные remoteWrite хранилища

Чтобы агент скрейпил таргеты и клал собранные данные у нужные неймспейсы нужно чтобы у таргетов был лейбл __tenant_id__ в котором должен быть указан tenantID. Значение этого лейбла будет подставляться в <-remoteWrite.multitnenatURL>/insert/<__tenant_id__>/prometheus/api/v1/write и метрики будут попадать в нужный namespace

Пример
Вот такой конфиг:

---
global:
  scrape_interval: 1s
scrape_configs:
  - job_name: monitoring
    static_configs:
      - targets:
          - mon-vm-01.g01.i-free.ru:9100
        labels:
          __tenant_id__: 1
  - job_name: mon-test-vms
    static_configs:
      - targets:
          - mon-vm-02.g01.i-free.ru:9100
        labels:
          __tenant_id__: 2

Вот такая команда запуска:

vmagent-prod -promscrape.config /etc/victoriametrics/vmagent/config.yml -remoteWrite.multitenantURL http://localhost:8480

Получаем в каждом NS метрики по своему хосту:

vandud@macbook: ~ [0] ? curl -s http://mon-vm-03.g01.i-free.ru:8481/select/1/prometheus/api/v1/series?match[]=node_load1 | jq
{
  "status": "success",
  "isPartial": false,
  "data": [
    {
      "__name__": "node_load1",
      "job": "monitoring",
      "instance": "mon-vm-01.g01.i-free.ru:9100"
    }
  ]
}
vandud@macbook: ~ [0] ? curl -s http://mon-vm-03.g01.i-free.ru:8481/select/2/prometheus/api/v1/series?match[]=node_load1 | jq
{
  "status": "success",
  "isPartial": false,
  "data": [
    {
      "__name__": "node_load1",
      "job": "mon-test-vms",
      "instance": "mon-vm-02.g01.i-free.ru:9100"
    }
  ]
}

Если лейбла с tenantID нет, то данные кладутся в 0 неймспейс

How to collect metrics in Prometheus format

Файл из -promscrape.config читается не полностью, некоторые секции из него игнорируются
vmagent понимает только global и scrape_configs секции, а остальные игнорирует
Можно либо убрать лишние секции из конфига, либо добавить флаг -promscrape.config.strictParse=false который заставит vmagent'a их игнорировать

Пример запуска с невалидным конфигом

root@mon-vm-02:~# ./vmagent-prod -promscrape.config /etc/victoriametrics/vmagent/config.yml -remoteWrite.multitenantURL http://localhost:8480
2022-08-23T12:41:35.988Z        info    VictoriaMetrics/lib/logger/flag.go:12   build version: vmagent-20220808-173305-tags-v1.80.0-0-gad00f4aaa
2022-08-23T12:41:35.988Z        info    VictoriaMetrics/lib/logger/flag.go:13   command-line flags
2022-08-23T12:41:35.988Z        info    VictoriaMetrics/lib/logger/flag.go:20     -promscrape.config="/etc/victoriametrics/vmagent/config.yml"
2022-08-23T12:41:35.988Z        info    VictoriaMetrics/lib/logger/flag.go:20     -remoteWrite.multitenantURL="http://localhost:8480"
2022-08-23T12:41:35.988Z        info    VictoriaMetrics/app/vmagent/main.go:103 starting vmagent at ":8429"...
2022-08-23T12:41:35.988Z        info    VictoriaMetrics/app/vmagent/main.go:128 started vmagent in 0.000 seconds
2022-08-23T12:41:35.988Z        info    VictoriaMetrics/lib/httpserver/httpserver.go:94 starting http server at http://127.0.0.1:8429/
2022-08-23T12:41:35.988Z        info    VictoriaMetrics/lib/httpserver/httpserver.go:95 pprof handlers are exposed at http://127.0.0.1:8429/debug/pprof/
2022-08-23T12:41:35.989Z        info    VictoriaMetrics/lib/promscrape/scraper.go:106   reading Prometheus configs from "/etc/victoriametrics/vmagent/config.yml"
2022-08-23T12:41:35.991Z        fatal   VictoriaMetrics/lib/promscrape/scraper.go:109   cannot read "/etc/victoriametrics/vmagent/config.yml": cannot parse Prometheus config from "/etc/victoriametrics/vmagent/config.yml": cannot unmarshal data: yaml: unmarshal errors:
  line 17: field storage not found in type promscrape.Config; pass -promscrape.config.strictParse=false command-line flag for ignoring unknown fields in yaml config

Пример запуска с ключом -promscrape.config.strictParse=false

root@mon-vm-02:~# ./vmagent-prod -promscrape.config /etc/victoriametrics/vmagent/config.yml -remoteWrite.multitenantURL http://localhost:8480 -promscrape.config.strictParse=false                                                                                                                                                                  [9/973]
2022-08-23T12:42:23.991Z        info    VictoriaMetrics/lib/logger/flag.go:12   build version: vmagent-20220808-173305-tags-v1.80.0-0-gad00f4aaa
2022-08-23T12:42:23.991Z        info    VictoriaMetrics/lib/logger/flag.go:13   command-line flags
2022-08-23T12:42:23.991Z        info    VictoriaMetrics/lib/logger/flag.go:20     -promscrape.config="/etc/victoriametrics/vmagent/config.yml"
2022-08-23T12:42:23.991Z        info    VictoriaMetrics/lib/logger/flag.go:20     -promscrape.config.strictParse="false"
2022-08-23T12:42:23.991Z        info    VictoriaMetrics/lib/logger/flag.go:20     -remoteWrite.multitenantURL="http://localhost:8480"
2022-08-23T12:42:23.991Z        info    VictoriaMetrics/app/vmagent/main.go:103 starting vmagent at ":8429"...
2022-08-23T12:42:23.991Z        info    VictoriaMetrics/app/vmagent/main.go:128 started vmagent in 0.000 seconds
2022-08-23T12:42:23.991Z        info    VictoriaMetrics/lib/httpserver/httpserver.go:94 starting http server at http://127.0.0.1:8429/
2022-08-23T12:42:23.991Z        info    VictoriaMetrics/lib/httpserver/httpserver.go:95 pprof handlers are exposed at http://127.0.0.1:8429/debug/pprof/
2022-08-23T12:42:23.991Z        info    VictoriaMetrics/lib/promscrape/scraper.go:106   reading Prometheus configs from "/etc/victoriametrics/vmagent/config.yml"
2022-08-23T12:42:23.995Z        info    VictoriaMetrics/lib/promscrape/config.go:117    starting service discovery routines...
2022-08-23T12:42:23.995Z        info    VictoriaMetrics/lib/promscrape/config.go:123    started service discovery routines in 0.000 seconds
2022-08-23T12:42:23.997Z        info    VictoriaMetrics/lib/promscrape/scraper.go:403   static_configs: added targets: 2, removed targets: 0; total targets: 2
2022-08-23T12:42:24.699Z        info    VictoriaMetrics/lib/memory/memory.go:42 limiting caches to 5019416985 bytes, leaving 3346277991 bytes to the OS according to -memory.allowedPercent=60
2022-08-23T12:42:24.701Z        info    VictoriaMetrics/lib/persistentqueue/fastqueue.go:59     opened fast persistent queue at "vmagent-remotewrite-data/persistent-queue/1_5E2F0F84E74D5D64" with maxInmemoryBlocks=1200, it contains 0 pending bytes
2022-08-23T12:42:24.701Z        info    VictoriaMetrics/app/vmagent/remotewrite/client.go:169   initialized client for -remoteWrite.url="1:secret-url:2:0"
2022-08-23T12:42:24.724Z        info    VictoriaMetrics/lib/persistentqueue/fastqueue.go:59     opened fast persistent queue at "vmagent-remotewrite-data/persistent-queue/1_3B7269031AC653CF" with maxInmemoryBlocks=1200, it contains 0 pending bytes
2022-08-23T12:42:24.724Z        info    VictoriaMetrics/app/vmagent/remotewrite/client.go:169   initialized client for -remoteWrite.url="1:secret-url:1:0"

Важное отличие prometheus можно полностью сконфигурировать через конфиг, а vmagent'у в конфиге можно указать только таргеты которые нужно скрейпить, все остальное у vmagent'a конфигурируется либо через флаги либо через перменные окружения

Файл указанный в -promscrape.config может содержать %{ENV_VAR} плейсхолдеры в которые будут подставлены соответствующие переменные окружения

scrape_config enhancements

vmagent имеет дополнительные опции которые могут быть указаны в секции scrape_configs

Loading scrape configs from multiple files

vmagent умеет загружать scrape конфиги из множества файлов указанных в секции scrape_config_files файла указанного в -promscrape.config

root@mon-vm-01:/etc/victoriametrics/vmagent# cat config.yml
scrape_configs:
  - job_name: monitoring

    static_configs:
      - targets:
          - mon-vm-03.g01.i-free.ru:8008
        labels:
          __tenant_id__: 1
scrape_config_files:
  - scrape_config_files/test.yaml
root@mon-vm-01:/etc/victoriametrics/vmagent# cat scrape_config_files/test.yaml
- job_name: ns1
  static_configs:
    - targets:
      - mon-test-vm-03x.g01.i-free.ru:9100
- job_name: ns2
  static_configs:
    - targets:
      - mon-test-vm-03x.g01.i-free.ru:9100

Screenshot_2021_02_02-12_49_03-2022-08-29-at-02targets.png

Можно задавать файлы разными способами:

scrape_config_files:
- configs/*.yml
- single_scrape_config.yml
- https://config-server/scrape_config.yml # даже  так

Каждый файл из этого списка должен содержать валидные скрейп конфиги (static_configs, *_sd_configs, etc)
Эти файлы могут релоадиться без рестарта

Unsupported Prometheus config sections

vmagent не поддерживает следующие секции из -promscrape.config файла (которые поддерживает пром):

Список поддерживаемых SD https://docs.victoriametrics.com/sd_configs.html
Также не поддерживается refresh_interval для service_discovery, эта опция заменяется флагами -promscrape.*CheckInterval

Adding labels to metrics

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

Как я понял -remoteWrite.label работает для метрик которые получены агентом через push протоколы и которые он дальше запушит в хранилку. То есть в случае когда агент работает вообще без конфига как гейтвей для пушинга

Automatically generated metrics

vmagent автоматически генерирует следующие метрики для каждого таргета:

Relabeling

Поддерживается Premetheus-compatible релейблинг и ряд дополнений к нему. Релейблинг может быть определен в следующих местах:

https://relabeler.promlabs.com/ поможет отдебажить правила релейблинга

Relabeling enhancements

VictoriaMetrics имеет дополнительные действия для релейблинга поверх стандартных прометеусовских:

The regex value can be split into multiple lines for improved readability and maintainability. These lines are automatically joined with | char when parsed. For example, the following configs are equivalent:

- action: keep_metrics
  regex: "metric_a|metric_b|foo_.+"
- action: keep_metrics
  regex:
  - "metric_a"
  - "metric_b"
  - "foo_.+"

VictoriaMetrics components support an optional if filter in relabeling configs, which can be used for conditional relabeling. The if filter may contain arbitrary time series selector. For example, the following relabeling rule drops metrics, which don't match foo{bar="baz"} series selector, while leaving the rest of metrics:

- action: keep
  if: 'foo{bar="baz"}'

This is equivalent to less clear Prometheus-compatible relabeling rule:

- action: keep
  source_labels: [__name__, bar]
  regex: 'foo;baz'

Graphite relabeling

Не интересно

Prometheus staleness markers

Про staleness маркеры - https://www.robustperception.io/staleness-and-promql/ (я не особо понял)

vmagent засылает staleness маркеры в -remoteWrite.url в следующих случаях:

Для работы маркеров требуется дополнительная память, потому что нужно хранить предыдущий response body для каждого таргета, чтобы сравнивать его с текущим response body. Потребление памяти можно уменить выключив этот функционал флагом -promscrape.noStaleMarkers (он выключает staleness tracking), также этот флаг выключает сервисную метрику scrape_series_added

Stream parsing mode

По умолчанию vmagent сперва записывает весь response body в память, потом парсит его, потом применяет релейблинг и пушит в в -remoteWrite.url. Этот режим работает хорошо в большинстве случаев когда таргет экспозит небольшое количество метрик (меньше 10к). Но этот режим может требовать много памяти когда таргеты экспозят огромное количество метрик. В таких случаях рекомендуется включать stream parsing mode. Когда включен этот режим, vmagent читает response body чанками, немедленно процессит каждый чанк и пушит полученные метрики в remote storage. Это позволяет сохранить потребление памяти когда таргеты экспозят миллионы метрик

Stream parsing mode включается автоматически для таргетов, размер ответа которых превышает значение флага -promscrape.minResponseSizeForStreamParse
Этот режим может быть включен явно в следующих местах:

Опции sample_limit и series_limit не могут быть использованы одновременно с stream parsing mode потому что пропаршенные данные пушатся в сторадж сразу

Scraping big number of targets

Один vmagent может скрейпить десятки тысяч таргетов. Иногда этого может быть недостаточно из-за разных ограничений по ресурсам. В таком случае таргеты можно пошарить между несколькими инстансами vmagent'a (горизонтальное масштабирование). Все vmagent'ы в кластере должны иметь идентичные -promscrape.config с ясным значением флага -promscrape.cluster.memberNum. Значение этого флага должно быть в диапазоне от 0 до N-1, где N это количество vmagent'ов в кластере. Количество vmagent'ов нужно указать в флаге -promscrape.cluster.memberCount
Например следующие две команды поднимут кластер vmagent'ов из двух инстансов и нагрузка будет разделена между ними:

/path/to/vmagent -promscrape.cluster.membersCount=2 -promscrape.cluster.memberNum=0 -promscrape.config=/path/to/config.yml ...
/path/to/vmagent -promscrape.cluster.membersCount=2 -promscrape.cluster.memberNum=1 -promscrape.config=/path/to/config.yml ...

По умолчанию каждый таргет скрейпится только одним vmagent'ом из кластера. Если нужна репликация таргетов между агентами, то нужно проставить флаг -promscrape.cluster.replicationFactor с значением желаемого количества реплик
Например следующие три команды поднимут кластер vmagent'ов из трех нод с фактором репликации - 2. То есть каждый таргет будет скрейпиться какими-то двумя vmagent'ами:

/path/to/vmagent -promscrape.cluster.membersCount=3 -promscrape.cluster.replicationFactor=2 -promscrape.cluster.memberNum=0 -promscrape.config=/path/to/config.yml ...
/path/to/vmagent -promscrape.cluster.membersCount=3 -promscrape.cluster.replicationFactor=2 -promscrape.cluster.memberNum=1 -promscrape.config=/path/to/config.yml ...
/path/to/vmagent -promscrape.cluster.membersCount=3 -promscrape.cluster.replicationFactor=2 -promscrape.cluster.memberNum=2 -promscrape.config=/path/to/config.yml ...

В случае с репликацией нужно включать data deduplication на сторадже указанном в -remoteWrite.url. Флаг -dedup.minScrapeInterval должен быть выставлен в scrape_interval указанный в -promscrape.config

High availability

Для этого можно запустить несколько агентов которые будут скрейпить одинаковые таргеты и пушить в один и тот же сторадж, но нужно чтобы была настроена дедупликация на сторадже
Также рекомендуется указывать разные значения в флагах -promscrape.cluster.name на агентах для более качественной дедупликации

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

Scraping targets via a proxy

https://docs.victoriametrics.com/vmagent.html#scraping-targets-via-a-proxy
vmagent может скрейпить таргеты сквозь прокси (http, https, socks5). Адрес прокси задается опцией proxy_url в секции scrape_configs:

scrape_configs:
- job_name: foo
  proxy_url: https://proxy-addr:1234

Работу через прокси можно законфигурировать следующими опциями:

Cardinality limiter

По умолчанию vmagent не ограничивает количество таймсерий которые могут быть потреблены с каждого таргета. Это ограничение может быть задано в следующих местах:

Так же может быть полезной опция sample_limit в секции scrape_config

Метрики сверх лимита будут дропаться

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

Эти сервисные метрики засылаются в -remoteWrite.url вместе с обычными метриками

Эти метрики позволяют настроить следующие алертинги:


По умолчанию vmagent не ограничивает количество таймсерий которые отправляются в хранилище указанное в -remoteWrite.url. Этот лимит может быть проставлен следующими флагами:

Оба лимита могут быть выставлены одновременно. Если любой из этих лимитов достигнут, тогда сэмплы для новых таймсерий будут дропаться и в лог будут писаться сообщения с уровнем WARNING

vmagent экспозит следующие метрики на http://vmagent:8429/metrics:

Эти лимиты примерны, обычно расходятся меньше чем на один процент

Monitoring

vmagent экспортирует разные метрики на эндпоинте http://vmagent-host:8429/metrics
Рекомендуется их регулярно скрейпить потому что их анализ в будущем может принести пользу
Есть официальный дашборд для графаны https://grafana.com/grafana/dashboards/12683-vmagent/

vmagent также экспортирует статус для разных таргетов на следующих хэндлерах:

Troubleshooting

Kafka integration

Пока не интересно
Подробности тут

How to build from sources

Пока не интересно
Подробности тут

Profiling

vmagent предоставляет хэндлеры для сбора Go профилей:

Команда для сбора CPU профиля сперва ждет 30 секунд и только потом возращает результат
Собранные профили можно проанализировать утилитой https://github.com/google/pprof
Файлы профилей не содержат сенсетивной информации поэтому их можно без страха шарить кому-то

Advanced usage

vmagent имеет еще массу различных флагов, актуальную справку по которым можно увидеть запустив vmagent -help

vmalert

vmalert выполняет список переданных ему alerting и recording rules в указанном в флаге -datasource.url датасорсе который должен быть совместим с Prometheus HTTP API
Для доставки алертов он полагается на Alertmanager путь до которого должен быть прописан в флаге -notifier.url
Результаты работы recording rules vmalert запишет через remote write протокол в указанный -remoteWrite.url
vmalert сильно вдохновлен Prometheus'ом и ставит перед собой цель быть совместимым с его синтаксисом

Features

Limitations

vmalert делает запросы в удаленный datasource, поэтому возможны сетевые проблемы, нужно это учитывать при составлении правил (нужны thresholds)

По умолчанию выполнение правил выполняется последовательно в пределах одной группы, но сохранение результатов выполнения в удаленном хранилище является асинхронным. Следовательно, пользователь не должен полагаться на цепочку правил записи, когда результат предыдущего правила записи повторно используется в следующем;

QuickStart

Чтобы начать использовать vmalert нужно:

Пример конфигурации vmalert'a:

./bin/vmalert -rule=alert.rules \            # Path to the file with rules configuration. Supports wildcard
    -datasource.url=http://localhost:8428 \  # Prometheus HTTP API compatible datasource
    -notifier.url=http://localhost:9093 \    # AlertManager URL (required if alerting rules are used)
    -notifier.url=http://127.0.0.1:9093 \    # AlertManager replica URL
    -remoteWrite.url=http://localhost:8428 \ # Remote write compatible storage to persist rules and alerts state info (required if recording rules are used)
    -remoteRead.url=http://localhost:8428 \  # Prometheus HTTP API compatible datasource to restore alerts state from
    -external.label=cluster=east-1 \         # External label to be applied for each rule
    -external.label=replica=a                # Multiple external labels may be set

Нужно отметить что раздельные -remoteWrite.url и -remoteRead.url позволяют использовать vmalert как транспортера данных между горячим, быстрым хранилищем и холодным, долгим (short-term -> long-term) (имеются ввиду record rules)

Если ты запускаешь несколько инстансов vmalert'a и все они подключаются к одному хранилищу и Alertmanager'у, то будет полезным настроить на них различающиеся лейблы, чтобы было понятно кто из них сгенерил алерт

Конфигурация для recording и alerting rules очень похожа на Prometheus rules, каждый rule пренадлежит какой-то group и каждый конфиг может содержать различное количество групп:

groups:
  [ - <rule_group>]

Groups

Каждая группа имеет слудующие аттрибуты:

# Имя группы, должно быть уникальным в рамках файла
name: <string>

# Как часто рулы из этой группы должны выполняться
[ interval: <duration> | default = -evaluationInterval flag ]

# Ограничение на количество алертов и таймсерий которые может породить этот рул. 0 - лимита нет
[ limit: <int> | default = 0 ]

# Как много правил будет выполнено за раз в рамках группы. Увеличение параллельности может скорить выполнение правил
[ concurrency: <integer> | default = 1 ]

# Опциональный тип выражения внутри рула. Значением может быть 'graphite' и 'prometheus', второй дефолтный
[ type: <string> ]

# Опциональные дополнительные HTTP URL параметры применяемые для всех запросов к хранилке в рамках выполнения рулов группы
# Например:
#  params:
#    nocache: ["1"]                # disable caching for vmselect
#    denyPartialResponse: ["true"] # fail if one or more vmstorage nodes returned an error
#    extra_label: ["env=dev"]      # apply additional label filter "env=dev" for all requests 
# see more details at https://docs.victoriametrics.com#prometheus-querying-api-enhancements
params:
  [ <string>: [<string>, ...]]

# Опциональные HTTP хедеры в формате `header-name: value` добавляемые ко всем запросам к хранилке в рамках выполнения рулов группы
# Например:
#  headers:
#    - "CustomHeader: foo"
#    - "CustomHeader2: bar"
# Заголовки выставленные таким образом имеет приоритет выше чем заголовки добавленные через флаг `-datasource.headers`
headers:
  [ <string>, ...]

# Опциональный список лейблов добавляемых каждому рулу в группе
# Эти лейблы имеют приоритет выше чем external labels
labels:
  [ <labelname>: <labelvalue> ... ]

rules:
  [ - <rule> ... ]

Rules

Каждое правило содержит поле expr с PromQL/MetricsQL выражением. vmalert выполняет это выражение и дальше действует в зависимости от типа правила
Есть два типа правил:

vmalert не разрешает наличие дубликатов - рулов с одинаковой комбинацией имени, выражения и лейблов в рамках одной группы

Alerting rules

Синтаксис алерт рулов следующий:

# Имя алерта, должно проходить правила валидации имен метрик
alert: <string>

# Выражение. Язык выражения зависит от значения в поле `type` группы
expr: <string>

# Алерт считается "горящим" после того как в течение этого времени (из поля for) его expr возвращал не пустоту
# Алерт который срабатыват в течение времени меньшего чем for находится в состоянии pending
# Если этот параметр отсутсвует или проставлен в 0, то алерт будет срабатывать сразу
[ for: <duration> | default = 0s ]

# Лейблы для добавления или оверрайдинга под каждый алерт
labels:
  [ <labelname>: <tmpl_string> ]

# Аннотации под каждый алерт
annotations:
  [ <labelname>: <tmpl_string> ]
Templating

Разрешено использовать Go templating в аннотациях для форматирования данных, перебора или выполнения выражений. Следующие переменные доступны к использованию в темплейтинге:

Variable Description Example
$value или .Value Текущее значение алерта Number of connections is {{ $value }}
$activeAt или .ActiveAt Момент времени когда алерт стал активным (pending или firing) http://vm-grafana.com/panelId=xx?from={{($activeAt.Add (parseDurationTime "1h")).Unix}}&to={{($activeAt.Add (parseDurationTime "-1h")).Unix}}
$labels или .Labels Список лейблов алерта Too high number of connections for {{ .Labels.instance }}
$alertID или .AlertID alert's ID сгенерированный vmalert'ом Link: vmalert/alert?group_id={{.GroupID}}&alert_id={{.AlertID}}
$groupID или .GroupID alert's group ID сгенерированный vmalert'ом Link: vmalert/alert?group_id={{.GroupID}}&alert_id={{.AlertID}}
$expr или .Expr Выражение алерта. Может быть использована для генерации ссылки на график в графане или для чего-то еще /api/v1/query?query={{ $expr
$externalLabels или .ExternalLabels Список лейблов настроенных через флаг -external.label Issues with {{ $labels.instance }} (datacenter-{{ $externalLabels.dc }})
$externalURL или .ExternalURL URL настроенный через флаг -external.url, используется когда vmalert спрятан за проксей Visit {{ $externalURL }} for more details
Reusable templates

Как и в прометеусе, в vmalert'e есть reusable templates
Для их использования нужно описать темплейт в файле и подключить файл через флаг -rule.templates
Например есть описанный темплейт с именем grafana.filter:

{{ define "grafana.filter" -}}
  {{- $labels := .arg0 -}}
  {{- range $name, $label := . -}}
    {{- if (ne $name "arg0") -}}
      {{- ( or (index $labels $label) "All" ) | printf "&var-%s=%s" $label -}}
    {{- end -}}
  {{- end -}}
{{- end -}}

И он может быть использован в аннотации следующим образом:

groups:
  - name: AlertGroupName
    rules:
      - alert: AlertName
        expr: any_metric > 100
        for: 30s
        labels:
          alertname: 'Any metric is too high'
          severity: 'warning'
        annotations:
          dashboard: '{{ $externalURL }}/d/dashboard?orgId=1{{ template "grafana.filter" (args .CommonLabels "account_id" "any_label") }}'

Флаг -rule.templates поддерживает вайлдкарды чтобы подсасывать сразу много файлов. Контент темплейт-файлов может быть зарелоажен на лету

Recording rules

Синтаксис recording rules следующий:

# Имя алерта, должно проходить правила валидации имен метрик
record: <string>

# Выражение. Язык выражения зависит от значения в поле `type` группы
expr: <string>

# Лейблы для добавления или оверрайдинга которые будут добавлены до сохранения результата
labels:
  [ <labelname>: <labelvalue> ]

Чтобы рекординг рулы работали нужно чтобы присутствовал флаг -remoteWrite.url

Alerts state on restarts

vmalert не имеет локального хранилища, поэтому состояния алертов хранятся в опертивной памяти. Следовательно после рестарта vmalert'a стейты алертов будут потеряны. Чтобы этого избежать нужно чтобы vmalert был сконфигурирован со следующими флагами:

Оба флага нужны для нормального хранения состояний алертов. Процесс восстановления может фейлиться если таймсерии нет в указанном -remoteRead.url или если она не обновлялась за последний час (контролируется флагом remoteRead.lookback) или если полученный стейт не матчится с текущей конфигурацией vmalert'a

Multitenancy

Есть следующие варинты для алертинга и рекординга при мультитенантном сетапе:

Когда установлен флаг -clusterMode, флаги -datasource.url, -remoteRead.url и -remoteWrite.url должны содержать просто хостнейм и порт, часть урла с тенантом (например /select/123/prometheus) будет добавлена vmalert'ом автоматически на основе тенанта из конфига

Пример запуска:

root@mon-vm-01:~# ./vmalert-prod -rule=/etc/victoriametrics/vmalert/rules.yml -datasource.url=http://mon-vm-01.g01.i-free.ru:8481 -notifier.url=http://mon-vm-01.g01.i-free.ru:9093 -clusterMode -eula
Copyright 2018-2022 VictoriaMetrics, Inc - All Rights Reserved.
For any questions please contact info@victoriametrics.com
2022-08-30T15:55:25.798Z        info    VictoriaMetrics/lib/logger/flag.go:12   build version: vmalert-20220808-174744-tags-v1.80.0-enterprise-0-gccf72e410
2022-08-30T15:55:25.798Z        info    VictoriaMetrics/lib/logger/flag.go:13   command-line flags
2022-08-30T15:55:25.798Z        info    VictoriaMetrics/lib/logger/flag.go:20     -clusterMode="true"
2022-08-30T15:55:25.798Z        info    VictoriaMetrics/lib/logger/flag.go:20     -datasource.url="http://mon-vm-01.g01.i-free.ru:8481"
2022-08-30T15:55:25.798Z        info    VictoriaMetrics/lib/logger/flag.go:20     -eula="true"
2022-08-30T15:55:25.798Z        info    VictoriaMetrics/lib/logger/flag.go:20     -notifier.url="http://mon-vm-01.g01.i-free.ru:9093"
2022-08-30T15:55:25.798Z        info    VictoriaMetrics/lib/logger/flag.go:20     -rule="/etc/victoriametrics/vmalert/rules.yml"
2022-08-30T15:55:25.799Z        info    VictoriaMetrics/app/vmalert/main.go:149 reading rules configuration file from "/etc/victoriametrics/vmalert/rules.yml"
2022-08-30T15:55:25.800Z        info    VictoriaMetrics/lib/httpserver/httpserver.go:94 starting http server at http://127.0.0.1:8880/
2022-08-30T15:55:25.800Z        info    VictoriaMetrics/lib/httpserver/httpserver.go:95 pprof handlers are exposed at http://127.0.0.1:8880/debug/pprof/
2022-08-30T15:56:11.271Z        info    VictoriaMetrics/app/vmalert/group.go:304        group "alert.rules" started; interval=1m0s; concurrency=1
2022-08-30T15:57:11.280Z        error   VictoriaMetrics/app/vmalert/group.go:321        group "alert.rules": rule "Node_State": failed to execute: failed to execute query "up == 0": error getting response from http://mon-vm-01.g01.i-free.ru:8481/select/1/prometheus/api/v1/query?query=up+%3D%3D+0&step=60s&time=1661875020: Post "http://mon-vm-01.g01.i-free.ru:8481/select/1/prometheus/api/v1/query?query=up+%3D%3D+0&step=60s&time=1661875020": EOF

Если в конфиге не указан тенант, то будет использоваться тенант из флага -defaultTenant.prometheus или -defaultTenant.graphite (в зависимости от поля type группы)
Если тенант не указан в конфиге и не указан флагом то будет ошибка:

root@mon-vm-01:~# ./vmalert-prod -rule=/etc/victoriametrics/vmalert/rules.yml -datasource.url=http://mon-vm-01.g01.i-free.ru:8481 -notifier.url=http://mon-vm-01.g01.i-free.ru:9093 -clusterMode -eula
Copyright 2018-2022 VictoriaMetrics, Inc - All Rights Reserved.
For any questions please contact info@victoriametrics.com
2022-08-30T16:19:33.935Z        info    VictoriaMetrics/lib/logger/flag.go:12   build version: vmalert-20220808-174744-tags-v1.80.0-enterprise-0-gccf72e410
2022-08-30T16:19:33.936Z        info    VictoriaMetrics/lib/logger/flag.go:13   command-line flags
2022-08-30T16:19:33.936Z        info    VictoriaMetrics/lib/logger/flag.go:20     -clusterMode="true"
2022-08-30T16:19:33.936Z        info    VictoriaMetrics/lib/logger/flag.go:20     -datasource.url="http://mon-vm-01.g01.i-free.ru:8481"
2022-08-30T16:19:33.936Z        info    VictoriaMetrics/lib/logger/flag.go:20     -eula="true"
2022-08-30T16:19:33.936Z        info    VictoriaMetrics/lib/logger/flag.go:20     -notifier.url="http://mon-vm-01.g01.i-free.ru:9093"
2022-08-30T16:19:33.936Z        info    VictoriaMetrics/lib/logger/flag.go:20     -rule="/etc/victoriametrics/vmalert/rules.yml"
2022-08-30T16:19:33.936Z        info    VictoriaMetrics/app/vmalert/main.go:149 reading rules configuration file from "/etc/victoriametrics/vmalert/rules.yml"
2022-08-30T16:19:33.937Z        fatal   VictoriaMetrics/app/vmalert/main.go:152 cannot parse configuration file: errors(1): invalid group "alert.rules" in file "/etc/victoriametrics/vmalert/rules.yml": group "alert.rules" must contain `tenant` section if `-clusterMode` enabled
root@mon-vm-01:~#

Указываем флаг с дефолтным тенантом и все работает:

root@mon-vm-01:~# ./vmalert-prod -rule=/etc/victoriametrics/vmalert/rules.yml -datasource.url=http://mon-vm-01.g01.i-free.ru:8481 -notifier.url=http://mon-vm-01.g01.i-free.ru:9093 -clusterMode -eula -defaultTenant.prometheus=1
Copyright 2018-2022 VictoriaMetrics, Inc - All Rights Reserved.
For any questions please contact info@victoriametrics.com
2022-08-30T16:20:33.848Z        info    VictoriaMetrics/lib/logger/flag.go:12   build version: vmalert-20220808-174744-tags-v1.80.0-enterprise-0-gccf72e410
2022-08-30T16:20:33.848Z        info    VictoriaMetrics/lib/logger/flag.go:13   command-line flags
2022-08-30T16:20:33.848Z        info    VictoriaMetrics/lib/logger/flag.go:20     -clusterMode="true"
2022-08-30T16:20:33.848Z        info    VictoriaMetrics/lib/logger/flag.go:20     -datasource.url="http://mon-vm-01.g01.i-free.ru:8481"
2022-08-30T16:20:33.848Z        info    VictoriaMetrics/lib/logger/flag.go:20     -defaultTenant.prometheus="1"
2022-08-30T16:20:33.848Z        info    VictoriaMetrics/lib/logger/flag.go:20     -eula="true"
2022-08-30T16:20:33.848Z        info    VictoriaMetrics/lib/logger/flag.go:20     -notifier.url="http://mon-vm-01.g01.i-free.ru:9093"
2022-08-30T16:20:33.848Z        info    VictoriaMetrics/lib/logger/flag.go:20     -rule="/etc/victoriametrics/vmalert/rules.yml"
2022-08-30T16:20:33.849Z        info    VictoriaMetrics/app/vmalert/main.go:149 reading rules configuration file from "/etc/victoriametrics/vmalert/rules.yml"
2022-08-30T16:20:33.850Z        info    VictoriaMetrics/lib/httpserver/httpserver.go:94 starting http server at http://127.0.0.1:8880/
2022-08-30T16:20:33.850Z        info    VictoriaMetrics/lib/httpserver/httpserver.go:95 pprof handlers are exposed at http://127.0.0.1:8880/debug/pprof/

Topology examples

Следующие секции показывают как может быть использован vmalert в различных сценариях
Отметим что не все флаги из примеров обязательны:

Single-node VictoriaMetrics

Простейшая конфигурация когда используется одна нода VictoriaMetrics и как datasource, и как хранилище стейтов алертов:

./bin/vmalert -rule=rules.yml  \                    # Path to the file with rules configuration. Supports wildcard
    -datasource.url=http://victoriametrics:8428 \   # VM-single addr for executing rules expressions
    -remoteWrite.url=http://victoriametrics:8428 \  # VM-single addr to persist alerts state and recording rules results
    -remoteRead.url=http://victoriametrics:8428 \   # VM-single addr for restoring alerts state after restart
    -notifier.url=http://alertmanager:9093          # AlertManager addr to send alerts when they trigger

vmalert_single.png

Cluster VictoriaMetrics

В кластерной версии VictoriaMetrics имеет выделенные компоненты для записи и чтения данных: vminsert и vmselect
vmselect используется для получения данных из хранилища для выполнения рулов
vminsert используется для сохранения результатов работы recording rules и для сохранения стейтов алертов

Пример конфигурации:

./bin/vmalert -rule=rules.yml  \                                # Path to the file with rules configuration. Supports wildcard
    -datasource.url=http://vmselect:8481/select/0/prometheus    # vmselect addr for executing rules expressions
    -remoteWrite.url=http://vminsert:8480/insert/0/prometheus   # vminsert addr to persist alerts state and recording rules results
    -remoteRead.url=http://vmselect:8481/select/0/prometheus    # vmselect addr for restoring alerts state after restart
    -notifier.url=http://alertmanager:9093                      # AlertManager addr to send alerts when they trigger

vmalert_cluster.png

vminsert'ов и vmselect'ов может быть много
Если ты хочешь распределить нагрузку на эти компоненты то добавь балансер и указывай vmalert'у адрес балансера

HA vmalert

Для High Availability можно поднять несколько идентичных vmalert'ов которые будут выполнять одинаковые рулы в одном и том же datasource, складывать результаты их работы в одно и то же хранилище и слать алерты в одни и те же alertmanager'ы
Пример конфигурации:

./bin/vmalert -rule=rules.yml \                   # Path to the file with rules configuration. Supports wildcard
    -datasource.url=http://victoriametrics:8428 \   # VM-single addr for executing rules expressions
    -remoteWrite.url=http://victoriametrics:8428 \  # VM-single addr to persist alerts state and recording rules results
    -remoteRead.url=http://victoriametrics:8428 \   # VM-single addr for restoring alerts state after restart
    -notifier.url=http://alertmanager1:9093 \       # Multiple AlertManager addresses to send alerts when they trigger
    -notifier.url=http://alertmanagerN:9093         # The same alert will be sent to all configured notifiers

vmalert_ha.png

Чтобы избежать дублирования результатов работы recording rules нужно просто настроить дедупликацию на сторадже
Рекомендуется использовать значение для флага -dedup.minScrapeInterval большее или равное значению evaluation_interval у vmalert'a

Если есть неконсистентные или "прыгающие" значения у таймсерий сгенеренных vmalert'ом, то можно выключить -datasource.queryTimeAlignment
Из-за выравнивания в HA сетапе (когда более одного vmalert'a обрабатывают recording rules) несколько vmalert'ов будут генерить таймсерии с одинаковыми таймстемпами, но из-за бэкфиллинга (backfilling) значения могут отличаться, это зааффектит логику дедупликации и датапоинты могут "прыгать"

Alertmanager автоматически дедуплицирует алерты с одинаковыми лейблами (поэтому нужно чтобы все vmalert'ы имели идентичные конфиги)

Не забудьте настроить cluster mode для Alertmanager'а для большей доступности

Downsampling and aggregation via vmalert

vmalert не может модифицировать уже существующие данные. Но он может запускать recording rules и записывать результат в -remoteWrite.url, это позволяет аггрегировать данные. Например следующее правило будет подсчитывать среднее значение метрикиhttp_requests на 5 минутном интервале:

- record: http_requests:avg5m   
    expr: avg_over_time(http_requests[5m])

Каждый раз когда это правило будет выполняться, vmalert будет записывать результат его работы как новую таймсерии с именем http_requests:avg5m в указанный -remoteWrite.url

vmalert запускает правила с периодичностью указанной в -evaluationInterval или в параметре interval указанном для группы
Интервал позволяет контролировать разрешение произведенных таймсерий (чем чаще выполняется тем четче получается)
Возможность задавать интервал позволяет даунсемлить метрики, например следующее правило будет выполяться раз в пять минут, соответственно новые сэмплы в ней будут реже чем в исходной метрике:

groups:
  - name: my_group
    interval: 5m
    rules:  
    - record: http_requests:avg5m
      expr: avg_over_time(http_requests[5m])   

Тот факт что для vmalert'a источник данных и пункт записи сгенеренных данных задаются раздельными флагами (-datasource.url и -remoteWrite.url), позволяет читать данные из одного хранилища, даунсэмплить их и записывать получившиеся метрики в другое хранилище

Следующий пример демонстрирует как может выглядеть сетап где vmalert берет данные из горячего хранилища, обрабатывает их и записывает результат в холодное

С помощью vmalert'a пользователь может настроить recording rules для преобразования данных из горячих в холодные

./bin/vmalert -rule=downsampling-rules.yml \                                        # Path to the file with rules configuration. Supports wildcard
    -datasource.url=http://raw-cluster-vmselect:8481/select/0/prometheus            # vmselect addr for executing recordi ng rules expressions
    -remoteWrite.url=http://aggregated-cluster-vminsert:8480/insert/0/prometheus    # vminsert addr to persist recording rules results

vmalert_multicluster.png

Функцию replay можно использовать для трансформирования исторических данных
Флаги -remoteRead.url и -notifier.url опискаются когда мы используем vmalert только для применения recording rules

Multiple remote writes

Для указания пункта сохранения данных используется флаг -remoteWrite.url, но он принимает в себя только одно значение. Чтобы сохранять данные в множество хранилищ рекомендуется использовать vmagent как fan-out proxy:

vmalert_multiple_rw.png
При такой топологии vmalert шлет данные в vmagent, который в свою очередь кладет полученные данные в указанные у него -remoteWrite.url
Использование vmagent'a дает ряд дополнительных фич, таких как сохранение данных когда сторадж не доступен или модификация таймсерий через релейблинг

Web

vmalert предоставляет фронтенд который доступен на -httpListenAddr. Он предоставляет он предоставляет метрики и данные по алертам (как у прометеуса):

WEB UI vmalert'a может быть доступным из Виктории
Для этого ей нужно указать флаг -vmalert.proxyURL
Это нужно например для графаны

Graphite

Не интересно

Rules backfilling

vmalert поддерживает alerting и recording rules backfilling (aka replay). В реплей моде он может применить правила на указанный временной диапазон и записать результат в указанный remote storage

How it works

В replay mode vmalert работает как cli утилита и завершается сразу после завершения работы

root@mon-vm-01:~# ./vmalert-prod --datasource.url=http://localhost:8481/select/0/prometheus --notifier.url=http://localhost:9093 -remoteWrite.url=http://localhost:8480/insert/0/prometheus --rule=/etc/victoriametrics/vmalert/rules.yml -eula -replay.timeFrom=2022-08-31T02:20:00Z -replay.timeTo=2022-08-31T02:30:00Z
Copyright 2018-2022 VictoriaMetrics, Inc - All Rights Reserved.
For any questions please contact info@victoriametrics.com
2022-08-30T23:37:12.757Z        info    VictoriaMetrics/lib/logger/flag.go:12   build version: vmalert-20220808-174744-tags-v1.80.0-enterprise-0-gccf72e410
2022-08-30T23:37:12.757Z        info    VictoriaMetrics/lib/logger/flag.go:13   command-line flags
2022-08-30T23:37:12.757Z        info    VictoriaMetrics/lib/logger/flag.go:20     -datasource.url="http://localhost:8481/select/0/prometheus"
2022-08-30T23:37:12.757Z        info    VictoriaMetrics/lib/logger/flag.go:20     -eula="true"
2022-08-30T23:37:12.757Z        info    VictoriaMetrics/lib/logger/flag.go:20     -notifier.url="http://localhost:9093"
2022-08-30T23:37:12.757Z        info    VictoriaMetrics/lib/logger/flag.go:20     -remoteWrite.url="http://localhost:8480/insert/0/prometheus"
2022-08-30T23:37:12.757Z        info    VictoriaMetrics/lib/logger/flag.go:20     -replay.timeFrom="2022-08-31T02:20:00Z"
2022-08-30T23:37:12.757Z        info    VictoriaMetrics/lib/logger/flag.go:20     -replay.timeTo="2022-08-31T02:30:00Z"
2022-08-30T23:37:12.757Z        info    VictoriaMetrics/lib/logger/flag.go:20     -rule="/etc/victoriametrics/vmalert/rules.yml"
Replay mode:
from:   2022-08-31 02:20:00 +0000 UTC
to:     2022-08-31 02:30:00 +0000 UTC
max data points per request: 1000

Group "alert.rules"
interval:       1m0s
requests to make:       1
max range per request:  16h40m0s
> Rule "Node_State" (ID: 9459300515240668085)
1 / 1 [---------------------------------------------------------------------------------------------------------------------------------------------------------] 100.00% ? p/s
> Rule "recorded_metric" (ID: 331216927271362772)
1 / 1 [---------------------------------------------------------------------------------------------------------------------------------------------------------] 100.00% ? p/s
2022-08-30T23:37:14.792Z        info    VictoriaMetrics/app/vmalert/replay.go:81        replay finished! Imported 11 samples

Screenshot_2021_02_02-12_49_03-2022-08-31-at-02recordedrule.png

Группы обрабатываются поочередно, правила в группах обрабатыватся поочередно (concurrency нет)
vmalert шлет выражение рула на эндпоинт /query_range указанного -datasource.url
В примере выше был сделан примерно такой запрос (здесь результат изменен для краткости):

(ifree-test-k8s:default) vandud@macbook: ~ [0] ? curl -s 'http://mon-vm-01.g01.i-free.ru:8481/select/0/prometheus/api/v1/query_range?query=1&start=2022-08-31T02:20:00Z&end=2022-08-31T02:30:00Z&step=1m' | jq 'del(.data.result[0].values[0:-1])'
{
  "status": "success",
  "isPartial": false,
  "data": {
    "resultType": "matrix",
    "result": [
      {
        "metric": {},
        "values": [
          [
            1661913000,
            "1"
          ]
        ]
      }
    ]
  }
}

Полученные данные процессятся в соответствии с rule type и бэкфиллятся в -remoteWrite.url
vmalert использует evaluationInterval указанный через флаг или указанный в параметрах группы
Так же он автоматически выключает кэш на стороне VictoriaMetrics засылая ей параметр nocache=1, это позволяет предотвратить загрязнение кэша и нежелательное корректирование временных границ на протяжении backfilling'a

Результат реплея рекординг рулов должен совпадать с тем как если бы эти рулы выполнялись естественным путем
Результат реплея алертинг рулов это таймсерия ALERTS отражающая стейты алертов. Реплей алертрулов позволяет посмотреть как вел бы себя алерт в прошлом

Addtional configuration

Дополнительные необязательные флаги для реплея:

Limitations

Monitoring

vmalert экспозит различные метрики на эндпоинте /metrics
Есть официальный дашборд для графаны https://grafana.com/grafana/dashboards/14950-vmalert/

Profiling

vmalert предоставляет хэндлеры для сбора Go профилей:

Команда для сбора CPU профиля сперва ждет 30 секунд и только потом возращает результат
Собранные профили можно проанализировать утилитой https://github.com/google/pprof
Файлы профилей не содержат сенсетивной информации поэтому их можно без страха шарить кому-то

Configuration

Flags

vmalert имеет еще массу различных флагов, актуальную справку по которым можно увидеть запустив vmalert -help

Hot config reload

Плавно релоаднуть конфигурацию можно следующими образами:

URL params

Чтобы добавить какие-то дополнительные параметры для datasource.url, remoteWrite.url или remoteRead.url можно просто добавить их в url. Например - -datasource.url=http://localhost:8428?nocache=1
Чтобы добавить такие параметры для конкретных групп правил можно добавить секцию params в конфиге:

groups:
  - name: TestGroup
    params:
      denyPartialResponse: ["true"]
      extra_label: ["env=dev"]

Параметры используются только для применения выражений из правил, если происходит конфликт между параметрами из конфига и из флага то параметры из конфига будут иметь более высокий приоритет

Notifier configuration file

Notifier может быть законфигурирован через конфиг указанный в флаге -notifier.config:

./bin/vmalert -rule=app/vmalert/config/testdata/rules.good.rules \
  -datasource.url=http://localhost:8428 \
  -notifier.config=app/vmalert/notifier/testdata/consul.good.yaml

Конфиг позволяет описать статические нотифайеры и обнаруженные через Consul или DNS

static_configs: 
  - targets:
      - localhost:9093
      - localhost:9095

consul_sd_configs:
  - server: localhost:8500
    services:
      - alertmanager
      
dns_sd_configs:
  - names:
      - my.domain.com
    type: 'A'
    port: 9093

Список всех нотифайеров виден в UI

Спецификация конфига:

# Per-target Notifier timeout when pushing alerts.
[ timeout: <duration> | default = 10s ]

# Prefix for the HTTP path alerts are pushed to.
[ path_prefix: <path> | default = / ]

# Configures the protocol scheme used for requests.
[ scheme: <scheme> | default = http ]

# Sets the `Authorization` header on every request with the
# configured username and password.
# password and password_file are mutually exclusive.
basic_auth:
  [ username: <string> ]
  [ password: <secret> ]
  [ password_file: <string> ]

# Optional `Authorization` header configuration.
authorization:
  # Sets the authentication type.
  [ type: <string> | default: Bearer ]
  # Sets the credentials. It is mutually exclusive with
  # `credentials_file`.
  [ credentials: <secret> ]
  # Sets the credentials to the credentials read from the configured file.
  # It is mutually exclusive with `credentials`.
  [ credentials_file: <filename> ]

# Configures the scrape request's TLS settings.
# see https://prometheus.io/docs/prometheus/latest/configuration/configuration/#tls_config
tls_config:
  [ <tls_config> ]

# List of labeled statically configured Notifiers.
static_configs:
  targets:
    [ - '<host>' ]

# List of Consul service discovery configurations.
# See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#consul_sd_config
consul_sd_configs:
  [ - <consul_sd_config> ... ]

# List of DNS service discovery configurations.
# See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#dns_sd_config
dns_sd_configs:
  [ - <dns_sd_config> ... ]

# List of relabel configurations for entities discovered via service discovery.
# Supports the same relabeling features as the rest of VictoriaMetrics components.
# See https://docs.victoriametrics.com/vmagent.html#relabeling
relabel_configs:
  [ - <relabel_config> ... ]

# List of relabel configurations for alert labels sent via Notifier.
# Supports the same relabeling features as the rest of VictoriaMetrics components.
# See https://docs.victoriametrics.com/vmagent.html#relabeling
alert_relabel_configs:
  [ - <relabel_config> ... ]

Конфигурация может быть плавно релоаднута

Тесты для VictoriaMetrics

Setup

Используется версия 1.80.0 - https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.80.0


https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.80.0/victoria-metrics-linux-amd64-v1.80.0-cluster.tar.gz
https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.80.0/vmutils-linux-amd64-v1.80.0.tar.gz

vmalert придется использовать версии enterprise

Указанные выше архивы содержат бинари с приложениями
Все приложения из обоих архивов распакованы в /usr/local/bin/*
Из имен бинарей убрано окончание -prod: vmstorage-prod -> vmstorage

root@mon-vm-01:/usr/local/bin# ls -1
vmagent-prod
vmalert-prod
vmauth-prod
vmbackup-prod
vmctl-prod
vminsert-prod
vmrestore-prod
vmselect-prod
vmstorage-prod

root@mon-vm-01:/usr/local/bin# ls -1 | cut -d'-' -f1 | xargs -I{} mv {}-prod {}

root@mon-vm-01:/usr/local/bin# ls -1
vmagent
vmalert
vmauth
vmbackup
vmctl
vminsert
vmrestore
vmselect
vmstorage

Создан пользователь victoriametrics с группой victoriametrics

useradd -d /nonexistent -M -r -s /usr/sbin/nologin -U victoriametrics

systemd service взят отсюда - https://github.com/VictoriaMetrics/ansible-playbooks/blob/master/roles/vmagent/templates/vmagent.service.j2

Вот такой шаблон для списка сервисов:

[Unit]
Description=VictoriaMetrics ${app}
After=network.target

[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
EnvironmentFile=/etc/${app}/${app}.conf
ExecStart=/usr/local/bin/${app} -envflag.enable
ExecReload=/bin/kill -SIGHUP $MAINPID

SyslogIdentifier=${app}
Restart=always

PrivateTmp=yes
ProtectHome=yes
NoNewPrivileges=yes

ProtectSystem=full

ProtectControlGroups=true
ProtectKernelModules=true
ProtectKernelTunables=yes

[Install]
WantedBy=multi-user.target

Создать сервисы:

root@mon-vm-01:~# echo 'vmagent
vmalert
vmauth
vminsert
vmselect
vmstorage' | xargs -I{} sh -c "sed -e 's/\${app}/{}/g' app.service > {}.service"
root@mon-vm-01:~# cat vmagent.service
[Unit]
Description=VictoriaMetrics vmagent
After=network.target

[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
EnvironmentFile=/etc/vmagent/vmagent.conf
ExecStart=/usr/local/bin/vmagent -envflag.enable

SyslogIdentifier=vmagent
Restart=always

PrivateTmp=yes
ProtectHome=yes
NoNewPrivileges=yes

ProtectSystem=full

ProtectControlGroups=true
ProtectKernelModules=true
ProtectKernelTunables=yes

[Install]
WantedBy=multi-user.target
root@mon-vm-01:~# mv !(app.service) /etc/systemd/system/.
root@mon-vm-01:~# ls
app.service
root@mon-vm-01:~# systemctl daemon-reload
root@mon-vm-01:~# systemctl status vmagent
● vmagent.service - Description=VictoriaMetrics vmagent
   Loaded: loaded (/etc/systemd/system/vmagent.service; disabled; vendor preset: enabled)
   Active: inactive (dead)

Заэнейблить сервисы:

root@mon-vm-01:~# echo 'vmagent
vmalert
vmauth
vminsert
vmselect
vmstorage' | xargs -I{} systemctl enable {}
Created symlink /etc/systemd/system/multi-user.target.wants/vmagent.service → /etc/systemd/system/vmagent.service.
Created symlink /etc/systemd/system/multi-user.target.wants/vmalert.service → /etc/systemd/system/vmalert.service.
Created symlink /etc/systemd/system/multi-user.target.wants/vmauth.service → /etc/systemd/system/vmauth.service.
Created symlink /etc/systemd/system/multi-user.target.wants/vminsert.service → /etc/systemd/system/vminsert.service.
Created symlink /etc/systemd/system/multi-user.target.wants/vmselect.service → /etc/systemd/system/vmselect.service.
Created symlink /etc/systemd/system/multi-user.target.wants/vmstorage.service → /etc/systemd/system/vmstorage.service.

Приложения конфигурируются через переменные окружения (https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html#environment-variables)
В файле /etc/${app}/${app}.conf лежит список переменных в формате:

insert_maxQueueDuration=<duration>
...

То есть это просто имя флага где точка заменена на подчеркивание

Создать папки для конфигов приложений:

root@mon-vm-01:~# echo 'vmagent
vmalert
vmauth
vminsert
vmselect
vmstorage' | xargs -I{} sh -c "mkdir /etc/{}; chmod 755 /etc/{}"

root@mon-vm-01:~# ls -1 /etc/ | grep vm
vmagent
vmalert
vmauth
vminsert
vmselect
vmstorage

vmalert взят из enterprise версии https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.80.0/vmutils-linux-amd64-v1.80.0-enterprise.tar.gz


Конфигурирование:


node_exporter версии 1.3.1 - https://github.com/prometheus/node_exporter/releases/download/v1.3.1/node_exporter-1.3.1.linux-amd64.tar.gz

Пользователь:

useradd -d /nonexistent -M -r -s /usr/sbin/nologin -U node_exporter

systemd service:

[Unit]
Description=Node Exporter
After=network.target

[Service]
Type=simple
User=node_exporter
Group=node_exporter
ExecStart=/usr/local/bin/node_exporter

SyslogIdentifier=node_exporter
Restart=always

PrivateTmp=yes
ProtectHome=yes
NoNewPrivileges=yes

ProtectSystem=full

ProtectControlGroups=true
ProtectKernelModules=true
ProtectKernelTunables=yes

[Install]
WantedBy=multi-user.target

windows_exporter 0.19.0
https://github.com/prometheus-community/windows_exporter/releases/tag/v0.19.0
https://github.com/prometheus-community/windows_exporter


mon-proxy-01
аналогичным всем остальным утилитам способ установлен vmauth


Порты везде открываются через AWX


Для решения вот этой проблемы https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3061 используется nginx
Со следующей конфигурацией:

root@mon-proxy-01x:/etc/vmauth# cat /etc/nginx/sites-enabled/default
upstream vminsert {
        server mon-vm-01.g01.i-free.ru:8480;
        server mon-vm-02.g01.i-free.ru:8480;
        server mon-vm-03.g01.i-free.ru:8480;
}
upstream vmselect {
        server mon-vm-01.g01.i-free.ru:8481;
        server mon-vm-02.g01.i-free.ru:8481;
        server mon-vm-03.g01.i-free.ru:8481;
}
server {
  listen 8428;
  location /insert {
    proxy_pass http://vminsert;
  }
  location /select {
    proxy_pass http://vmselect;
  }
}

Alertmanager version - 0.24.0
https://github.com/prometheus/alertmanager/releases/download/v0.24.0/alertmanager-0.24.0.linux-amd64.tar.gz

Бинари alertmanager и amtool кладутся в /usr/local/bin/.

Пользователь:

useradd -d /nonexistent -M -r -s /usr/sbin/nologin -U alertmanager

Создать папку для хранения стейтов алертов (что акнуто, что отправлено, итд):

mkdir /var/lib/alertmanager; chown -R alertmanager:alertmanager /var/lib/alertmanager

Папка для конфигов:

mkdir /etc/alertmanager; chown -R alertmanager:alertmanager /etc/alertmanager/

systemd service:

root@mon-vm-01:~# cat /etc/systemd/system/alertmanager.service
[Unit]
Description=Alertmanager
After=network.target

[Service]
Type=simple
User=alertmanager
Group=alertmanager
ExecStart=/usr/local/bin/alertmanager --config.file=/etc/alertmanager/main.yaml --storage.path=/var/lib/alertmanager/ --log.level=debug --cluster.peer=mon-vm-02.g01.i-free.ru:9094 --cluster.peer=mon-vm-03.g01.i-free.ru:9094
ExecReload=/bin/kill -SIGHUP $MAINPID

SyslogIdentifier=alertmanager
Restart=always

PrivateTmp=yes
ProtectHome=yes
NoNewPrivileges=yes

ProtectSystem=full

ProtectControlGroups=true
ProtectKernelModules=true
ProtectKernelTunables=yes

[Install]
WantedBy=multi-user.target

grafana
stable релиз по инструкции - https://grafana.com/docs/grafana/latest/setup-grafana/installation/debian/

apt-get install -y apt-transport-https; apt-get install -y software-properties-common wget; wget -q -O /usr/share/keyrings/grafana.key https://packages.grafana.com/gpg.key; echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list; apt-get update; apt-get install grafana

Prometheus-msteams version - 1.5.1 https://github.com/prometheus-msteams/prometheus-msteams/releases/download/v1.5.1/prometheus-msteams-linux-amd64

бинарь в /usr/local/bin/

юзер

useradd -d /nonexistent -M -r -s /usr/sbin/nologin -U prometheus-msteams

папка для конфигов

mkdir /etc/prometheus-msteams; chown -R prometheus-msteams:prometheus-msteams /etc/prometheus-msteams

конфиг и шаблон для алерта

vim /etc/prometheus-msteams/config.yml
connectors:
  - alert_channel: "WEBHOOK"
vim /etc/prometheus-msteams/card.tmpl
{{ define "teams.card" }}
{
  "@type": "MessageCard",
  "@context": "http://schema.org/extensions",
  "themeColor": "{{- if eq .Status "resolved" -}}2DC72D
                 {{- else if eq .Status "firing" -}}
                    {{- if eq .CommonLabels.severity "critical" -}}8C1A1A
                    {{- else if eq .CommonLabels.severity "warning" -}}FFA500
                    {{- else -}}808080{{- end -}}
                 {{- else -}}808080{{- end -}}",
  "summary": "VictoriaMetrics Alerts",
  "title": "VictoriaMetrics ({{ .Status }})",
  "sections": [ {{$externalUrl := .ExternalURL}}
  {{- range $index, $alert := .Alerts }}{{- if $index }},{{- end }}
    {
      "facts": [
        {{- range $key, $value := $alert.Annotations }}
        {
          "name": "{{ reReplaceAll "_" "\\\\_" $key }}",
          "value": "{{ reReplaceAll "_" "\\\\_" $value }}"
        },
        {{- end -}}
        {{$c := counter}}{{ range $key, $value := $alert.Labels }}{{if call $c}},{{ end }}
        {
          "name": "{{ reReplaceAll "_" "\\\\_" $key }}",
          "value": "{{ reReplaceAll "_" "\\\\_" $value }}"
        }
        {{- end }}
      ],
      "markdown": true
    }
    {{- end }}
  ]
}
{{ end }}

создаем юнит

vim /etc/systemd/system/prometheus-msteams.service
[Unit]
Description=Prometheus-msteams
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus-msteams
Group=prometheus-msteams
Type=simple
ExecStart=/usr/local/bin/prometheus-msteams -config-file /etc/prometheus-msteams/config.yml -template-file /etc/prometheus-msteams/card.tmpl
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl start prometheus-msteams.service
systemctl enable prometheus-msteams.service

OpenResty установлен по этой статье https://www.installing.in/how-to-install-openresty-on-debian-10/
Изменения в systemd сервисе

root@mon-proxy-01y:/usr/local/openresty# diff /tmp/openresty.service.old /lib/systemd/system/openresty.service
21,24c21,24
< ExecStartPre=/usr/local/openresty/nginx/sbin/nginx -t -q -g 'daemon on; master_process on;'
< ExecStart=/usr/local/openresty/nginx/sbin/nginx -g 'daemon on; master_process on;'
< ExecReload=/usr/local/openresty/nginx/sbin/nginx -g 'daemon on; master_process on;' -s reload
< ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /usr/local/openresty/nginx/logs/nginx.pid
---
> ExecStartPre=/usr/local/openresty/nginx/sbin/nginx -t -q -g 'daemon on; master_process on;' -c /etc/nginx/nginx.conf
> ExecStart=/usr/local/openresty/nginx/sbin/nginx -g 'daemon on; master_process on;' -c /etc/nginx/nginx.conf
> ExecReload=/usr/local/openresty/nginx/sbin/nginx -g 'daemon on; master_process on;' -s reload -c /etc/nginx/nginx.conf
> ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /usr/local/openresty/nginx/logs/nginx.pid -c /etc/nginx/nginx.conf

Так же нужно перенести дефолтный конфиг openresty в /etc/nginx:

root@mon-proxy-01y:/etc/nginx# rm -rf !(sites-enabled) ^C
root@mon-proxy-01y:/etc/nginx# cp -R /usr/local/openresty/nginx/conf/. /etc/nginx/. ^C

И привести секцию http в nginx.conf к следующему виду:

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    include /etc/nginx/sites-enabled/*;

}

apt install libjq-dev


Вместо alertmanager'a используется cortex-alertmanager (потому что у нем есть multitenancy)
Взята версия Cortex 1.13.0

https://github.com/cortexproject/cortex/releases/download/v1.13.0/cortex-linux-amd64

Директория для конфигов - /etc/cortex-alertmanager

root@mon-vm-01:/etc/cortex-alertmanager# tree
.
├── configs
│   └── 1.yml
├── fallback.yaml
└── main.yaml

1 directory, 3 files
root@mon-vm-01:/etc/cortex-alertmanager# cat main.yaml
target: alertmanager

server:
  http_listen_port: 9093

alertmanager:
  external_url: http://mon-vm-01.test.i-free.ru:9093/alertmanager
  data_dir: /var/lib/cortex-alertmanager
  retention: 120h
  poll_interval: 15s
  sharding_enabled: false

  fallback_config_file: /etc/cortex-alertmanager/fallback.yaml
  # [auto_webhook_root: <string> | default = ""]
  cluster:
    listen_address: "0.0.0.0:9094"
    advertise_address: ""
    peers: "mon-vm-01.test.i-free.ru:9094,mon-vm-02.test.i-free.ru:9094,mon-vm-03.test.i-free.ru:9094"
    peer_timeout: 15s
    gossip_interval: 200ms
    push_pull_interval: 1m

  storage:
    type: local
    local:
      path: /etc/cortex-alertmanager/configs
wget https://github.com/cortexproject/cortex/releases/download/v1.13.0/cortex-linux-amd64 -O /usr/local/bin/cortex-alertmanager
chmod 755 /usr/local/bin/cortex-alertmanager
useradd -d /nonexistent -M -r -s /usr/sbin/nologin -U cortex-alertmanager

systemd unit:

cat <<EOF > /etc/systemd/system/cortex-alertmanager.service
[Unit]
Description=Horizontally scalable, highly available, multi-tenant, long term Prometheus.
Documentation=https://cortexmetrics.io/docs
Wants=network-online.target
After=network-online.target

[Service]
Restart=always
User=cortex-alertmanager
ExecStart=/usr/local/bin/cortex-alertmanager --config.file /etc/cortex-alertmanager/main.yaml
ExecReload=/bin/kill -HUP $MAINPID
TimeoutStopSec=20s
SendSIGKILL=no
WorkingDirectory=/var/lib/cortex-alertmanager

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
mkdir /var/lib/cortex-alertmanager; chown -R cortex-alertmanager:cortex-alertmanager /var/lib/cortex-alertmanager
mkdir /etc/cortex-alertmanager; chown -R cortex-alertmanager:cortex-alertmanager /etc/cortex-alertmanager
mkdir /etc/cortex-alertmanager/configs; chown -R cortex-alertmanager:cortex-alertmanager /etc/cortex-alertmanager/configs/
systemctl enable cortex-alertmanager.service

Grafana Provisioning

Организации можно создавать только вручную (или через API)
Поэтому пока будем делать их вручную


LDAP
группы в ldap под тенанты кроме первого тенанта
в первый тенант (monitoring) добавляем по группе techsupp@i-free.com


Для ансиблизирования keepalived использована эта роль https://github.com/Oefenweb/ansible-keepalived (немного модифицирована)

Переналив машин

mon-proxy-01x.g01.i-free.ru (hoster-kvm-23.g01.i-free.ru)

virsh shutdown mon-proxy-01x.g01.i-free.ru
virsh undefine --remove-all-storage mon-proxy-01x.g01.i-free.ru
vm_create.sh -m 1024 -c 1 -s 20  -b vlanbr294 -i 172.27.245.237 -n 255.255.255.0 -g 172.27.247.254 ifree-buster-2.tar mon-proxy-01x.g01.i-free.ru -d "172.27.245.100" -e "Monitoring (prod)" --cpu-model SandyBridge
virsh -c qemu:///system start mon-proxy-01x.g01.i-free.ru
virsh attach-interface mon-proxy-01x.g01.i-free.ru bridge vlanbr300 --model virtio --persistent

mon-proxy-01y.g01.i-free.ru (hoster-kvm-24.g01.i-free.ru)

virsh shutdown mon-proxy-01y.g01.i-free.ru
virsh undefine --remove-all-storage mon-proxy-01y.g01.i-free.ru
vm_create.sh -m 1024 -c 1 -s 20  -b vlanbr294 -i 172.27.245.227 -n 255.255.255.0 -g 172.27.247.254 ifree-buster-2.tar mon-proxy-01y.g01.i-free.ru -d "172.27.245.100" -e "Monitoring (prod)" --cpu-model SandyBridge
virsh -c qemu:///system start mon-proxy-01y.g01.i-free.ru
virsh attach-interface mon-proxy-01y.g01.i-free.ru bridge vlanbr300 --model virtio --persistent

mon-exporters-01x.g01.i-free.ru (hoster-kvm-25.g01.i-free.ru)

vm_create.sh -m 4096 -c 4 -s 40  -b vlanbr294 -i 172.27.245.248 -n 255.255.255.0 -g 172.27.247.254 ifree-buster-2.tar mon-exporters-01x.g01.i-free.ru -d "172.27.245.100" -e "Monitoring (prod)" --cpu-model SandyBridge
virsh attach-interface mon-exporters-01x.g01.i-free.ru bridge vlanbr300 --model virtio --persistent

mon-exporters-01y.g01.i-free.ru (hoster-kvm-24.g01.i-free.ru)

vm_create.sh -m 4096 -c 4 -s 40  -b vlanbr294 -i 172.27.245.250 -n 255.255.255.0 -g 172.27.247.254 ifree-buster-2.tar mon-exporters-01y.g01.i-free.ru -d "172.27.245.100" -e "Monitoring (prod)" --cpu-model SandyBridge
virsh attach-interface mon-exporters-01y.g01.i-free.ru bridge vlanbr300 --model virtio --persistent

mtail

https://github.com/google/mtail/releases/download/v3.0.0-rc50/mtail_3.0.0-rc50_Linux_x86_64.tar.gz

Kubernetes Monitoring

Чтобы замониторить k8s с помощью VictoriaMetrics, нужно установить туда victoria-metrics-k8s-stack helm chart
Сперва подготовь вот такой вэльюс и отредактируй если нужно (обязательно подставь корректный адрес для remote write), можешь добавить каких-то лейблов для vmagent (эти лейблы будут на всех собранных метриках)

# victoria-metrics-k8s-stack.values.yaml
---
fullnameOverride: "victoria-metrics-k8s-stack"
victoria-metrics-operator:
  operator:
    disable_prometheus_converter: false
externalVM:
  write:
    url: "http://10.0.244.254:8428/api/v1/write"
    # bearerTokenSecret:
    #   name: dbaas-read-access-token
    #   key: bearerToken
vmagent:
  spec:
    externalLabels:
      cluster: test
      env: test
defaultRules:
  create: false
vmsingle:
  enabled: false
alertmanager:
  enabled: false
vmalert:
  enabled: false
grafana:
  enabled: false
prometheus-node-exporter:
  enabled: true
kube-state-metrics:
  enabled: true
kubeEtcd:
  enabled: false
crds:
  enabled: true

Далее задеплой это такими командами:

helm repo add vm https://victoriametrics.github.io/helm-charts/
helm install victoria-metrics-k8s-stack vm/victoria-metrics-k8s-stack --version 0.18.8 -n monitoring --create-
namespace --wait --atomic --values victoria-metrics-k8s-stack.values.yaml

Также нужно чтобы были установлены CRD от prometheus-operator (проверь, они могут быть уже установлены (например если ранее стоял kube-prometheus-stack))

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus-operator-crds prometheus-community/prometheus-operator-crds -n monitoring