Как мы реализовали мониторинг на автопилоте: наш стек с VictoriaMetrics

Мониторинг — это сердце любой современной IT-инфраструктуры. Сегодня я хочу рассказать о нашем опыте построения и развития инфраструктуры мониторинга в одном из крупнейших банков России – Россельхозбанке.

Привет, Хабр! Меня зовут Сергей Смирнов, я DevOps экосистемы "Своё" в РСХБ.Цифра. Наша команда занимается поддержкой инфраструктуры проектов.

  • Свое Фермерство
  • Свое Родное
  • Свое за Городом
  • Я в Агро
  • Все свое

Речь пойдет не о всей гигантской IT-инфраструктуре банка, а о ее специфической части. Мы работаем с тем, что можно назвать "внешним облаком" РСХБ. В этой статье я расскажу об общей архитектуре, ключевых технологиях для сбора метрик, логов, трассировок, алертинга и визуализации, принципах настройки и развертывания, примерах и готовых решениях, в частности о том, как Victoria Metrics может стать центральным элементом системы мониторинга, охватывающей как Kubernetes, так и другие компоненты инфраструктуры.

Самое главное – я поделюсь конкретными примерами конфигурационных файлов, Helm-чартов или других манифестов, которые позволят вам развернуть базовый (или даже расширенный) стек мониторинга "из коробки" в вашей собственной среде.

Тема актуальна из-за растущей потребности в универсальных системах мониторинга, способных:

  • Обеспечивать глубокий анализ Kubernetes-кластеров,
  • Мониторить традиционные серверные инфраструктуры,
  • Работать с облачными сервисами,
  • Обрабатывать большие объемы данных,
  • Предоставлять гибкие возможности визуализации.

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

На практике развернем и настроим готовый вариант для мониторинга инфраструктуры.

Как работает система

Основные части системы:

  • VMSingle: Хранилище метрик.
  • VMAgent: Сборщик метрик.
  • VMAlert: Проверяет правила и создает алерты.
  • Alertmanager: Система управления оповещениями.
  • Grafana: Визуализация метрик, логов и прочего.
  • VMAuth: Прокси с авторизацией.
  • x509-certificate-exporter: Следит за сертификатами Kubernetes.
  • Prometheus Blackbox Exporter: Blackbox-мониторинг.
Предварительные требования
  • Требования к установке:
    • Kubernetes-кластер 1.25+
    • Helm 3+
    • Предустановленный Vault для секретов и External Secrets (включая External Secrets Operator). По настройке оставлю ссылку на свою предыдущую статью.
  • Зависимости для Helm: В боевом решении мы используем Argo CD для автоматизации, но для этого гайда упростим задачу и возьмем Helm. Чарт зависит от следующих пакетов:
    • victoria-metrics-k8s-stack — Helm charts · GitHub
    • grafana-operator — Helm charts · GitHub
    • prometheus-blackbox-exporter — Helm charts · GitHub
    • x509-certificate-exporter — Helm charts · GitHub
Пример Chart.yaml
apiVersion: v2 name: lab description: Lab Kubernetes monitoring stack type: application version: 0.1.0 appVersion: "0.1.0" dependencies: # Список зависимостей от других чартов - name: victoria-metrics-k8s-stack # Зависимость от стека VictoriaMetrics version: 0.x.x repository: https://victoriametrics.github.io/helm-charts/ # ... другие зависимости
Конфигурация lab_values.yaml

Файл разделён на части по блокам.

Начнём с конфигурации victoria-metrics-k8s-stack. В чарт "из коробки" входят следующие компоненты:

  • VM Operator
  • VMSingle
  • VMAgent
  • VMAlert
  • Alertmanager
Общая конфигурация

Helm-чарт victoria-metrics-k8s-stack поставляет из коробки необходимые дашборды и правила для мониторинга Kubernetes. Мы вынесли их из этого чарта в целевой чарт для управления и дальнейшей доработки.

