Логирование: ELK stack
ELK stack (Elasticsearch + Logstash + Kibana) — платформа централизованного сбора, хранения и визуализации логов со всех сервисов в едином интерфейсе.
Зачем нужно
При наличии нескольких сервисов или серверов ручной просмотр логов через SSH на каждом становится неудобным. ELK собирает логи в одном месте: поиск по всем сервисам одновременно, фильтрация, дашборды, алерты. Стандарт для enterprise и крупных проектов.
Где используется
- Централизованный сбор логов из Docker-контейнеров, Kubernetes, серверов
- Поиск по логам всех микросервисов из единого интерфейса Kibana
- Анализ паттернов ошибок и аномалий
- Дебаггинг распределённых запросов через trace ID
Основной контент
Компоненты стека
Приложение/Сервер → Filebeat/Logstash → Elasticsearch → Kibana
(генерирует логи) (сбор и парсинг) (хранение) (UI поиск)
| Компонент | Роль |
|---|---|
| Elasticsearch | Поисковое хранилище данных |
| Logstash | ETL: сбор, трансформация, отправка логов |
| Kibana | Web UI для поиска и дашбордов |
| Filebeat | Лёгкий агент сбора логов (альтернатива Logstash на хостах) |
| Fluentd | Альтернатива Logstash, популярен в Kubernetes |
ELK через docker-compose
# docker-compose.elk.yml
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
environment:
- discovery.type=single-node
- ELASTIC_PASSWORD=changeme
- xpack.security.enabled=true
volumes:
- esdata:/usr/share/elasticsearch/data
ports:
- "9200:9200"
kibana:
image: docker.elastic.co/kibana/kibana:8.12.0
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- ELASTICSEARCH_USERNAME=kibana_system
- ELASTICSEARCH_PASSWORD=changeme
ports:
- "5601:5601"
depends_on:
- elasticsearch
logstash:
image: docker.elastic.co/logstash/logstash:8.12.0
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
depends_on:
- elasticsearch
volumes:
esdata:
Конфиг Logstash
# logstash.conf
input {
beats {
port => 5044 # принимает от Filebeat
}
}
filter {
# Парсинг JSON-логов Node.js
if [message] =~ /^\{/ {
json {
source => "message"
}
}
# Добавить геолокацию по IP
geoip {
source => "clientip"
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "myapp-logs-%{+YYYY.MM.dd}"
user => "elastic"
password => "changeme"
}
}
Filebeat на сервере/в контейнере
# filebeat.yml
filebeat.inputs:
- type: log
paths:
- /var/log/myapp/*.log
json.keys_under_root: true # парсить JSON-логи
json.add_error_key: true
- type: container
paths:
- /var/lib/docker/containers/*/*.log
output.logstash:
hosts: ["logstash:5044"]
Более простая альтернатива: Loki + Grafana
Для небольших проектов Grafana Loki значительно легче ELK:
# docker-compose.loki.yml
services:
loki:
image: grafana/loki:latest
ports:
- "3100:3100"
promtail:
image: grafana/promtail:latest
volumes:
- /var/log:/var/log
- ./promtail-config.yml:/etc/promtail/config.yml
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
Частые ошибки
- Запускать Elasticsearch с 512MB heap — минимально рекомендуется 2GB (
ES_JAVA_OPTS=-Xms2g -Xmx2g) - Хранить все логи в одном индексе без rotation — индекс растёт неограниченно
- Логировать в ELK вместо
console.logнапрямую из кода — правильно: файл/stdout → Filebeat → ELK - Не настроить index lifecycle management (ILM) — диск заполняется старыми логами
Связанные темы
- _MOC DevOps
- Логи -- просмотр и анализ
- Мониторинг -- Prometheus и Grafana
- APM -- Application Performance Monitoring