Skip to content

Instantly share code, notes, and snippets.

@vorlon001
Last active July 29, 2026 14:57
Show Gist options
  • Select an option

  • Save vorlon001/ded54f6fc9f62d4a2f8b7972a3792004 to your computer and use it in GitHub Desktop.

Select an option

Save vorlon001/ded54f6fc9f62d4a2f8b7972a3792004 to your computer and use it in GitHub Desktop.
Victoria Metrics Cluster + Federation, Google AI

Полное и структурированное техническое решение, включающее описание задачи, архитектурную схему и все необходимые конфигурационные файлы.

📋 1. Описание задачи

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

  • Изоляция и автономность: Кластер Kubernetes должен собирать и хранить метрики локально, оставаясь независимым от доступности центральных ЦОДов.
  • Отказоустойчивость 1+1: Центральное хранилище развернуто в двух независимых ЦОДах (ЦОД-1 и ЦОД-2). Данные должны записываться в оба ЦОДа параллельно. При падении одного из них сбор и историчность данных не нарушаются.
  • Безопасность: Доступ к метрикам из Kubernetes наружу должен осуществляться по протоколу Gateway API с обязательной базовой аутентификацией (Basic Auth).
  • Полнота данных: С локального кластера необходимо забирать абсолютно все метрики без фильтрации на этапе отдачи, но с возможностью их постобработки (очистки от тестового мусора) на стороне центрального сборщика.

🗺️ 2. Архитектурная схема потоков данных (Pull-модель)

       [ KUBERNETES CLUSTER ]
  +-----------------------------------+
  |                                   |
  |  [vmagent (K8s)]                  |
  |         │                         |
  |         │                         |
  |         ▼                         |
  |    [vminsert]                     |
  |         │                         |
  |         │                         |
  |         ▼                         |
  |  [vmstorage (K8s)]                |
  |         │                         |
  |         │                         |
  |         ▼                         |
  |  [vmselect (K8s)] :8481           |
  +─────────┬─────────────────────────+
            │
            │
            ▼ (внутренний трафик)
   [HTTPRoute / Gateway API] (Авторизация: federation_user / secure_password)
            │
            ▲ (скрапинг наружу через порт :80/:443)
            │
 ┌──────────┴───────────────────────────────────────────────────────┐
 │                      [ ЦЕНТРАЛЬНЫЙ КОНТУР ]                      │
 │                                                                  │
 │                    ┌────────────────────────┐                    │
 │                    │ Глобальный [vmagent]   │                    │
 │                    │  (сборщик в ЦОДах)     │                    │
 │                    └───────────┬────────────┘                    │
 │                                │                                 │
 │                ┌───────────────┴───────────────┐                 │
 │                ▼ (remote_write)                ▼ (remote_write)  │
 │         [ ЦОД-1 (1) ]                   [ ЦОД-2 (+1) ]           │
 │   ┌───────────────────────┐       ┌───────────────────────┐      │
 │   │ [vminsert]            │       │ [vminsert]            │      │
 │   │     │                 │       │     │                 │      │
 │   │     ▼                 │       │     ▼                 │      │
 │   │ [vmstorage (ЦОД-1)]   │       │ [vmstorage (ЦОД-2)]   │      │
 │   │     ▲                 │       │     ▲                 │      │
 │   │     │ (чтение)        │       │     │ (чтение)        │      │
 │   │ [vmselect]            │       │ [vmselect]            │      │
 │   │  └─ флаг -dedup       │       │  └─ флаг -dedup       │      │
 │   └───────────────────────┘       └───────────────────────┘      │
 └──────────────────────────────────────────────────────────────────┘

🛠️ 3. Полный комплект конфигураций и манифестов

ШАГ 1: Подготовка учетных данных (Basic Auth)

Сгенерируйте зашифрованную строку для Kubernetes Secret (логин: federation_user, пароль: secure_password):

echo -n "federation_user:$(openssl passwd -apr1 secure_password)" | base64
# Ожидаемый результат: ZmVkZXJhdGlvbl91c2VyOiRhcHIxJHBDU1R4S1ZDJFhEVmlvT1E4dnUzQmhvRHUveHNLMS8K

ШАГ 2: Инфраструктурный манифест для Kubernetes (k8s-monitoring-bundle.yaml)

Этот манифест разворачивает локальный VMCluster через оператор, создает секрет авторизации, включает фильтр аутентификации для Gateway API и настраивает маршрут до компонента vmselect.

---
# https://docs.victoriametrics.com/operator/resources/vmcluster/
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMCluster
metadata:
  name: k8s-local-cluster
  namespace: monitoringspec:
  vminsert:
    replicaCount: 2
    resources:
      limits: { cpu: "2", memory: 4Gi }
      requests: { cpu: "500m", memory: 1Gi }
  vmselect:
    replicaCount: 2
    cacheMountPath: "/cache"
    storage:
      volumeClaimTemplate:
        spec:
          resources:
            requests: { storage: 10Gi }
    resources:
      limits: { cpu: "2", memory: 4Gi }
  vmstorage:
    replicaCount: 2
    retentionPeriod: "1" # Локально храним данные всего 1 месяц
    storage:
      volumeClaimTemplate:
        spec:
          resources:
            requests: { storage: 100Gi }
    resources:
      limits: { cpu: "4", memory: 8Gi }