Если вы пользовались CRD от Prometheus, VM Operator конвертирует их в свои CRD.

Конфигурация lab_values.yaml
global: cluster: # Суффикс DNS кластера (обычно cluster.local.). Здесь lab. — просто тестовый пример. dnsDomain: lab. victoria-metrics-k8s-stack: fullnameOverride: "k8s" victoria-metrics-operator: # Оператор для управления VM ресурсами serviceAccount: create: true operator: prometheus_converter_add_argocd_ignore_annotations: true enable_converter_ownership: true grafana: # Настройка встроенной в VM k8s stack Grafana (отключена) enabled: false defaultRules: # Дефолтные правила алертинга (отключены) create: false defaultDashboards: # Дефолтные дашборды (отключены) enabled: false defaultTimezone: msk labels: {} annotations: {} grafanaOperator: enabled: true spec: instanceSelector: matchLabels: dashboards: grafana allowCrossNamespaceImport: false dashboards: victoriametrics-vmalert: enabled: false victoriametrics-operator: enabled: false node-exporter-full: enabled: false
Настройка VMSingle

Для наших задач хватает VMSingle — компонент для развертывания одноузловой версии (приём, хранение, обработка данных, API) VictoriaMetrics в Kubernetes.Если скорость обработки данных более миллиона точек в секунду(взято из документации), нужна мультитенантность или retention для разных метрик/тенантов — используйте VMCluster.

Конфигурация lab_values.yaml
vmsingle: enabled: true spec: # По умолчанию VMSingle слушает на 8428. port: "8428" # Если единица не указана, то значение в месяцах: "1" = 1 месяц. retentionPeriod: "1" extraArgs: dedup.minScrapeInterval: 30s # Ресурсы произвольные, взяты для теста resources: requests: memory: "800Mi" cpu: "600m" limits: memory: "1600Mi" cpu: "1200m" storage: # По умолчанию использует дефолтный storage class accessModes: - ReadWriteOnce resources: requests: storage: 20Gi
Настройка VMAgent

VMAgent — агент для сбора метрик из различных источников.

Настроим VMAgent и таргеты для мониторинга. Метрики Kubernetes собираются из коробки. Для внешних таргетов необходимо настроить volumes и volumeMounts.

Конфигурация из lab_values.yaml
vmagent: enabled: true spec: resources: limits: cpu: "300m" memory: "600Mi" requests: cpu: "150m" memory: "300Mi" scrapeInterval: 30s scrapeTimeout: 25s externalLabels: env: lab-infra # Дополнительный лейбл для фильтрации, если у вас несколько VMAgent в других кластерах/VM и т.п. replicaCount: 2 selectAllByDefault: true secrets: ["etcd-secret"] # Нужен для аутентификации в etcd extraArgs: promscrape.streamParse: "true" promscrape.maxScrapeSize: 50MB promscrape.maxDroppedTargets: "5000" promscrape.dropOriginalLabels: "false" loggerTimezone: Europe/Moscow promscrape.suppressScrapeErrorsDelay: 5s additionalScrapeConfigs: name: vault-secrets # имя секрета из Vault, где лежит конфигурационный файл key: additional-scrape-configs.yaml remoteWrite: # URL VMSingle (ниже lab — тестовый cluster domain из примера выше). # Имя `vmsingle-k8s` — это пример для релиза с именем `k8s` (обычно шаблон: `<component>-<releaseName>`). # В вашем случае подставьте фактическое имя сервиса/CR или задайте `fullnameOverride`. - url: "http://vmsingle-k8s.mon.svc.lab:8428/api/v1/write" volumes: - name: node-exporter-targets configMap: name: k8s-vmagent-targets-node-exporter # `k8s` — пример префикса из `fullnameOverride` (или имени Helm-релиза) volumeMounts: - mountPath: /etc/vmagent/targets/node-exporter name: node-exporter-targets
Генерация секрета для etcd
kubectl create secret --namespace mon generic etcd-secret \ --from-file=etcd-client-ca.crt=/etc/kubernetes/pki/etcd/ca.crt \ --from-file=etcd-client.key=/etc/kubernetes/pki/etcd/peer.key \ --from-file=etcd-client.crt=/etc/kubernetes/pki/etcd/peer.crt
Секрет additional-scrape-configs.yaml из Vault
- job_name: 'node-exporter' # node exporter использует basic auth для доступа к эндпоинту :9100/metrics basic_auth: username: 'username' password: 'password' honor_labels: true file_sd_configs: - files: - /etc/vmagent/targets/node-exporter/*.yaml
Целевые группы для VMAgent из lab_values.yaml
targetGroups: node-exporter: - address: "192.168.20.2:9102" labels: host: "lab-01"

