Сбор логов с ELK: настройка Filebeat, Logstash, Elasticsearch и Kibana | AdminWiki

Сбор логов с ELK: настройка Filebeat, Logstash, Elasticsearch и Kibana

11 сентября 2026 19 мин. чтения
Содержание статьи

Стек ELK собирает логи с сотен серверов в одно хранилище и позволяет искать по ним за секунды. Компонентов четыре: Filebeat читает лог-файлы на хостах, Logstash обрабатывает и маршрутизирует события, Elasticsearch хранит данные и выполняет поиск, Kibana показывает результат в браузере. Поток данных: Filebeat → Logstash (опционально) → Elasticsearch → Kibana.

За сбор текстовых логов отвечает Filebeat. Это лёгкий агент на Go: держит небольшой буфер в памяти, читает файлы через input типа filestream и отправляет события по сети. Остальные агенты семейства Beats решают другие задачи: Metricbeat снимает метрики, Winlogbeat читает журнал Windows, Heartbeat проверяет доступность сервисов, Packetbeat разбирает сетевой трафик. Ставить Logstash на каждый хост не нужно: это JVM-приложение занимает от 1 ГБ памяти и рассчитано на центральную обработку.

Logstash нужен не всегда. На малых объёмах разбор строк выполнят ingest-ноды Elasticsearch или процессоры самого Filebeat. Logstash подключают там, где нужен сложный grok, несколько источников и приёмников, обогащение внешними данными и буферизация на пиках нагрузки. Ниже рабочие конфигурации для обоих сценариев и критерии выбора.

Зачем нужен централизованный сбор логов и какую роль играет каждый компонент ELK

Пять серверов можно обслуживать руками: ssh, grep, cat. Пятьдесят так не обслуживаются. Приходится помнить, где лежит нужный файл, держать открытыми десяток терминалов и сопоставлять события по времени вручную. Централизованный сбор решает три задачи: хранит логи всех хостов в одном месте, сохраняет их после ротации на сервере и даёт единый поиск по всем источникам.

Роли компонентов:

  • Filebeat - агент на каждом хосте. Читает текстовые логи, stdout контейнеров, journald. Потребляет десятки мегабайт RAM и почти не нагружает CPU.
  • Logstash - обработчик и маршрутизатор. Принимает поток от Beats (beats input, порт 5044), разбирает строки на поля, приводит их к ECS (Elastic Common Schema), раскладывает события по индексам и отправляет в Elasticsearch.
  • Elasticsearch - распределённое хранилище и поисковый движок. Хранит документы в шардах, индексирует их и отвечает на запросы за миллисекунды.
  • Kibana - веб-интерфейс. Поиск в Discover, графики в Lens, дашборды, управление индексами, пользователями и API-ключами.

Схема потока: Filebeat → Logstash → Elasticsearch → Kibana. Logstash в этой цепочке опционален: Filebeat умеет писать напрямую в Elasticsearch, а простой парсинг выполнят ingest-ноды. Отказ от Logstash экономит 1-4 ГБ RAM и один хост.

Если выбираете между Elastic Stack и альтернативами, сначала посмотрите сравнение ELK и Grafana Loki по архитектуре, стоимости и производительности: оно помогает понять, подходит ли классический ELK под ваши объёмы. Дальше речь пойдёт об Elastic Stack 8.x.

Все компоненты Elastic Stack 8.x выходят с единой нумерацией версий. Смешивать Filebeat 9.x с Elasticsearch 8.x нельзя: ломается совместимость API, агент получает ошибки при отправке. Перед развёртыванием сверьте версии командами filebeat version и curl -u elastic localhost:9200.

Какой Beat отвечает за сбор текстовых логов

Текстовые логи собирает Filebeat. В ветке 8.x основной input - filestream, он пришёл на смену устаревшему log. Filestream читает файлы по путям из конфигурации, отслеживает ротацию, хранит позицию в registry-файле и продолжает чтение после перезапуска с того же места. Для systemd-логов в Filebeat есть input journald, поэтому отдельный Journalbeat не нужен: проект закрыт, его функции перешли к Filebeat.

