2.6 Observability и мониторинг #
🎯 Что такое Observability #
Observability (наблюдаемость) — это способность понимать внутреннее состояние системы на основе знаний о её внешних выходных данных. В DevOps это критически важная практика для поддержания надёжности и производительности приложений.
Три столпа Observability: #
- Метрики (Metrics) — числовые показатели системы
- Логи (Logs) — записи событий в системе
- Трассировка (Traces) — отслеживание запросов через систему
📊 Метрики #
Типы метрик: #
Технические метрики:
- CPU, память, диск, сеть
- Время отклика приложения
- Количество запросов в секунду (RPS)
- Коды ошибок HTTP
Бизнес-метрики:
- Количество пользователей
- Доходы
- Конверсии
Популярные инструменты: #
- Prometheus — сбор и хранение метрик
- VictoriaMetrics — более быстрая альтернатива Prometheus
- Grafana — визуализация данных
- InfluxDB — временные ряды
- Datadog — коммерческое решение
Пример настройки Prometheus: #
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'my-app'
static_configs:
- targets: ['localhost:8080']
metrics_path: /metrics
scrape_interval: 5s
⚠️ “Слепые зоны” метрик: что происходит между точками? #
🔥 ВАЖНО: Большинство не думает об этом, но графики могут врать!
Проблема интерполяции:
Время: 10:00 10:05 10:10 10:15
CPU: 20% 25% 30% 20%
График: ────────────────────────────────────
20% ~~~~ 25% ~~~~ 30% ~~~~ 20%
Что на самом деле могло происходить между 10:05 и 10:10:
Реальность:
10:05 -> 25% CPU
10:06 -> 95% CPU (пик нагрузки!)
10:07 -> 98% CPU (почти предел!)
10:08 -> 40% CPU (нагрузка спала)
10:09 -> 35% CPU
10:10 -> 30% CPU
График покажет: плавный рост с 25% до 30%
Реальность: был критический пик в 95-98%!
Почему это критично: #
- Пропущенные инциденты - алерты не сработали
- Ложное спокойствие - “всё было хорошо”
- Неправильные выводы о производительности
- Недооценка нагрузки на систему
Примеры реальных проблем: #
Случай 1: Memory leak
12:00 -> 2GB RAM
12:15 -> 2.1GB RAM
12:30 -> 2.2GB RAM
График: стабильный рост
Реальность: в 12:20 было 7.8GB (чуть не OOM!)
Случай 2: Database спайки
Query time: 100ms -> 120ms -> 110ms
График: небольшие колебания
Реальность: между точками были запросы по 8 секунд!
Решения: #
1. Уменьшение интервала сбора
# Вместо 15s
scrape_interval: 15s
# Используйте 5s или даже 1s для критических метрик
scrape_interval: 5s
2. Дополнительные метрики
Не ограничивайтесь только средними значениями, которые могут скрывать критические пики нагрузки. Используйте:
- Максимальные значения - покажут реальные пики нагрузки
- 95-й перцентиль - показывает типичную высокую нагрузку
- 99-й перцентиль - помогает обнаружить редкие, но критичные пики
3. Structured logging для деталей
{
"timestamp": "2024-01-15T12:06:30Z",
"level": "WARN",
"message": "High CPU spike detected",
"cpu_percent": 97.5,
"duration_seconds": 30
}
4. Профилирование и трейсинг
# APM инструменты для детального анализа
- Jaeger (трейсинг запросов)
- New Relic (мониторинг производительности приложений)
- DataDog (мониторинг пользователей)
Практический совет: #
Правило “3-х сигм” - если видите странные паттерны на графиках:
- Уменьшите интервал сбора метрик
- Добавьте max/p95/p99 метрики
- Включите детальное логирование
- Используйте профилировщики
💡 Запомните: Графики показывают тренды, но между точками может скрываться ад. Хороший мониторинг = метрики + логи + трейсы!
VictoriaMetrics — более быстрая альтернатива #
VictoriaMetrics — высокопроизводительная система мониторинга, совместимая с Prometheus API, но значительно превосходящая его по скорости и эффективности использования ресурсов.
Преимущества VictoriaMetrics: #
- В 20x быстрее чем Prometheus при записи данных
- В 10x меньше потребление RAM и CPU
- Долгосрочное хранение без внешних зависимостей
- Горизонтальное масштабирование (VictoriaMetrics Cluster)
- Полная совместимость с Prometheus API
- Сжатие данных — до 70% экономии места
Установка VictoriaMetrics: #
# Single node версия
docker run -it --rm -v victoria-metrics-data:/victoria-metrics-data \
-p 8428:8428 \
victoriametrics/victoria-metrics:latest
Миграция с Prometheus: #
# docker-compose.yml
version: '3.8'
services:
victoria-metrics:
image: victoriametrics/victoria-metrics:latest
ports:
- "8428:8428"
volumes:
- vmdata:/victoria-metrics-data
command:
- '--storageDataPath=/victoria-metrics-data'
- '--httpListenAddr=:8428'
- '--retentionPeriod=12' # 12 месяцев хранения
vmagent:
image: victoriametrics/vmagent:latest
ports:
- "8429:8429"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
command:
- '--promscrape.config=/etc/prometheus/prometheus.yml'
- '--remoteWrite.url=http://victoria-metrics:8428/api/v1/write'
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
vmdata:
Grafana настройка для VictoriaMetrics: #
{
"name": "VictoriaMetrics",
"type": "prometheus",
"url": "http://victoria-metrics:8428",
"access": "proxy",
"isDefault": true
}
VictoriaMetrics vs Prometheus: #
Метрика | Prometheus | VictoriaMetrics |
---|---|---|
RAM usage | ~3GB | ~300MB |
CPU usage | ~2 cores | ~0.2 cores |
Disk IOPS | ~1000 | ~100 |
Compression | gzip | zstd (лучше) |
Запросы/сек | ~1000 | ~10000 |
Кластерная версия: #
# VictoriaMetrics Cluster
version: '3.8'
services:
vmstorage:
image: victoriametrics/vmstorage:cluster
ports:
- "8482:8482"
volumes:
- vmstorage:/storage
command:
- '--storageDataPath=/storage'
vminsert:
image: victoriametrics/vminsert:cluster
ports:
- "8480:8480"
depends_on:
- vmstorage
command:
- '--storageNode=vmstorage:8400'
vmselect:
image: victoriametrics/vmselect:cluster
ports:
- "8481:8481"
depends_on:
- vmstorage
command:
- '--storageNode=vmstorage:8401'
volumes:
vmstorage:
📝 Логирование #
Структурированные логи: #
{
"timestamp": "2024-01-15T10:30:00Z",
"level": "ERROR",
"service": "user-service",
"message": "Failed to authenticate user",
"user_id": "12345",
"request_id": "abc-def-123"
}
Централизованное логирование: #
Grafana Loki для логов #
Loki - это система для сбора и запроса логов, разработанная Grafana Labs:
# docker-compose для Loki
version: '3.8'
services:
loki:
image: grafana/loki:latest
ports:
- "3100:3100"
volumes:
- ./loki-config.yml:/etc/loki/loki-config.yml
command: -config.file=/etc/loki/local-config.yaml
promtail:
image: grafana/promtail:latest
volumes:
- /var/log:/var/log:ro
- ./promtail-config.yml:/etc/promtail/config.yml
command: -config.file=/etc/promtail/config.yml
Преимущества Loki #
✅ **Эффективное хранение**: индексирует только метки, не контент
✅ **Grafana интеграция**: native поддержка в Grafana
✅ **LogQL**: мощный язык запросов похожий на PromQL
✅ **Horizontal scaling**: поддержка кластерного развертывания
✅ **Cost effective**: дешевле ELK stack для больших объемов
# Пример LogQL запроса
{job="nginx"} |= "error" | json | status_code >= 400
Grafana Mimir для метрик #
Mimir - высокопроизводительная система хранения метрик:
# Mimir для long-term storage метрик Prometheus
version: '3.8'
services:
mimir:
image: grafana/mimir:latest
ports:
- "9009:9009"
volumes:
- ./mimir.yml:/etc/mimir/mimir.yml
command:
- --config.file=/etc/mimir/mimir.yml
- --target=all
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
command:
- --config.file=/etc/prometheus/prometheus.yml
- --enable-feature=remote-write-receiver
Конфигурация Prometheus для отправки в Mimir #
# prometheus.yml
global:
scrape_interval: 15s
remote_write:
- url: http://mimir:9009/api/v1/push
queue_config:
capacity: 10000
max_shards: 1000
min_shards: 1
max_samples_per_send: 2000
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
Преимущества Mimir #
✅ **Horizontal scaling**: автоматическое масштабирование
✅ **Multi-tenancy**: изоляция данных разных команд
✅ **Long-term storage**: эффективное хранение исторических данных
✅ **Prometheus compatibility**: 100% совместимость с Prometheus API
✅ **Cloud native**: оптимизирован для Kubernetes и облачных хранилищ
ELK Stack (Elasticsearch, Logstash, Kibana):
# docker-compose.yml для ELK
version: '3'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.15.0
environment:
- discovery.type=single-node
ports:
- "9200:9200"
logstash:
image: docker.elastic.co/logstash/logstash:7.15.0
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
ports:
- "5000:5000"
kibana:
image: docker.elastic.co/kibana/kibana:7.15.0
ports:
- "5601:5601"
Альтернативы ELK: #
- Fluentd + OpenSearch
- Loki (от Grafana)
- Splunk (коммерческое)
🔍 Distributed Tracing #
Зачем нужна трассировка: #
- Отслеживание запросов в микросервисах
- Поиск узких мест в производительности
- Понимание зависимостей между сервисами
Популярные решения: #
- Jaeger
- Zipkin
- AWS X-Ray
- OpenTelemetry (стандарт)
Пример интеграции с OpenTelemetry: #
Настройка трассировки для отслеживания запросов:
- Инициализация - настройка поставщика трассировки и создание объекта tracer
- Конфигурация экспорта - подключение к Jaeger для отправки данных трассировки
- Обработка span’ов - настройка batch обработчика для эффективной отправки
- Использование в коде - создание span’ов для отслеживания функций обработки заказов
Эта конфигурация позволяет отслеживать полный путь запроса от валидации до отправки заказа.
🚨 Алертинг #
Принципы качественного алертинга: #
- Не шумите — алерты только на критичные проблемы
- Действенность — каждый алерт должен требовать действий
- Контекст — включайте полезную информацию для решения
- Эскалация — система уведомления по уровням
Пример правил в Prometheus: #
# alert.rules.yml
groups:
- name: example
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.1
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate on {{ $labels.instance }}"
description: "Error rate is {{ $value }} requests per second"
- alert: DiskSpaceLow
expr: disk_free_percent < 10
for: 2m
labels:
severity: warning
annotations:
summary: "Disk space is running low"
Инструменты алертинга: #
- Alertmanager (Prometheus)
- PagerDuty
- Opsgenie
- VictorOps
🏗️ Практический пример: Мониторинг веб-приложения #
1. Настройка метрик в приложении: #
Пример создания Flask приложения с метриками Prometheus:
Приложение выполняет следующие функции:
-
Определение метрик:
- Counter для подсчета общего количества запросов по методам и endpoint’ам
- Histogram для измерения времени отклика запросов
-
Отслеживание запросов:
- Фиксация времени начала обработки запроса
- Увеличение счетчика запросов после обработки
- Запись времени обработки в гистограмму
-
Экспорт метрик:
- Создание endpoint’а /metrics для Prometheus
- Генерация метрик в формате Prometheus
2. Docker Compose для полного стека: #
version: '3.8'
services:
app:
build: .
ports:
- "5000:5000"
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- ./alert.rules.yml:/etc/prometheus/alert.rules.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--web.enable-lifecycle'
grafana:
image: grafana/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-storage:/var/lib/grafana
alertmanager:
image: prom/alertmanager
ports:
- "9093:9093"
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
volumes:
grafana-storage:
✅ Best Practices #
1. SRE подход: #
- SLI (Service Level Indicators) — что измеряем
- SLO (Service Level Objectives) — цели
- SLA (Service Level Agreements) — договоренности
- Error Budget — допустимое количество ошибок
2. Golden Signals: #
- Latency — время отклика
- Traffic — количество запросов
- Errors — количество ошибок
- Saturation — загруженность ресурсов
3. Мониторинг как код: #
# monitoring.tf (Terraform)
resource "aws_cloudwatch_dashboard" "main" {
dashboard_name = "MyApp-Dashboard"
dashboard_body = jsonencode({
widgets = [
{
type = "metric"
properties = {
metrics = [
["AWS/ApplicationELB", "RequestCount"],
["AWS/ApplicationELB", "TargetResponseTime"]
]
period = 300
stat = "Sum"
region = "us-west-2"
title = "Application Metrics"
}
}
]
})
}
🛠️ Альтернативные решения мониторинга #
Zabbix - Enterprise мониторинг #
Zabbix - зрелое enterprise решение для мониторинга инфраструктуры:
# docker-compose для Zabbix
version: '3.8'
services:
zabbix-server:
image: zabbix/zabbix-server-mysql:latest
environment:
- DB_SERVER_HOST=mysql
- MYSQL_DATABASE=zabbix
- MYSQL_USER=zabbix
- MYSQL_PASSWORD=zabbix_password
ports:
- "10051:10051"
depends_on:
- mysql
zabbix-web:
image: zabbix/zabbix-web-nginx-mysql:latest
environment:
- DB_SERVER_HOST=mysql
- MYSQL_DATABASE=zabbix
- MYSQL_USER=zabbix
- MYSQL_PASSWORD=zabbix_password
- ZBX_SERVER_HOST=zabbix-server
ports:
- "8080:8080"
mysql:
image: mysql:8.0
environment:
- MYSQL_DATABASE=zabbix
- MYSQL_USER=zabbix
- MYSQL_PASSWORD=zabbix_password
- MYSQL_ROOT_PASSWORD=root_password
Преимущества Zabbix #
✅ **SNMP мониторинг**: отличная поддержка сетевого оборудования
✅ **Агенты**: мощные агенты для глубокого мониторинга ОС
✅ **Templates**: готовые шаблоны для популярных систем
✅ **Network discovery**: автоматическое обнаружение устройств
✅ **Notifications**: гибкая система уведомлений
SNMP мониторинг сетевого оборудования #
SNMP (Simple Network Management Protocol) для мониторинга железа:
# Установка SNMP tools
sudo apt install snmp snmp-mibs-downloader
# Проверка SNMP доступности
snmpwalk -v2c -c public 192.168.1.1 1.3.6.1.2.1.1.1.0
# Мониторинг интерфейсов
snmpwalk -v2c -c public 192.168.1.1 1.3.6.1.2.1.2.2.1.2
# CPU загрузка на Cisco
snmpget -v2c -c public 192.168.1.1 1.3.6.1.4.1.9.2.1.56.0
# Память на Cisco
snmpget -v2c -c public 192.168.1.1 1.3.6.1.4.1.9.2.1.8.0
Prometheus + SNMP Exporter #
# snmp.yml конфигурация для SNMP exporter
modules:
cisco_router:
walk:
- 1.3.6.1.2.1.2.2.1.2 # Interface names
- 1.3.6.1.2.1.2.2.1.10 # Interface inbound octets
- 1.3.6.1.2.1.2.2.1.16 # Interface outbound octets
- 1.3.6.1.4.1.9.2.1.56 # CPU utilization
metrics:
- name: snmp_cisco_cpu_utilization
oid: 1.3.6.1.4.1.9.2.1.56
type: gauge
- name: snmp_interface_in_octets
oid: 1.3.6.1.2.1.2.2.1.10
type: counter
# prometheus.yml для SNMP мониторинга
scrape_configs:
- job_name: 'snmp'
static_configs:
- targets:
- 192.168.1.1 # Router IP
- 192.168.1.2 # Switch IP
metrics_path: /snmp
params:
module: [cisco_router]
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: snmp-exporter:9116
Мониторинг физических серверов #
# Node Exporter для серверного железа
version: '3.8'
services:
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
restart: unless-stopped
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
- '--collector.textfile.directory=/var/lib/node_exporter/textfile_collector'
- '--collector.systemd'
- '--collector.processes'
ports:
- "9100:9100"
Важные метрики для серверов #
# CPU загрузка
100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# Использование памяти
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
# Использование диска
100 - ((node_filesystem_avail_bytes * 100) / node_filesystem_size_bytes)
# Network I/O
rate(node_network_receive_bytes_total[5m])
rate(node_network_transmit_bytes_total[5m])
# Disk I/O
rate(node_disk_read_bytes_total[5m])
rate(node_disk_written_bytes_total[5m])
# Load Average
node_load1
node_load5
node_load15
🎯 Практические задания #
Задание 1: Базовый мониторинг #
- Поднимите Prometheus и Grafana через Docker Compose
- Создайте простое приложение с метриками
- Настройте дашборд в Grafana
Задание 2: Алертинг #
- Создайте правила алертинга в Prometheus
- Настройте Alertmanager для отправки уведомлений
- Протестируйте срабатывание алертов
Задание 3: Логирование #
- Настройте ELK stack
- Интегрируйте приложение с Logstash
- Создайте поисковые запросы в Kibana
📚 Дополнительные ресурсы #
- Prometheus Documentation
- Grafana Tutorials
- OpenTelemetry
- Site Reliability Engineering Book
- The Art of Monitoring
Следующий раздел: 2.9 GitOps