configMap для volumes cобирается из шаблона. configmap.yaml находится в директории templates нашего чарта.

configmap.yaml
{{- range $name, $targets := .Values.targetGroups }} --- apiVersion: v1 kind: ConfigMap metadata: name: {{ $.Release.Name }}-vmagent-targets-{{ $name }} labels: app: {{ $.Release.Name }}-vmagent data: targets-{{ $name }}.yaml: | {{- range $index, $target := $targets }} {{- if $index }}{{ end }} - targets: [{{ $target.address }}] labels: {{- range $key, $value := $target.labels }} {{ $key }}: {{ $value }} {{- end }} {{- end }} {{- end }}

Добавим в конфигурационный файл сбор метрик с etcd, scheduler, controllermanager. VM Operator создаст ресурс VMServiceScrape для каждого компонента.

Конфигурация из lab_values.yaml
kubeEtcd: # Скрейпинг метрик etcd enabled: true endpoints: #[ ] - 192.168.1.3 # Адрес(а) Ваших control-plane нод service: enabled: true port: 2379 targetPort: 2379 selector: component: etcd vmScrape: spec: jobLabel: jobLabel namespaceSelector: matchNames: [kube-system] endpoints: - port: http-metrics scheme: https tlsConfig: insecureSkipVerify: false caFile: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" # Секрет etcd, прописанный в конфигурации vmagent certFile: "/etc/vm/secrets/etcd-secret/etcd-client.crt" keyFile: "/etc/vm/secrets/etcd-secret/etcd-client.key" kubeScheduler: # Скрейпинг метрик kube-scheduler endpoints: - 192.168.1.3 # Адрес(а) Ваших control-plane нод vmScrape: spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token port: http-metrics scheme: https tlsConfig: caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecureSkipVerify: false serverName: kubernetes kubeControllerManager: # Скрейпинг метрик kube-controller-manager endpoints: - 192.168.1.3 # Адрес(а) Ваших control-plane нод vmScrape: spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token port: http-metrics scheme: https tlsConfig: caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecureSkipVerify: false serverName: kubernetes
Настройка алертинга

VMAlert — компонент для обработки алертов.Alertmanager — система управления оповещениями. Занимается дедупликацией, группировкой и маршрутизацией уведомлений в нужные каналы.

Настроим VMAlert, Alertmanager, правила для мониторинга и отправку сообщений в Telegram.

Конфигурация из lab_values.yaml
alertmanager: # Конфигурация Alertmanager для обработки алертов enabled: true monzoTemplate: enabled: false config: global: resolve_timeout: 3m route: receiver: blackhole group_by: [alertname, severity] group_wait: 30s group_interval: 1m repeat_interval: 8737h routes: - matchers: - severity="critical" receiver: telegram-critical continue: true - matchers: - alertname="Watchdog" - alertname="InfoInhibitor" receiver: blackhole receivers: - name: telegram-critical telegram_configs: - bot_token: "" # Токен вашего телеграм чата chat_id: # ID вашего телеграм чата send_resolved: true parse_mode: MarkdownV2 # Можно также: HTML disable_notifications: false message_thread_id: 4 # ID топика Telegram-группы (если используете) - name: blackhole templateFiles: # Шаблоны для Alertmanager (например, для форматирования сообщений) telegram.tmpl: "" # Сокращено для краткости. Можно в markdown/html. vmalert: # Конфигурация VMAlert для обработки правил алертинга annotations: {} enabled: true

