Централізоване логування: чому це критично для веб-застосунків
Після чергового інциденту на продакшені з 5xx помилками ми витратили 3 години, перебираючи логи на десяти серверах. Це повторювалося щомісяця. Коли веб-застосунок обслуговує тисячі користувачів, логи генеруються у величезних обсягах — до 50 ГБ на день на 10 серверах. Без централізації знайти помилку — як голку в копиці сіна. ELK Stack вирішує цю проблему: всі логи стікаються в єдине сховище з пошуком за секунди. У нашій практиці час інциденту скорочується на 70% після впровадження ELK. Алерти в Telegram сигналізують про 5xx, повільні запити, помилки застосунку. Ми беремо на себе повний цикл: від розгортання Elasticsearch до дашбордів і алертів. Строк — від 2 до 7 днів залежно від складності.
Як ELK Stack вирішує проблеми збору та аналізу логів?
ELK — це зв'язка Elasticsearch (зберігання та пошук), Logstash (парсинг та трансформація) і Kibana (візуалізація). Filebeat доставляє логи з серверів. У результаті ви отримуєте єдину точку входу для всіх логів, що значно спрощує моніторинг логів та пошук помилок.
Вибір схеми: ELK vs EFK vs без Logstash
| Схема | Складність | Продуктивність | Гнучкість |
|---|---|---|---|
| ELK | Висока | Середня | Висока |
| EFK | Середня | Вища | Середня |
| Без Logstash | Низька | Висока | Низька |
Logstash виграє в можливостях: парсить старі формати логів за допомогою grok, збагачує дані (geoip, useragent). У 80% проектів використовуємо його. Однак Ingest Pipelines Elasticsearch швидші: обробляють до 15 000 подій/с — у 3 рази більше, ніж Logstash (5 000). Але Logstash справляється з неструктурованими даними, де Ingest безсилий.
Як ми налаштовуємо ELK під ваш проект
Docker Compose для тестового середовища
Використовуємо такий compose-файл:
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0
environment:
- discovery.type=single-node
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=false
- ELASTIC_PASSWORD=changeme
- "ES_JAVA_OPTS=-Xms2g -Xmx2g"
volumes:
- esdata:/usr/share/elasticsearch/data
ports:
- "9200:9200"
ulimits:
memlock:
soft: -1
hard: -1
kibana:
image: docker.elastic.co/kibana/kibana:8.13.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.13.0
volumes:
- ./logstash/pipeline:/usr/share/logstash/pipeline
- ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml
ports:
- "5044:5044"
- "5000:5000"
depends_on:
- elasticsearch
volumes:
esdata:
Logstash Pipeline: парсинг Nginx access та JSON-логів
input {
beats { port => 5044 }
tcp { port => 5000; codec => json_lines }
}
filter {
if [fields][log_type] == "nginx_access" {
grok { match => { "message" => '%{IPORHOST:client_ip} - %{DATA:user} \[%{HTTPDATE:timestamp}\] "%{WORD:method} %{DATA:request} HTTP/%{NUMBER:http_version}" %{NUMBER:status_code:int} %{NUMBER:bytes_sent:int} "%{DATA:referrer}" "%{DATA:user_agent}" %{NUMBER:request_time:float}' } }
date { match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]; target => "@timestamp" }
geoip { source => "client_ip"; target => "geoip" }
useragent { source => "user_agent"; target => "ua" }
mutate { remove_field => ["message", "timestamp"] }
}
if [fields][log_type] == "app_json" {
json { source => "message"; target => "app" }
mutate { remove_field => ["message"] }
}
}
output {
if [fields][log_type] == "nginx_access" {
elasticsearch { hosts => ["http://elasticsearch:9200"]; user => "elastic"; password => "changeme"; index => "nginx-access-%{+YYYY.MM.dd}" }
} else {
elasticsearch { hosts => ["http://elasticsearch:9200"]; user => "elastic"; password => "changeme"; index => "app-logs-%{+YYYY.MM.dd}" }
}
}
Відправка логів з Laravel
Через кастомний Monolog handler:
class LogstashLogger
{
public function __invoke(array $config): Logger
{
$handler = new SocketHandler("tcp://{$config['host']}:{$config['port']}");
$handler->setFormatter(new JsonFormatter());
return new Logger('app', [$handler]);
}
}
Тепер Log::error(...) відправляє JSON напряму в Logstash.
На одному з проектів з навантаженням 10 000 RPS ми налаштували кластер Elasticsearch з 3 нод з ILM і Logstash з grok-патернами для парсингу специфічних логів застосунку. В результаті час пошуку помилки скоротився з 40 хвилин до 10 секунд. Це дозволило команді швидше реагувати на інциденти та знизити середній час відновлення (MTTR) на 65%.
Чому ILM обов'язковий?
Без ILM індекси неконтрольовано ростуть, і через місяць диск забитий. Налаштовуємо політику: hot (5 ГБ або 1 день) → warm (3 дні) → cold (30 днів) → delete (90 днів). Все через шаблон індексу. Це основа економічного зберігання логів. Додатково можна налаштувати rollover за розміром або віком, щоб уникнути перевантаження вузлів.
Продуктивність Elasticsearch: поради з практики
- Heap — не більше 50% RAM і не більше 31 ГБ (через compressed oops)
- Кількість шардів: 1 шард ≈ 20–40 ГБ даних. Oversharding — часта помилка
- Slow log:
index.search.slowlog.threshold.query.warn: 2s - Заборона свопу:
bootstrap.memory_lock: true
Порівняння: Logstash vs Ingest Pipelines
| Параметр | Logstash | Ingest Pipelines |
|---|---|---|
| Продуктивність | ~5 тис. подій/с | ~15 тис. подій/с |
| Гнучкість | Grok, enrich, маршрутизація | Тільки прості парсинги |
| Складність | Потребує налаштування сервера | Вбудований в ES |
Для складних трансформацій Logstash незамінний. Вбудовані pipeline-процесори справляються з типовими завданнями, але не вміють працювати з довільними текстовими патернами.
Що входить у налаштування ELK
- Розгортання кластера Elasticsearch з оптимальними налаштуваннями (шарди, ILM, безпека)
- Конфігурація Logstash для парсингу Nginx, PHP і прикладних логів
- Підключення Filebeat на всіх серверах
- Створення дашбордів у Kibana для моніторингу логів (5xx, latency, traffic)
- Налаштування ILM для економії дискового простору
- Інтеграція алертів у Telegram або Email
- Документація з експлуатації та навчання команди
Процес роботи
- Аналітика — вивчаємо поточні логи, джерела, вимоги до зберігання
- Проєктування — обираємо схему (ELK/EFK), намічаємо ILM і дашборди
- Реалізація — розгортаємо кластер, налаштовуємо конвеєри
- Тестування — перевіряємо надходження даних, алерти, час пошуку
- Деплой — впроваджуємо в продакшен, передаємо документацію
Гарантуємо SLA 99.9% для кластера. Наші інженери мають досвід понад 5 років і реалізували 30+ проєктів. Отримайте консультацію з налаштування ELK під ваш проєкт. Заплануйте впровадження ELK та скоротіть час пошуку помилок.