АгентЧто собираетТипичный источник
FilebeatТекстовые логи, stdout контейнеров, journald/var/log/*.log, Docker JSON, systemd
MetricbeatМетрики ОС и сервисовCPU, RAM, Nginx stub_status
WinlogbeatЖурнал событий WindowsApplication, System, Security
HeartbeatДоступность по TCP, HTTP, ICMPПроверки аптайма
PacketbeatСетевой трафикDNS, HTTP, MySQL
AuditbeatАудит файлов и процессов Linuxauditd, системные вызовы

На Linux-хосты с логами ставьте Filebeat, на Windows - Winlogbeat, для метрик - Metricbeat. Три агента спокойно работают на одной машине: конфликтов по портам нет, каждый пишет свой registry и свои логи.

Когда Logstash необходим, а когда можно обойтись без него

Logstash - самое тяжёлое звено цепочки: JVM, heap от 1 до 4 ГБ, лишний сетевой хоп между Filebeat и Elasticsearch. Подключение оправдано при хотя бы одном условии:

  • фильтры grok, mutate, date и geoip, которые неудобно поддерживать в ingest-нодах;
  • несколько источников (Beats, Kafka, syslog, СУБД) и несколько приёмников (Elasticsearch, S3, второй кластер);
  • маршрутизация по индексам и data streams на основе содержимого события;
  • обогащение из внешних источников: geoip, справочники через translate, перевод кодов;
  • пиковая нагрузка, нужна буферизация через persistent queue, чтобы события не терялись при недоступности Elasticsearch.

Обойтись без Logstash можно в трёх случаях. Объём до нескольких тысяч событий в секунду, логи уже в JSON. Логика разбора укладывается в процессоры Filebeat (dissect, decode_json_fields, drop_event) и ingest-pipeline Elasticsearch (grok, date, geoip). Отдельного хоста под JVM нет, Elasticsearch потянет обработку на своих нодах.

Критерий простой: меньше 20 строк фильтров - переносите в ingest-ноды. Сотни строк, несколько pipeline, условная маршрутизация - ставьте Logstash.

Подготовка инфраструктуры и установка компонентов ELK

До установки проверьте версии, память и лимиты ядра. Ошибки здесь дают неприятные симптомы: Elasticsearch падает через десять минут после старта, Logstash не принимает соединения, Kibana не видит кластер.

Версии держите в одной мажорной ветке. На сентябрь 2026 года актуальна ветка 8.x, 9.x берите после проверки совместимости плагинов и клиентских библиотек. Пакеты ставятся из официальных репозиториев Elastic через apt или yum. Пошаговый сценарий развёртывания кластера Elasticsearch 8.x с репликацией и шардированием разобран в отдельном руководстве, здесь базовые шаги, которые нужны в любом варианте.

Память. Elasticsearch резервирует heap по формуле 50% от RAM, но не выше 31 ГБ. Порог связан с compressed ordinary object pointers: выше него JVM теряет сжатие ссылок и расходует больше памяти на те же данные. Если на ноде 64 ГБ, heap ставьте 31 ГБ, остальное отдайте под файловый кэш, он ускоряет поиск по индексам.

Лимиты ядра. На каждом хосте с Elasticsearch выполните:

sudo sysctl -w vm.max_map_count=262144
echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/99-elasticsearch.conf
ulimit -n 65535

Значение vm.max_map_count закрепите в файле, иначе после перезагрузки Elasticsearch не стартует с ошибкой mmap. Swap отключите командой swapoff -a и закомментируйте строку swap в /etc/fstab. В elasticsearch.yml добавьте bootstrap.memory_lock: true: heap перестанет выгружаться на диск.

Порты: 9200 - HTTP API Elasticsearch, 9300 - транспорт между нодами, 5601 - Kibana, 5044 - приём Beats в Logstash. Наружу открывайте только 5601, и то через VPN или reverse proxy. Порт 9200 в интернете без TLS и аутентификации даёт доступ ко всем логам: там встречаются токены, cookie и персональные данные.

Если тестового контура ещё нет, серверы под ноды разворачиваются за пару минут: Timeweb Cloud даёт серверы, хранилище и Kubernetes с гибким изменением ресурсов. Для стенда хватит машины с 8 ГБ RAM под Elasticsearch и Kibana плюс второй с 4 ГБ под Logstash.

Минимальные требования к ресурсам Elasticsearch и Logstash

Практические минимумы для контура до 50 ГБ логов в сутки. Для продакшена с репликацией нужно минимум три ноды Elasticsearch.

КомпонентRAMCPUДискКомментарий
Elasticsearchот 4 ГБ, лучше 8-16 ГБ2-4 ядраSSD, отдельный раздел под /var/lib/elasticsearchheap 50% RAM и не более 31 ГБ
Logstash2-4 ГБ2-4 ядра20-50 ГБ под persistent queueheap 1-4 ГБ, pipeline.workers по числу ядер
Kibana1-2 ГБ1-2 ядра10 ГБстатичный UI, тяжёлые запросы уходят в Elasticsearch
Filebeat100-200 МБменее 0.5 ядра1 ГБ под registry и логина каждом хосте с логами

В jvm.options Elasticsearch задайте Xms и Xmx одинаковыми: -Xms4g и -Xmx4g. Разные значения дают лишние паузы на изменение размера heap. Файл параметров разместите в /etc/elasticsearch/jvm.options.d/heap.options.

ILM-политику и шаблон индекса создайте до того, как агенты начнут писать данные: переделывать маппинги на живом индексе дороже, чем настроить всё сразу.

Параметры конвейера Logstash задаются в logstash.yml:

pipeline.workers: 4          # число ядер CPU
pipeline.batch.size: 125     # размер батча по умолчанию
pipeline.batch.delay: 50     # мс ожидания до отправки неполного батча
queue.type: persisted        # буфер на диске при недоступности Elasticsearch

pipeline.workers ставьте равным числу ядер, не больше: лишние воркеры конкурируют за CPU и замедляют фильтры.

Базовая защита: TLS и xpack.security

В Elasticsearch 8.x security включён по умолчанию. После первого запуска генерируются пароль пользователя elastic, сертификаты для транспортного и HTTP слоёв. Вручную проверьте параметры в elasticsearch.yml:

xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.http.ssl.enabled: true

Свои сертификаты создаются утилитой elasticsearch-certutil: сначала CA, затем сертификат с SAN-именами ваших хостов. Корневой сертификат положите в доверенные на всех нодах и агентах. Filebeat и Logstash не подключайте под пользователем elastic: выпустите API-ключ в Kibana (Stack Management, раздел API Keys) или роль с правом записи только в нужные индексы. Kibana подключается к Elasticsearch через служебную учётную запись kibana_system, а не через суперпользователя.

Пароль elastic смените командой elasticsearch-reset-password -u elastic и сохраните в менеджере секретов. Пароли по умолчанию в конфигах агентов - одна из частых причин утечек из тестовых контуров, которые случайно оказались доступны извне.

Настройка Filebeat: пошаговая инструкция

Filebeat ставится на каждый хост, с которого собираются логи. Пакет занимает около 150 МБ, запускается как systemd-сервис. Порядок: установить пакет, описать входы и выход в filebeat.yml, проверить конфигурацию, запустить сервис.

sudo apt-get install -y filebeat
sudo filebeat test config -c /etc/filebeat/filebeat.yml
sudo systemctl enable --now filebeat
sudo filebeat test output -c /etc/filebeat/filebeat.yml

Конфигурация состоит из четырёх блоков: filebeat.inputs (что читать), processors (что делать с событием до отправки), output (куда отправлять), logging (куда писать логи самого агента). YAML не терпит табуляцию и лишние пробелы: отступы только пробелами.

В /var/lib/filebeat/registry лежит registry-файл с позициями чтения. При перезапуске агент продолжает с последней позиции, а не перечитывает файл целиком. Удалите registry, и агент повторно отправит все логи, которые попадают под ignore_older.

Пример filebeat.yml для сбора логов Nginx и системного журнала

filebeat.inputs:
  # Access-логи Nginx
  - type: filestream
    id: nginx-access
    enabled: true
    paths:
      - /var/log/nginx/access.log
    fields:
      log_type: nginx
      service: frontend
    fields_under_root: true
    ignore_older: 72h
    clean_inactive: 96h

  # Error-логи Nginx
  - type: filestream
    id: nginx-error
    enabled: true
    paths:
      - /var/log/nginx/error.log
    fields:
      log_type: nginx-error
    fields_under_root: true

  # Системный журнал
  - type: filestream
    id: syslog
    enabled: true
    paths:
      - /var/log/syslog
    fields:
      log_type: syslog
    fields_under_root: true

processors:
  - add_host_metadata:
      when.not.contains.tags: forwarded
  - add_fields:
      target: ""
      fields:
        env: production
  - drop_event:
      when:
        equals:
          message: ""

output.logstash:
  hosts: ["192.168.10.20:5044"]
  loadbalance: true

setup.kibana:
  host: "192.168.10.10:5601"

logging.level: info
logging.to_files: true

Что делают ключевые директивы:

  • id - постоянное имя входа. Без него Filebeat генерирует идентификатор сам, и после правки конфигурации позиция чтения может сброситься.
  • fields_under_root: true - поля log_type и service попадают в корень события, а не в подобъект fields. В Logstash условие выглядит как [log_type] == "nginx".
  • ignore_older: 72h вместе с clean_inactive: 96h не дают агенту читать архивы старше трёх суток и удаляют позиции для файлов, которых нет четыре дня. clean_inactive всегда больше ignore_older, иначе Filebeat не стартует.
  • add_host_metadata добавляет имя хоста, ОС и IP в каждое событие: без этого в Kibana не понять, с какой машины пришёл лог.
  • drop_event выбрасывает пустые строки, которые иначе занимают место в индексах.

Если Elasticsearch принимает данные напрямую, замените блок output на:

output.elasticsearch:
  hosts: ["192.168.10.10:9200"]
  protocol: https
  api_key: "ID:API_KEY"
  ssl.certificate_authorities: ["/etc/filebeat/ca.crt"]

Модули экономят время. Команда filebeat modules enable nginx system добавляет готовые input, ingest-pipeline и дашборды Kibana. Модуль nginx сам разбирает access и error log в ECS-поля. Минус: контроля над парсингом меньше, при нестандартном log_format модуль оставит сырую строку без разбора.

Шаблоны индексов и дашборды загружаются один раз командой filebeat setup -e с любого хоста. Перед запуском укажите адрес Kibana в блоке setup.kibana, иначе дашборды не установятся.

Типичные ошибки при первом запуске Filebeat

  • Нет прав на чтение логов. Агент работает от пользователя filebeat и не видит /var/log/nginx/*.log. Добавьте его в группу adm: usermod -aG adm filebeat, затем перезапустите сервис. Проверка: sudo -u filebeat cat /var/log/nginx/access.log.
  • SELinux или AppArmor блокирует доступ. Записи denied ищите в /var/log/audit/audit.log. Для SELinux проверьте ausearch -m avc -ts recent и настройте контекст файлов, отключать SELinux целиком не нужно.
  • Дубликаты событий. Появляются после удаления registry или смены id входа. Не меняйте id без необходимости, а при пересоздании входа переносите registry-файл.
  • Сломанный YAML. Табуляция или лишний пробел не дают агенту стартовать, сообщение об ошибке ничего не объясняет. Прогоняйте filebeat test config -c /etc/filebeat/filebeat.yml перед каждым перезапуском.
  • Забытый setup.template. При прямой отправке в Elasticsearch без шаблона поля получают динамический маппинг, и строки вроде status_code попадают в text. Агрегации по ним в Kibana не строятся. Запустите filebeat setup --index-management.

Logstash: фильтры, нормализация и маршрутизация логов

Конвейер Logstash описывается в файле pipeline из трёх секций: input, filter, output. Событие проходит их последовательно. Конфигурации лежат в /etc/logstash/conf.d/, Logstash собирает их в один pipeline при старте.

Минимальный pipeline для приёма Beats и отправки в Elasticsearch:

input {
  beats {
    port => 5044
    ssl => true
    ssl_certificate => "/etc/logstash/logstash.crt"
    ssl_key => "/etc/logstash/logstash.key"
  }
}

output {
  elasticsearch {
    hosts => ["192.168.10.10:9200"]
    ssl_enabled => true
    ssl_certificate_authorities => ["/etc/logstash/ca.crt"]
    api_key => "${ES_API_KEY}"
    data_stream => "true"
  }
}

Фильтров здесь нет: Filebeat добавил метаданные хоста, разбор строк выполнят ingest-ноды. Как только появляется grok или маршрутизация, pipeline разрастается.

Практический пример: парсинг Nginx access log через grok

filter {
  # Ветка для access-логов Nginx
  if [log_type] == "nginx" {
    grok {
      match => { "message" => "%{COMBINEDAPACHELOG}" }
      remove_field => ["message"]
    }

    date {
      match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
      target => "@timestamp"
      remove_field => ["timestamp"]
    }

    mutate {
      rename => {
        "response" => "[http][response][status_code]"
        "bytes"    => "[http][response][body][bytes]"
        "verb"     => "[http][request][method]"
        "request"  => "[url][original]"
        "clientip" => "[client][ip]"
        "agent"    => "[user_agent][original]"
      }
    }

    mutate {
      convert => {
        "[http][response][status_code]" => "integer"
        "[http][response][body][bytes]" => "integer"
      }
    }

    geoip {
      source => "[client][ip]"
      target => "geo"
      fields => ["country_name", "city_name", "location"]
    }
  }
}

Разбор по шагам. Grok с паттерном COMBINEDAPACHELOG раскладывает стандартную строку combined в поля clientip, response, bytes, verb, request и другие. Фильтр date берёт timestamp из лога и ставит его в @timestamp: без этого событие получит время приёма, и хронология при разборе инцидентов поплывёт. Блоки mutate приводят поля к ECS и конвертируют строки в числа: по числовым полям строятся графики, по строкам нет. Geoip по IP клиента добавляет страну, город и координаты.

Второй mutate стоит отдельным блоком не случайно: внутри одного блока Logstash выполняет rename раньше convert, поэтому конвертация полей идёт после переименования.

Отладка занимает минуты: в Kibana откройте Dev Tools, раздел Grok Debugger, вставьте строку лога и паттерн. Частые причины провала: кастомный log_format в Nginx, несовпадение даты, лишние кавычки в message.

Формат с фиксированными разделителями разбирайте через dissect: он не использует регулярные выражения и работает быстрее grok. Пример для строки вида 2026-09-11T10:15:30 level=error service=api msg=timeout:

dissect {
  mapping => {
    "message" => "%{ts} level=%{level} service=%{service} msg=%{msg}"
  }
}

Маршрутизация событий по индексам и data streams

Nginx и системный журнал лучше не смешивать в одном индексе: у них разные наборы полей, сроки хранения и права доступа. Маршрутизация выполняется условными блоками в output:

output {
  if [log_type] == "nginx" {
    elasticsearch {
      hosts => ["192.168.10.10:9200"]
      index => "nginx-%{+YYYY.MM.dd}"
      ssl_enabled => true
      api_key => "${ES_API_KEY}"
    }
  } else if [log_type] == "syslog" {
    elasticsearch {
      hosts => ["192.168.10.10:9200"]
      index => "syslog-%{+YYYY.MM.dd}"
      ssl_enabled => true
      api_key => "${ES_API_KEY}"
    }
  } else {
    elasticsearch {
      hosts => ["192.168.10.10:9200"]
      index => "other-%{+YYYY.MM.dd}"
      ssl_enabled => true
      api_key => "${ES_API_KEY}"
    }
  }
}

Шаблон %{+YYYY.MM.dd} подставляет дату события, а не дату отправки: старые логи при бэкфилле лягут в правильные индексы. Имена индексов совпадут с шаблонами, по которым созданы data view в Kibana и ILM-политики.

Для новых конвейеров в 8.x используйте data streams: настройка data_stream => "true" создаёт скрытые индексы .ds-*, подхватывает ILM из коробки и не требует отдельного шаблона на каждый тип лога. Имя потока собирается из data_stream_type, data_stream_dataset и data_stream_namespace. Классический вариант index => "nginx-%{+YYYY.MM.dd}" остаётся для существующих контуров с ручным управлением шаблонами.

Перед перезапуском проверьте конфигурацию:

sudo /usr/share/logstash/bin/logstash --path.settings /etc/logstash -t

Команда собирает файлы из conf.d, проверяет синтаксис и выводит Configuration OK. Ошибки вида Expected one of означают пропущенную скобку или запятую, номер строки есть в том же сообщении.

Поиск и анализ логов в Kibana

Работа в Kibana начинается с data view, до версии 8.0 это был index pattern. Data view связывает Kibana с индексами: укажите шаблон nginx-* и поле времени @timestamp, данные появятся в Discover.

Discover - основной инструмент разбора инцидентов. Слева список полей, в центре документы, сверху строка поиска и выбор временного диапазона. Клик по значению поля добавляет фильтр, значок минус исключает значение. Удачный запрос сохраните как Saved search: он пригодится в дашбордах.

Проверяйте маппинг полей до первых агрегаций. Строковые поля в Elasticsearch бывают двух типов: text разбивается на слова и годится только для полнотекстового поиска, keyword хранится целиком и подходит для сортировки, агрегаций и точных фильтров. В шаблонах 8.x поля создаются как multi-field с сабполем keyword, Lens сам предложит правильный вариант. Если поле пришло с динамическим маппингом как text без keyword, график по нему не построится: нужна переиндексация или правка шаблона с повторным приёмом данных.

KQL и Lucene: чем отличаются и что использовать

Строка поиска в Kibana 8.x работает на KQL по умолчанию: проще синтаксис, есть автодополнение имён полей, под капотом запрос всё равно переводится в Lucene. Одно и то же условие в двух синтаксисах:

KQL:    http.response.status_code: 500 and url.original: *api/v1*
Lucene: http.response.status_code:500 AND url.original:*api/v1*

Диапазоны в KQL записываются знаками сравнения, например http.response.status_code >= 500. В Lucene для того же условия нужен интервал: http.response.status_code:[500 TO *]. Переключатель KQL и Lucene находится в правом конце строки поиска.

Lucene выручает с регулярными выражениями: message:/timeout|refused/. Если запрос не находит ничего, а документы в Discover видны, проверьте временной диапазон и тип поля раньше, чем синтаксис.

Сборка первого дашборда для мониторинга веб-логов

Минимальный дашборд веб-сервиса собирается из трёх визуализаций:

  1. Line chart: количество запросов по времени. Ось Y - Count, ось X - @timestamp с интервалом auto.
  2. Pie chart: распределение по http.response.status_code. Коды 5xx сразу показывают деградацию.
  3. Table: топ-10 url.original по числу запросов, сортировка по убыванию.

В Lens визуализация собирается перетаскиванием полей: выберите тип графика, положите поле на ось, задайте метрику Count. Панели сохраняются в Dashboard, автообновление включается кнопкой Refresh раз в 30 секунд.

Для быстрого разбора ошибок создайте Saved search с фильтром http.response.status_code >= 500 и добавьте его на дашборд отдельной панелью. Если дашбордами пользуются разные команды, разделите их по Spaces в Stack Management.

Контроль потребления ресурсов Elasticsearch и Logstash

Типовой сбой выглядит так: логи копятся месяцами, диск заполняется, Elasticsearch переходит в режим read-only и перестаёт принимать события. Причины две: нет политики удаления старых индексов, heap выехал за лимит. Оба параметра настраиваются заранее.

Elasticsearch:

  • heap задаётся в /etc/elasticsearch/jvm.options.d/heap.options, Xms равен Xmx;
  • swap отключён, bootstrap.memory_lock: true;
  • число шардов: не более 20 шардов на 1 ГБ heap на ноду, иначе каждому шарду не хватает ресурсов;
  • refresh_interval для логов поднимается с 1s до 30s: меньше нагрузка на сегменты, поиск отстаёт на полминуты;
  • ILM управляет переходом индексов по фазам и удалением.

Logstash:

  • pipeline.workers равен числу ядер CPU;
  • pipeline.batch.size 125-500, pipeline.batch.delay 50 мс;
  • persistent queue на диске защищает от потери событий при падении Elasticsearch;
  • JVM heap 1-4 ГБ, больше не требуется: узкое место обычно в фильтрах и сети.

ILM: автоматическое удаление старых логов

Index Lifecycle Management переводит индексы по фазам и удаляет устаревшие. Политика для логов с хранением 30 дней:

PUT _ilm/policy/logs-30d
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_primary_shard_size": "50gb",
            "max_age": "1d"
          }
        }
      },
      "warm": {
        "min_age": "7d",
        "actions": {
          "shrink": { "number_of_shards": 1 },
          "forcemerge": { "max_num_segments": 1 }
        }
      },
      "delete": {
        "min_age": "30d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

Запрос выполняется в Dev Tools Kibana. Дальше политика привязывается к шаблону индекса через настройку "index.lifecycle.name": "logs-30d", новые индексы подхватывают её автоматически. Для data streams связка задаётся в компонентном шаблоне.

Готовые конфигурации ротации и хранения, включая logrotate для Nginx и Docker и схему hot/warm/cold с выгрузкой в S3, собраны в материале про управление хранением и ротацией логов в production.

Диагностика узких мест: где смотреть метрики

Быстрые команды Elasticsearch (Dev Tools или curl на localhost:9200):

GET _cluster/health                  # статус кластера и число нод
GET _cat/indices?v                   # индексы, размер, здоровье
GET _cat/shards?v                    # распределение шардов по нодам
GET _nodes/stats/jvm,os,fs           # heap, CPU и диск по каждой ноде

Logstash отдаёт статистику конвейеров:

curl -s localhost:9600/_node/stats/pipelines?pretty

Смотрите на events.in, events.out, queue_push_duration_in_millis и время выполнения фильтров. Если grok съедает больше времени, чем всё остальное, упростите паттерн или переходите на dissect.

Filebeat пишет логи в /var/log/filebeat/filebeat и отдаёт метрики при включённом мониторинге. Признак backpressure: очередь растёт, отправка отстаёт. Причины: медленный Logstash, сеть, недоступный Elasticsearch. Что проверить: pipeline.workers и batch.size на стороне Logstash, размер spooler-очереди у Filebeat, потери пакетов между хостами.

Сводная картина собирается в Stack Monitoring: Stack Management, раздел Stack Monitoring. Там видны нагрузка на ноды, использование heap, задержки индексации и очереди Logstash на одном экране.

Чек-лист запуска и типичные ошибки при развёртывании ELK

Развёртывание заканчивается проверкой: сервис отвечает, данные идут, дашборд открывается. Если что-то из этого не работает, идите по цепочке от агента к интерфейсу.

Что делать, если логи не появляются в Kibana

Каждый шаг проверяет своё звено:

  1. Filebeat читает файл. filebeat test output проверяет соединение с выходом. В логах агента не должно быть ошибок harvester. Файл не читается, вернитесь к правам и SELinux.
  2. События уходят. Счётчики событий смотрите в логах агента при включённом logging.metrics. Ноль на выходе означает проблему с input или registry.
  3. Logstash принимает событие. Временно добавьте в output секцию stdout { codec => rubydebug } и перезапустите Logstash: событие появится в журнале конвейера с разобранными полями. После отладки вывод уберите, он пишет всё на диск.
  4. Elasticsearch создал индекс. Проверьте GET _cat/indices?v: нужный индекс есть, число документов растёт. Индекса нет, смотрите журнал Logstash на ошибки маппинга и прав доступа.
  5. Kibana видит данные. Проверьте data view (шаблон совпадает с именем индекса) и временной диапазон. Свежие события не появятся, если @timestamp пришёл из лога со старым временем или часовой пояс сдвинул дату.

Если приложения пишут логи неинформативно, ни один стек это не исправит: стратегия логирования для DevOps с примерами логгеров на Python, Go и Java помогает настроить вывод на стороне сервисов. Структурированный JSON с trace_id и уровнем важности экономит часы разбора инцидентов.

Финальный чек-лист перед вводом в работу:

  • версии Filebeat, Logstash, Elasticsearch и Kibana совпадают в пределах мажорной ветки;
  • vm.max_map_count=262144 закреплён в sysctl;
  • swap отключён, bootstrap.memory_lock: true;
  • heap Elasticsearch не превышает 31 ГБ, Xms равен Xmx;
  • TLS включён на транспортном и HTTP слоях, пароль elastic сменён, для агентов выпущены API-ключи;
  • порт 9200 закрыт файрволом от внешних сетей;
  • ILM-политика создана и привязана к шаблонам индексов;
  • filebeat test config и filebeat test output проходят без ошибок;
  • data view в Kibana создан, временной диапазон охватывает тестовые события;
  • дашборд открывается и показывает свежие данные.

Остальные типичные ошибки:

  • несовпадение версий: Filebeat 8.x и Elasticsearch 9.x несовместимы по API;
  • дубликаты после удаления registry или смены id входа;
  • открытый порт 9200 без TLS и пароля;
  • забытый setup.template при прямой отправке в Elasticsearch: поля получают text вместо keyword;
  • отсутствие ILM: диск заполняется, индексы уходят в read-only;
  • heap Elasticsearch больше 31 ГБ: сжатие ссылок на объекты отключается, производительность падает;
  • pipeline.workers больше числа ядер: воркеры конкурируют за CPU;
  • grok на каждом логе вместо dissect: лишняя нагрузка на фильтры.

Соберите стенд в тестовом контуре: одна нода Elasticsearch, Kibana, Filebeat на паре хостов. Когда схема Filebeat → Logstash → Elasticsearch → Kibana заработает на тестовых данных, добавляйте остальные источники и переносите конфигурации в продакшен. Конфиги из статьи переносятся без правок, меняются только адреса и ключи.

Поделиться:
Сохранить гайд? В закладки браузера