Настроим алерты, используя ресурс VictoriaMetrics Operator — VMRule.

Конфигурация ресурса VMRule из nodeexporter_rule.yaml
apiVersion: operator.victoriametrics.com/v1beta1 kind: VMRule metadata: name: k8s-stack-node-exporter namespace: mon spec: groups: - name: node-exporter # Имя группы params: {} # Параметры rules: # ... полные правила опущены
Настройка Grafana

Grafana — это платформа для сбора, мониторинга и визуализации данных.

Grafana разворачивается через Grafana Operator.Настроим следующие ресурсы:

  • Grafana
  • GrafanaFolder
  • GrafanaDatasource
  • GrafanaDashboard

GrafanaFolder и GrafanaDatasource создаются из шаблонов в директории templates/ нашего чарта. Для GrafanaDashboard это нецелесообразно, потому что количество строк JSON может быть огромным.

Конфигурация из lab_values.yaml
grafana: # Конфигурация Grafana enabled: true ingress: host: grafana.lab.local folders: - name: victoria-metrics # имя папки permissions: - role: Admin # в данном варианте пользователи с правами viewers не увидят ее permission: 4 - role: Editor permission: 2 - name: infra # директория доступна всем - name: node-exporter # можно создавать поддиректории parentFolder: infra datasources: # список источников данных для Grafana - name: prometheus access: proxy type: prometheus datasourceName: VictoriaMetrics # Если не хотите завязываться на FQDN, можно использовать просто http://<service>:<port> внутри namespace. url: http://vmsingle-k8s.mon.svc.lab:8428 isDefault: true - name: alertmanager access: proxy type: alertmanager datasourceName: Alertmanager url: http://vmalertmanager-k8s.mon.svc.lab:9093 jsonData: implementation: prometheus handleGrafanaManagedAlerts: false

Шаблоны для ресурсов Grafana, GrafanaFolder, GrafanaDatasource.

Секреты для пользователя admin тянутся из Vault.

Файл grafana-core.yaml
{{- if .Values.grafana.enabled -}} apiVersion: grafana.integreatly.org/v1beta1 kind: Grafana metadata: name: grafana labels: dashboards: "grafana" spec: config: log: mode: "console" deployment: spec: template: spec: containers: - name: grafana image: docker.io/grafana/grafana:12.0.0 env: - name: GF_SECURITY_ADMIN_USER valueFrom: secretKeyRef: key: admin-user name: vault-secrets - name: GF_SECURITY_ADMIN_PASSWORD valueFrom: secretKeyRef: key: admin-password name: vault-secrets volumeMounts: - mountPath: /opt/secrets/ name: grafana-secrets readOnly: false volumes: - name: grafana-secrets secret: secretName: vault-secrets ingress: spec: ingressClassName: nginx rules: - host: {{ .Values.grafana.ingress.host }} http: paths: - backend: service: name: grafana-service port: number: 3000 path: / pathType: Prefix {{- end }}
Файл grafana-datasource.yaml
{{- if .Values.grafana.enabled -}} {{- range .Values.grafana.datasources }} --- apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDatasource metadata: name: {{ .name }} spec: instanceSelector: matchLabels: dashboards: grafana datasource: access: {{ .access }} type: {{ .type }} name: {{ .datasourceName }} url: {{ .url }} {{- if .isDefault }} isDefault: {{ .isDefault }} {{- end }} {{- if .jsonData }} jsonData: {{- range $index, $target := .jsonData}} {{ $index }}: {{ $target }} {{- end }} {{- end }} {{- end }} {{- end }}
Файл grafana-folder.yaml
{{- if .Values.grafana.enabled -}} {{- range .Values.grafana.folders }} --- apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaFolder metadata: name: {{ .name }} namespace: {{ $.Release.Namespace }} spec: title: {{ .name }} instanceSelector: matchLabels: dashboards: "grafana" {{- if .parentFolder }} parentFolderRef: {{ .parentFolder }} {{- end }} {{- if .permissions }} permissions: | { "items": [ {{- range $index, $target := .permissions }} {{- if $index }},{{ end }} { "role": "{{ .role }}", "permission": {{ .permission }} } {{- end }} ] } {{- end }} {{- end }} {{- end }}
Конфигурация ресурса GrafanaDashboard из nodeexporter_dashboard.yaml
apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: node-exporter namespace: mon spec: folderRef: infra # директория из ресурса GrafanaFolder instanceSelector: matchLabels: dashboards: "grafana" # лейбл, по которому grafana определяет дашборды, настраиваем в файле grafana-core json: | # ... здесь JSON дашборда или ссылка на файл
Настройка VMAuth