---
apiVersion: v1
kind: Secret
metadata:
  name: federation-auth-secret
  namespace: monitoringtype: Opaquedata:
  # Base64 строка, полученная на этапе генерации
  auth: ZmVkZXJhdGlvbl91c2VyOiRhcHIxJHBDU1R4S1ZDJFhEVmlvT1E4dnUzQmhvRHUveHNLMS8K
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: AuthenticationFiltermetadata:
  name: basic-auth-filter
  namespace: monitoringspec:
  type: Basic
  basic:
    secretRef:
      name: federation-auth-secret
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: vmselect-federation-route
  namespace: monitoringspec:
  parentRefs:
    - name: global-gateway         # Имя вашего шлюза Gateway API в кластере
      namespace: gateway-system    # Неймспейс шлюза
  hostnames:
    - "k8s-metrics.company.local"
  rules:
    - matches:
        - path:
            type: Exact
            value: /select/0/prometheus/federate
      filters:
        - type: ExtensionRef
          extensionRef:
            group: gateway.envoyproxy.io
            kind: AuthenticationFilter
            name: basic-auth-filter
      backendRefs:
        - name: vmselect-k8s-local-cluster # Имя сервиса, генерируемое VictoriaMetrics Operator автоматически
          port: 8481

ШАГ 3: Конфигурация глобального vmagent в ЦОДах (vmagent.yml)

Этот конфигурационный файл указывает центральному сборщику забирать абсолютно все метрики через эндпоинт федерации Gateway API и на лету отсекать мусорные данные.

global:
  scrape_interval: 30s
  external_labels:
    datacenter: "global_core"
scrape_configs:
  - job_name: 'federation_k8s_gateway'
    metrics_path: '/select/0/prometheus/federate'
    honor_labels: true 
    
    # Пулл всех метрик без исключения
    params:
      'match[]':
        - '{__name__=~".+"}'

    # Авторизация для прохождения шлюза Gateway API
    basic_auth:
      username: "federation_user"
      password: "secure_password"

    static_configs:
      - targets: ['k8s-metrics.company.local:80']
        labels:
          environment: 'k8s-prod-cluster'

    # Тонкая фильтрация потока меток после забора всех данных
    metric_relabel_configs:
      # Исключаем метрики из тестовых стендов для экономии диска в ЦОДах
      - source_labels: [namespace]
        regex: '(dev|test|sandbox)'
        action: drop

      # Удаляем тяжелую техническую метку
      - regex: 'image_id'
        action: labeldrop

Если вы хотите фильтровать метрики прямо во время выборки (скрапинга) на уровне параметров match[], а не после загрузки в память, то синтаксис остается в рамках языка PromQL. Вы можете комбинировать имя метрики и любые лейблы внутри фигурных скобок прямо в параметре match[]. Ниже приведен обновленный пример конфигурации глобального vmagent.

Пример конфигурации vmagent.yml с фильтрацией по меткам на этапе выборки

При таком подходе vmagent отправит запрос к vmselect в K8s, и vmselect отдаст только те метрики, которые соответствуют указанным лейблам. Это значительно экономит сетевой трафик между Кубом и ЦОДами.

global:
  scrape_interval: 30s
  external_labels:
    datacenter: "global_core"
scrape_configs:
  - job_name: 'federation_k8s_gateway'
    metrics_path: '/select/0/prometheus/federate'
    honor_labels: true 

    # ФИЛЬТРАЦИЯ НА ЭТАПЕ ВЫБОРКИ (Запрос к vmselect):
    params:
      'match[]':
        # Вариант 1: Забрать ВСЕ метрики, но только из определенного неймспейса
        - '{namespace="production"}'
        
        # Вариант 2: Забрать только метрики определенного приложения с конкретным окружением
        - '{app="myapp", env="prod"}'
        
        # Вариант 3: Использовать регулярные выражения (забрать из нескольких неймспейсов)
        - '{namespace=~"(production|stage|infrastructure)"}'
        
        # Вариант 4: Фильтр по имени метрики И по метке одновременно
        # Забираем только CPU-метрики контейнеров, игнорируя всё остальное
        - '{__name__=~"container_cpu_.*", container!=""}'
        
        # Вариант 5: Исключение по метке (забрать всё, кроме метрик с лейблом tier="frontend")
        - '{tier!="frontend"}'

    basic_auth:
      username: "federation_user"
      password: "secure_password"

    static_configs:
      - targets: ['k8s-metrics.company.local:80']
        labels:
          environment: 'k8s-prod-cluster'

Docs: https://docs.victoriametrics.com/victoriametrics/url-examples/

Single-node VictoriaMetrics:

curl 'http://<vmsingle>:8428/federate' -d 'match[]=vm_http_request_errors_total'

Cluster version of VictoriaMetrics:

curl 'http://<vmselect>:8481/select/0/prometheus/federate' -d 'match[]=vm_http_request_errors_total'

В чем разница между фильтрацией в params.match[] и metric_relabel_configs?

  1. Фильтрация в params (match[]) [Pull-фильтр]:
  • Как работает: vmagent просит у vmselect только то, что написано в блоке.
    • Плюсы: Минимальный сетевой трафик. vmselect в Кубе сам отсекает лишнее и отдает наружу компактный ответ.
    • Минусы: Нельзя сделать сложные трансформации (переименовать метку, удалить конкретный лейбл из метрики).
  1. Фильтрация в metric_relabel_configs [Пост-фильтр]:
  • Как работает: vmagent выкачивает вообще всё, а затем локально в своей памяти дропает ненужное.
    • Плюсы: Можно гибко модифицировать структуру метрик, переименовывать лейблы и комбинировать их.
    • Минусы: Нагрузка на сеть, так как из Куба в ЦОД изначально летят «сырые» гигабайты данных.

ШАГ 4: Команда запуска глобального vmagent в режиме 1+1

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

/usr/local/bin/vmagent \
  -config=/etc/vmagent/vmagent.yml \
  -remoteWrite.url=http://company.local \
  -remoteWrite.url=http://company.local \
  -remoteWrite.tmpDataPath=/var/lib/vmagent/tmp

*Параметр -remoteWrite.tmpDataPath критически важен: если один из ЦОДов уйдет в оффлайн, агент начнет буферизировать данные на диск и дошлет их сразу после восстановления сети.

ШАГ 5: Запуск компонентов чтения (vmselect) в ЦОД-1 и ЦОД-2

Для предотвращения дублирования графиков при отображении в Grafana из двух идентичных источников, каждый центральный vmselect в обоих ЦОДах запускается с флагом дедупликации:

-dedup.minScrapeInterval=30s

пример настройки vmagent

Вот полный практический пример для Шага 1 (настройка локального vmagent, который будет собирать метрики с локальных целей и отдавать их наружу для центрального сервера по pull-модели). В этом примере настроим vmagent так, чтобы он собирал метрики с самого себя и с локального node_exporter, сохранял их и ждал, пока центральный сервер заберет данные.

1. Файл конфигурации сбора (vmagent.yml)

Создайте конфигурационный файл для vmagent, где укажите, откуда ему локально забирать метрики:

global:
  scrape_interval: 15s # Как часто vmagent собирает метрики локально
scrape_configs:
  # Задача 1: Сбор метрик производительности самого vmagent
  - job_name: 'vmagent-local'
    static_configs:
      - targets: ['localhost:8429']
  # Задача 2: Сбор системных метрик ОС (если запущен node_exporter)
  - job_name: 'node-exporter-local'
    static_configs:
      - targets: ['localhost:9100']

2. Варианты запуска vmagent

Вариант А: Запуск в Docker

Самый быстрый способ развернуть агент с открытым портом наружу:

docker run -d \
  --name=vmagent-federation \
  -p 8429:8429 \
  -v $(pwd)/vmagent.yml:/etc/vmagent.yml \
  victoriametrics/vmagent:v1.101.0 \
  -promscrape.config=/etc/vmagent.yml \
  -remoteWrite.tmpDataPath=/tmp/vmagent-cache

Параметр -remoteWrite.tmpDataPath обязателен, так как vmagent будет кэшировать собранные данные в этой директории, пока их кто-нибудь не заберет или пока не настроен remote write.

Вариант Б: Запуск как службы Systemd (для Linux)

Если вы устанавливаете vmagent как бинарный файл, отредактируйте его unit-файл (обычно /etc/systemd/system/vmagent.service):

[Unit]
Description=VictoriaMetrics Agent
After=network.target

[Service]
Type=simple
User=prometheus
ExecStart=/usr/local/bin/vmagent \
  -promscrape.config=/etc/vmagent/vmagent.yml \
  -httpListenAddr=0.0.0.0:8429 \
  -remoteWrite.tmpDataPath=/var/lib/vmagent/cache

Restart=always

[Install]
WantedBy=multi-user.target

После создания файла выполните:

systemctl daemon-reload
systemctl enable --now vmagent

3. Проверка готовности Шага 1

Чтобы убедиться, что vmagent успешно запустился, собирает метрики и готов отдавать их центральному серверу, выполните команду curl с любого доверенного сервера в сети (или локально):

  • Проверить статус здоровья:
curl http://<IP_АДРЕС_VMAGENT>:8429/-/healthy# Ответ должен быть: VictoriaMetrics is Healthy
  • Проверить эндпоинт федерации (доступность данных):
curl -G 'http://<IP_АДРЕС_VMAGENT>:8429/api/v1/federate' --data-urlencode 'match[]={job="vmagent-local"}'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment