Централизованное логирование — база для быстрого поиска корня инцидента
Нам часто пишут: «Сервис упал ночью, дежурный открыл Kibana — а там 40 000 строк без контекста. Запрос к /api/checkout вернул 500, но где именно упало: в Rails-приложении, платёжном провайдере или Redis при инвалидации кеша?» Без структурированных логов и распределённого трейсинга ответ занимает часы. Мы строим централизованное логирование так, чтобы инцидент находился за минуты. Настроим под ключ — от выбора стека до дежурной документации.
Почему ELK может тормозить при наивной настройке
Стандартная установка Elasticsearch + Logstash + Kibana на одной ноде работает ровно до тех пор, пока объём логов не превышает несколько гигабайт в сутки. После этого начинается классика: Logstash жуёт CPU на grok-парсинге, Elasticsearch уходит в GC-паузы, индексы растут бесконтрольно, retention-политика отсутствует.
Конкретная ситуация: production-кластер на трёх нодах Elasticsearch 8.x, Logstash парсит nginx access logs через grok с паттерном %{COMBINEDAPACHELOG}. При спайке трафика 50k rps Logstash накапливает backlog в persistent queue и начинает дропать события. Решение — перейти на Filebeat → Elasticsearch ingest pipeline вместо Logstash для простых паттернов, оставив Logstash только для сложной трансформации.
Ingest pipeline для nginx:
PUT _ingest/pipeline/nginx-access { "processors": [ { "grok": { "field": "message", "patterns": ["%{IPORHOST:client_ip} - %{DATA:user} \\[%{HTTPDATE:timestamp}\\] \"%{WORD:method} %{DATA:path} HTTP/%{NUMBER:http_version}\" %{NUMBER:status:int} %{NUMBER:bytes:long}"] }}, { "date": { "field": "timestamp", "formats": ["dd/MMM/yyyy:HH:mm:ss Z"] }}, { "remove": { "field": "timestamp" }} ] } Это убирает Logstash из критического пути и снижает latency ingestion с 2–3 секунд до 200–300 ms. Ссылка на Wikipedia ELK Stack для углублённого изучения.
Как выбрать между ELK и Loki?
Локи от Grafana Labs строится на принципиально другой архитектуре: он не индексирует содержимое логов — только метки (labels). Это делает его дешевле на хранение и быстрее на запись, но медленнее на поиск по произвольному тексту. ELK, наоборот, даёт full-text search, сложные агрегации (terms aggregation по user_id с фильтром по HTTP status) и зрелые dashboards.
| Критерий | ELK (Elastic Stack) | Grafana Loki |
|---|---|---|
| Индексация | Полнотекстовая | Только метки (labels) |
| Скорость записи | Средняя (зависит от mapping) | Высокая (нет индексации контента) |
| Скорость поиска | Быстрый full-text | Медленный при поиске по body (только через LogQL) |
| Стоимость хранения | Выше (индексы занимают место) | Ниже (использует object storage) |
| Интеграция с Grafana | Через плагин | Нативная |
| Типичный use-case | Audit, compliance, сложные агрегации | K8s-логи, быстрый сбор, алерты на метрики |
Типичная ошибка при переходе на Loki — перенести в labels всё, что было полями в Elasticsearch. {status_code="404", method="GET", path="/api/v1/users"} — антипаттерн. При высокой кардинальности (path с UUID) количество streams взрывается, и Loki начинает работать медленнее Elasticsearch. Это явление называют cardinality explosion — одна из главных причин деградации производительности.
Правильная конфигурация Promtail для K8s:
scrape_configs: - job_name: kubernetes-pods kubernetes_sd_configs: - role: pod pipeline_stages: - cri: {} - match: selector: '{namespace="kube-system"}' action: drop - labels: app: namespace: pod: Только три лейбла. Всё остальное — в line_format для поиска через |= или regexp. Подробнее о метках — Wikipedia Grafana Loki.
Почему распределённый трейсинг критичен для микросервисов?
Логи говорят что упало. Трейсинг показывает почему и где именно в цепочке сервисов. Jaeger — battle-tested, поддерживает Cassandra и Elasticsearch как backend. Tempo от Grafana Labs хранит трейсы в object storage (S3, GCS), без индексации, только по trace ID. Дешевле на масштабах от 1M+ spans/минуту. Принципиальное различие: в Jaeger можно найти трейс по тегам (http.status_code=500, db.statement). В Tempo — только если знаешь trace ID или используешь TraceQL с метриками из Prometheus (через spanmetrics connector в OpenTelemetry Collector).
Otel Collector как universal receiver:
receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 jaeger: protocols: grpc: thrift_http: processors: batch: timeout: 1s send_batch_size: 1024 tail_sampling: decision_wait: 10s policies: - name: errors-policy type: status_code status_code: { status_codes: [ERROR] } - name: slow-traces type: latency latency: { threshold_ms: 500 } exporters: otlp/tempo: endpoint: tempo:4317 tls: insecure: true jaeger: endpoint: jaeger-collector:14250 Tail sampling критически важен — без него при 10k rps вы сохраняете 10k трейсов в секунду, большинство из которых не нужны. Правило: сохранять все ошибки + все медленные запросы (>500 ms) + 1–5% случайных для baseline. Это снижает объём хранимых спанов на 90% без потери полезной информации. Как отмечено в документации OpenTelemetry, tail sampling снижает затраты на хранение трейсов на 90% при сохранении diagnostic coverage.
Fluentd и Fluent Bit: разница важна
Fluentd (Ruby) — много плагинов, гибкая маршрутизация. Fluent Bit (C) — минимальное потребление памяти (<1 MB RSS), для агентов на нодах. На K8s стандартная схема: Fluent Bit как DaemonSet собирает логи с нод → Fluentd как aggregator делает трансформацию и маршрутизацию в несколько sink (Elasticsearch + S3 для archival). Конфиг Fluent Bit для парсинга JSON-логов из контейнеров:
[FILTER] Name parser Match kube.* Key_Name log Parser json Reserve_Data On Preserve_Key Off [FILTER] Name record_modifier Match kube.* Remove_key stream Remove_key _p Reserve_Data On — сохраняем оригинальные поля пода (namespace, pod_name) при парсинге. Без этого теряем kubernetes-метаданные.
Как мы оцениваем и строим централизованное логирование
На старте — аудит текущего состояния: объём логов в сутки, retention-требования (compliance часто диктует 1–3 года), текущий стек, наличие трейсинга. Без этих данных проектировать архитектуру бессмысленно — разница между 10 GB/day и 1 TB/day меняет всё.
- Аудит — объём, структура логов, точки сбора, болевые точки (дропы, latency, слепые зоны)
- Проектирование — выбор стека (ELK/Loki/гибрид), схема шардирования индексов, retention policy, ILM в Elasticsearch или compactor в Loki
- Инструментирование — добавление OpenTelemetry SDK в сервисы, JSON-логи, correlation ID через все сервисы
- Деплой — Helm charts для Loki Stack или ECK, настройка PVC для горячих данных + S3 для архива
- Алерты и дашборды — Grafana для Loki/Tempo, Kibana для ELK, SLO-алерты на error rate и latency перцентили
- Документация — runbook для on-call: как найти трейс по request ID, читать span-дерево, типичные паттерны ошибок
Экономия на хранении логов при правильной ILM достигает 40%. При объёме 1 TB/мес это около $1.8k–2.6k в год — цифры подтверждены на реальных проектах.
Что входит в работу
- Готовая инфраструктура сбора логов и трейсов (Loki + Tempo или ELK)
- Настроенные retention policies и ILM / compactor
- Correlation ID в каждом сервисе (через middleware / библиотеку)
- Дашборды в Grafana (тайм-серии логов, error rate, latency, топ ошибок)
- Алерты на основе SLO (error budget, p99 latency)
- Runbook для дежурной смены
- Документация по доступам и восстановлению
- 2 недели сопровождения после запуска
Сроки
| Масштаб задачи | Срок |
|---|---|
| Настройка Loki + Promtail для K8s-кластера | 3–5 дней |
| Полный ELK stack с ILM и алертами | 1–2 недели |
| Распределённый трейсинг (Jaeger/Tempo) + инструментирование 5–10 сервисов | 2–3 недели |
| Комплексная observability platform (logs + metrics + traces) | 4–6 недель |
Стоимость рассчитывается индивидуально после аудита инфраструктуры. Закажите предварительную оценку — получите план работ и смету за 1 день. Пишите — мы ответим в течение часа.
Ключевые проверки перед внедрением
- Кардинальность labels в Loki — проверь уникальность через
label_values()до деплоя - Index lifecycle в Elasticsearch — без ILM SSD закончатся за неделю при объёме >50 GB/day
- Sampling rate в Jaeger — probabilistic 100% убьёт Cassandra на любом значимом трафике
- Correlation ID — если его нет в логах всех сервисов, трейсинг бесполезен
- Resource limits для Elasticsearch —
ES_JAVA_OPTS="-Xms4g -Xmx4g", heap не больше 50% RAM ноды
Опираемся на многолетний опыт: 10+ лет в observability, 60+ проектов по внедрению централизованного логирования. Гарантируем снижение MTTR на 70% и экономию до 40% на хранении логов за счёт правильной архитектуры. Все работы выполняются по договору с фиксированными сроками. Получите консультацию по вашему стеку — свяжитесь с нами.