VMAuth — это прокси-сервер с функциями аутентификации, маршрутизации и балансировки нагрузки для системы мониторинга VictoriaMetrics. Он обеспечивает безопасный доступ к данным и распределяет нагрузку между серверами. Мы настраиваем его в extraObjects для аутентификации.

Секреты для пользователей тянутся из Vault.

Пример настройки доступа для компонентов VMSingle и VMAgent:

Конфигурация из lab_values.yaml
extraObjects: - apiVersion: operator.victoriametrics.com/v1beta1 kind: VMAuth # Аутентификация для VM metadata: name: lab namespace: mon spec: ingress: annotations: nginx.ingress.kubernetes.io/client-body-buffer-size: 2m class_name: nginx host: vmauth.lab.local selectAllByDefault: true - apiVersion: operator.victoriametrics.com/v1beta1 kind: VMUser # Пользователь для VMSingle metadata: name: admin-vmsingle namespace: mon spec: username: admin passwordRef: name: vault-secrets key: vmsingle-password targetRefs: - crd: kind: VMSingle # Имя `vmsingle-k8s` — пример; подставьте фактическое имя VMSingle в вашем кластере. name: vmsingle-k8s namespace: mon paths: [ "/.*" ] - apiVersion: operator.victoriametrics.com/v1beta1 kind: VMUser # Пользователь для VMAgent metadata: name: admin-vmagent namespace: mon spec: username: admin-vmagent passwordRef: name: vault-secrets key: vmagent-password targetRefs: - crd: kind: VMAgent # Имя `vmagent-k8s` — пример; подставьте фактическое имя VMAgent в вашем кластере. name: vmagent-k8s namespace: mon paths: [ "/.*" ]

Чтобы helm распарсил extraObjects, создадим файл extraobjects.yaml в директории templates нашего целевого чарта.

Файл extraobjects.yaml
{{ range .Values.extraObjects }} --- {{ tpl (toYaml .) $ }} {{ end }}
Настройка x509-certificate-exporter

x509-certificate-exporter следит за сертификатами в кластере. Мы настраиваем его для control-plane-нод и worker-нод, чтобы мониторить файлы.

