Когда ваш стек мониторинга перерастает масштаб нескольких серверов, классический Prometheus показывает свои ограничения:
Проблемы с производительностью при миллионах метрик
Вертикальное масштабирование
Сложности с долгосрочным хранением
Ограниченные возможности репликации

Сегодня настроим высокодоступную и масштабируемую систему на основе VictoriaMetrics - современной time-series базы, совместимой с PromQL.
⠀⠀⠀⠀⠀⠀⠀⠀
Архитектура:

⠀⠀⠀⠀⠀⠀⠀⠀
Что получим:
Горизонтальное масштабирование
Автоматическое переключение при сбоях
Эффективное долгосрочное хранение
Совместимость с существующими Prometheus-конфигами
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Шаг 1: Подготовка инфраструктуры
Разворачиваем на 3-х нодах с label monitoring: true:
# k8s/storage-class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp3
iops: "3000"
throughput: "125"
allowVolumeExpansion: true
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Шаг 2: Устанавливаем VictoriaMetrics Cluster
# k8s/victoriametrics/vmstorage.yaml
apiVersion: apps/v1/v1
kind: StatefulSet
metadata:
name: vmstorage
namespace: monitoring
spec:
serviceName: vmstorage
replicas: 3
selector:
matchLabels:
app: vmstorage
template:
metadata:
labels:
app: vmstorage
spec:
containers:
- name: storage
image: victoriametrics/vmstorage:v1.93.4-cluster
args:
- -retentionPeriod=12
- -storageDataPath=/storage
- -envflag.enable=true
- -envflag.prefix=VM_
- -loggerFormat=json
- -clusternativeListenAddr=:8482
ports:
- name: clusternative
containerPort: 8482
- name: http
containerPort: 8482
volumeMounts:
- name: storage
mountPath: /storage
resources:
requests:
memory: 4Gi
cpu: "1"
limits:
memory: 8Gi
cpu: "2"
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
timeoutSeconds: 10
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
timeoutSeconds: 5
volumeClaimTemplates:
- metadata:
name: storage
spec:
storageClassName: fast-ssd
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Gi
# k8s/victoriametrics/vmselect.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vmselect
namespace: monitoring
spec:
replicas: 2
selector:
matchLabels:
app: vmselect
template:
metadata:
labels:
app: vmselect
spec:
containers:
- name: select
image: victoriametrics/vmselect:v1.93.4-cluster
args:
- -envflag.enable=true
- -envflag.prefix=VM_
- -loggerFormat=json
- -clusternativeListenAddr=:8481
- -storageNode=vmstorage-0.vmstorage.monitoring.svc.cluster.local:8482
- -storageNode=vmstorage-1.vmstorage.monitoring.svc.cluster.local:8482
- -storageNode=vmstorage-2.vmstorage.monitoring.svc.cluster.local:8482
ports:
- name: http
containerPort: 8481
resources:
requests:
memory: 2Gi
cpu: "500m"
limits:
memory: 4Gi
cpu: "1"
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
⠀⠀⠀⠀⠀⠀⠀⠀
Шаг 3: Настраиваем VMAgent с продвинутым service discovery
# k8s/victoriametrics/vmagent.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vmagent
namespace: monitoring
spec:
replicas: 2
selector:
matchLabels:
app: vmagent
template:
metadata:
labels:
app: vmagent
spec:
serviceAccountName: vmagent
containers:
- name: agent
image: victoriametrics/vmagent:v1.93.4
args:
- -promscrape.config=/etc/vmagent/scrape.yaml
- -remoteWrite.url=http://vminsert.monitoring.svc.cluster.local:8480/insert/0/prometheus
- -remoteWrite.maxBlockSize=4M
- -remoteWrite.showURL=true
- -promscrape.suppressScrapeErrors=true
- -promscrape.cluster.membersCount=2
- -promscrape.cluster.memberNum=$(POD_INDEX)
- -promscrape.cluster.replicationFactor=1
volumeMounts:
- name: config
mountPath: /etc/vmagent
env:
- name: POD_INDEX
valueFrom:
fieldRef:
fieldPath: metadata.name
apiVersion: v1
resources:
requests:
memory: 1Gi
cpu: "500m"
limits:
memory: 2Gi
cpu: "1"
livenessProbe:
httpGet:
path: /health
port: 8429
---
apiVersion: v1
kind: ConfigMap
metadata:
name: vmagent-config
namespace: monitoring
data:
scrape.yaml: |
global:
scrape_interval: 30s
external_labels:
cluster: 'production'
replica: '$(POD_INDEX)'
scrape_configs:
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
metrics_path: /metrics
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name
# Кастомный job для мониторинга бизнес-метрик
- job_name: 'business-metrics'
static_configs:
- targets: ['business-api:8080']
metrics_path: /actuator/prometheus
scrape_interval: 15s
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Шаг 4: Настройка алертинга с VMAler
# k8s/victoriametrics/vmalert.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vmalert
namespace: monitoring
spec:
replicas: 2
selector:
matchLabels:
app: vmalert
template:
metadata:
labels:
app: vmalert
spec:
containers:
- name: alert
image: victoriametrics/vmalert:v1.93.4
args:
- -datasource.url=http://vmselect.monitoring.svc.cluster.local:8481/select/0/prometheus
- -notifier.url=http://alertmanager.monitoring.svc.cluster.local:9093
- -remoteWrite.url=http://vminsert.monitoring.svc.cluster.local:8480/insert/0/prometheus
- -rule=/etc/vmalert/rules/*.yaml
- -evaluationInterval=30s
- -external.alert.source=VictoriaMetrics
volumeMounts:
- name: rules
mountPath: /etc/vmalert/rules
resources:
requests:
memory: 1Gi
cpu: "500m"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: vmalert-rules
namespace: monitoring
data:
infrastructure.yaml: |
groups:
- name: infrastructure
rules:
- alert: NodeDown
expr: up{job="kubernetes-nodes"} == 0
for: 5m
labels:
severity: critical
tier: infrastructure
annotations:
summary: "Node {{ $labels.instance }} is down"
description: "Node {{ $labels.instance }} has been down for more than 5 minutes"
- alert: HighMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
for: 10m
labels:
severity: warning
annotations:
summary: "High memory usage on {{ $labels.instance }}"
description: "Memory usage is {{ $value | humanize }}%"
business.yaml: |
groups:
- name: business
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100 > 5
for: 5m
labels:
severity: critical
tier: application
annotations:
summary: "High error rate on {{ $labels.service }}"
description: "Error rate is {{ $value | humanize }}%"
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Шаг 5: Настройка Grafana для работы с VMSelect
# k8s/grafana/datasources.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-datasources
namespace: monitoring
data:
victoriametrics.yaml: |
apiVersion: 1
datasources:
- name: VictoriaMetrics
type: prometheus
url: http://vmselect.monitoring.svc.cluster.local:8481/select/0/prometheus
access: proxy
isDefault: true
jsonData:
timeInterval: 30s
queryTimeout: 60s
httpMethod: POST
manageAlerts: true
disableMetricsLookup: false
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Шаг 6: Мониторинг самого мониторинга
# k8s/victoriametrics/self-monitoring.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: vm-self-monitoring
namespace: monitoring
data:
self-scrape.yaml: |
- job_name: 'victoriametrics'
static_configs:
- targets:
- 'vmselect:8481'
- 'vminsert:8480'
- 'vmstorage-0:8482'
- 'vmstorage-1:8482'
- 'vmstorage-2:8482'
- 'vmagent:8429'
- 'vmalert:8880'
metrics_path: /metrics
scrape_interval: 30s
⠀⠀⠀⠀⠀⠀
Проверка работы:
# Проверяем репликацию
kubectl port-forward svc/vmselect 8481:8481 -n monitoring
curl "http://localhost:8481/select/0/prometheus/api/v1/label/__name__/values"
# Смотрим метрики самого VMAgent
curl "http://localhost:8481/select/0/prometheus/api/v1/query?query=vmagent_remotewrite_blocks_sent_total"
# Проверяем алерты
kubectl port-forward svc/vmalert 8880:8880 -n monitoring
curl http://localhost:8880/api/v1/alerts

⠀⠀⠀⠀⠀⠀⠀⠀
Заключение:
Мы развернули высокодоступную, масштабируемую систему мониторинга, которая:
Обрабатывает миллионы метрик в реальном времени
Автоматически распределяет нагрузку между нодами
Обеспечивает отказоустойчивость на всех уровнях
Поддерживает сложные правила алертинга
Интегрируется с существующей экосистемой Prometheus
Такой стек способен выдержать нагрузку крупного production-окружения и предоставляет надежную основу для observability вашей инфраструктуры.

Есть вопросы по тонкой настройке или конкретным кейсам? Пишите в комментариях :-)