Конфигурация из lab_values.yaml
x509-certificate-exporter: # Экспортер для мониторинга сертификатов hostPathsExporter: daemonSets: cp: # Для control-plane нод nodeSelector: node-role.kubernetes.io/control-plane: "" tolerations: - effect: NoSchedule key: node-role.kubernetes.io/control-plane operator: Exists watchFiles: # Пути расположения сертификатов k8s - /var/lib/kubelet/pki/kubelet-client-current.pem - /etc/kubernetes/pki/apiserver.crt - /etc/kubernetes/pki/apiserver-etcd-client.crt - /etc/kubernetes/pki/apiserver-kubelet-client.crt - /etc/kubernetes/pki/ca.crt - /etc/kubernetes/pki/front-proxy-ca.crt - /etc/kubernetes/pki/front-proxy-client.crt - /etc/kubernetes/pki/etcd/ca.crt - /etc/kubernetes/pki/etcd/healthcheck-client.crt - /etc/kubernetes/pki/etcd/peer.crt - /etc/kubernetes/pki/etcd/server.crt watchKubeconfFiles: # Kubeconfig файлы - /etc/kubernetes/admin.conf - /etc/kubernetes/controller-manager.conf - /etc/kubernetes/scheduler.conf nodes: # Для worker нод tolerations: - effect: NoSchedule key: node-role.kubernetes.io/ingress operator: Exists watchFiles: # Пути расположения сертификатов k8s - /var/lib/kubelet/pki/kubelet-client-current.pem - /etc/kubernetes/pki/ca.crt
Мониторинг внешних сервисов

Blackbox Exporter — это инструмент мониторинга, являющийся частью экосистемы Prometheus, предназначенный для проверки доступности и работоспособности сетевых сервисов.

Настроим blackbox-exporter.

Конфигурация из lab_values.yaml
prometheus-blackbox-exporter: configExistingSecretName: "vault-secrets"
Сокращенный секрет blackbox.yaml из Vault
modules: http_2xx: prober: http timeout: 30s http: valid_http_versions: ["HTTP/1.1", "HTTP/2", "HTTP/2.0"] valid_status_codes: [200] # Defaults to 2xx method: GET no_follow_redirects: false fail_if_ssl: false fail_if_not_ssl: false tls_config: insecure_skip_verify: true preferred_ip_protocol: "ip4" # defaults to "ip6"

VMProbe — это компонент VictoriaMetrics Operator, предназначенный для настройки конфигураций проб (проверок) целевых объектов с использованием blackbox exporter.

Файл lab_host.yaml
apiVersion: operator.victoriametrics.com/v1beta1 kind: VMProbe metadata: name: lab spec: jobName: blackbox # Имя джобы VMAgent vmProberSpec: url: prometheus-blackbox-exporter.mon.svc.lab:9115 # URL к Blackbox Exporter module: http_2xx # Модуль проверки (HTTP 2xx статус) targets: staticConfig: labels: # Лейблы для метрик module: http_2xx project: lab targets: # Список URL для проверки - https://lab.test.local interval: 15s
Установка чарта

Структура рабочей директории:

main/ charts/ grafana-operator-v0.0.0.tgz prometheus-blackbox-exporter-0.0.0.tgz victoria-metrics-k8s-stack-0.0.0.tgz x509-certificate-exporter-0.0.0.tgz templates/ configmap.yaml extraobjects.yaml grafana-core.yaml grafana-datasource.yaml grafana-folder.yaml Chart.yaml lab_values.yaml files/ grafana-dashboards/ nodeexporter_dash.yaml rules/ nodeexporter_rule.yaml probes/ lab_host.yaml
# Установка чарта с именем 'monitoring' в namespace 'mon', используя values из lab_values.yaml helm install monitoring . -n mon -f lab_values.yaml # либо helm upgrade -i monitoring . -n mon -f lab_values.yaml

Файлы из директории files/ применяем через kubectl apply -f ....

В продакшене мы используем Argo CD: у нас всё автоматизировано, ручного труда минимум — чего и вам советуем.

Заключение

Мы рассмотрели процесс установки и настройки стека мониторинга с VictoriaMetrics, но у каждого из вас наверняка есть свои секреты по настройке. Поделитесь в комментариях.Интересно услышать мнение тех, кто перешёл с других систем мониторинга на VictoriaMetrics — поделитесь своим опытом миграции.

Обмен опытом — ключ к профессиональному росту!

Читать на сайте источника »