ADG Оставить заявку
Блог Системное администрирование 5 мин чтения

Filebeat вместо Logstash-агентов: 150+ серверов, 12 МБ вместо 256 МБ на хост

Elastic выпустила Beats 1.0 - лёгкие шипперы для ELK. Мы заменили Logstash-агенты на Filebeat и получили падение потребления памяти с 256 до 12 МБ на хост.

Контекст момента

Elastic выпустила Beats 1.0 (Filebeat, Packetbeat) как лёгкие шипперы логов для ELK-стека

Elastic в октябре выпустила Beats 1.0 - и это был повод наконец закрыть задачу, которую мы откладывали несколько месяцев. Задача называлась «сделать что-нибудь с Logstash-агентами на 150+ серверах, которые жрут 256 МБ на хост и периодически падают».

Откуда взялась проблема

Когда мы строили ELK-стек для централизованных логов, архитектура была типичная: Logstash-агент на каждом сервере читает файлы, парсит через grok-паттерны и отправляет в центральный Elasticsearch. Такая схема работает, но у неё есть свойство, которое на 10-20 серверах не ощущается, а на 150+ начинает раздражать.

Logstash написан на JVM. На каждом хосте живёт java-процесс, которому минимальный heap мы урезали до 256 МБ - и это уже была граница, ниже которой Logstash нестабильно себя вёл при всплесках. На серверах с 2-4 ГБ оперативки это 6-12% памяти - просто за то, что логи куда-то летят. На одном из клиентских стендов в какой-то момент половина серверов имела RSS Logstash-процесса больше 300 МБ: JVM разошлась и не спешила возвращать память.

Параллельно был второй симптом: агент занимался и сбором, и первичным парсингом. Парсинг - это grok, это регулярки, это CPU. На нескольких хостах с высоким объёмом логов мы видели периодические всплески нагрузки именно от Logstash. Не катастрофа, но неприятно.

Что такое Beats 1.0

Beats - это семейство лёгких шипперов, написанных на Go. Filebeat читает файлы логов, Packetbeat нюхает сетевые пакеты. Принцип простой: шиппер делает только одно - доставляет данные, без тяжёлой обработки на борту. Парсинг остаётся центральному Logstash.

Go-бинарник весит несколько мегабайт, статически слинкован, зависимостей нет. Потребление памяти в покое - около 10-15 МБ. Мы замерили после первых развёртываний: Filebeat 1.0 на наших хостах потреблял от 10 до 14 МБ RSS, в среднем около 12 МБ. По сравнению с 256 МБ от Logstash - это другая категория.

Как выглядит конфиг Filebeat

Минимальный конфиг для сбора системных логов и логов приложения:

filebeat:
  prospectors:
    - paths:
        - /var/log/syslog
        - /var/log/auth.log
      input_type: log
      document_type: syslog

    - paths:
        - /var/log/app/*.log
      input_type: log
      document_type: app
      multiline:
        pattern: '^\d{4}-\d{2}-\d{2}'
        negate: true
        match: after

output:
  logstash:
    hosts: ["logstash.internal:5044"]

shipper:
  name: "%{[host]}"

Multiline - это то, без чего стек-трейсы Java превращаются в тысячи отдельных событий. Filebeat умеет собирать многострочные события по паттерну начала строки, и это важно для любых приложений с нормальными исключениями.

На центральном Logstash добавился input для Beats:

input {
  beats {
    port => 5044
  }
}

Парсинг grok переехал сюда - туда, где ему и место. Агенты теперь занимаются только доставкой.

Как раскатывали на 150+ серверов

Благо Ansible у нас уже был налажен после перехода на Ansible 2.0. Написали роль: скачивает deb/rpm-пакет Filebeat 1.0, деплоит конфиг из шаблона, включает сервис. Конфиг параметризован через переменные - пути к логам, адрес Logstash, тип документа.

Раскатка на тестовой группе заняла несколько минут. Смотрели на центральном Logstash: события появляются, типы документов правильные, multiline работает. Потом прогнали по всем хостам батчами по 20, чтобы не создавать всплеск на центральном Logstash при одновременном старте 150 агентов.

На центральном Logstash пришлось поднять количество воркеров - он теперь получает сырые события и сам делает весь парсинг. Нагрузка на Logstash-кластер выросла, но это контролируемо и в одном месте, а не размазано по всем хостам.

Что получилось в итоге

Потребление памяти на хостах упало существенно - с 256 МБ до примерно 12 МБ на хост. На 150 серверах это несколько десятков гигабайт оперативки, которые раньше были заняты java-процессами и теперь свободны для приложений.

Парсинг централизован. Когда нужно добавить новый grok-паттерн или исправить существующий - меняем конфиг в одном месте и перезапускаем центральный Logstash. Раньше надо было либо держать grok-конфиги синхронизированными на всех агентах (что реально делалось через Ansible, но всё равно сложнее), либо мириться с тем, что агенты на разных хостах ведут себя по-разному.

Из неожиданного: Filebeat отслеживает позицию в файлах через registry-файл (/var/lib/filebeat/registry). При перезапуске агента - ничего не теряется, продолжает с места остановки. При ротации логов (logrotate) - работает корректно, если конфиг logrotate использует copytruncate или Filebeat правильно настроен на следование за inode. Это надо проверять на конкретной системе, у нас на нескольких хостах с нестандартной ротацией пришлось чуть подкрутить.

Что пока не трогали

Packetbeat мы пока не развёртывали. Он перехватывает сетевой трафик и умеет разбирать HTTP, MySQL, Redis и ещё несколько протоколов - отдельный разговор про то, нужно ли это нам и на каких хостах. Оставили на потом.

Схема с Logstash как центральным парсером тоже не окончательная - на больших объёмах Logstash сам становится узким местом. Но это проблема другого порядка и другого масштаба, чем то, что мы решали сейчас.

В целом замена заняла два дня работы на сопровождении: написать роль, прогнать по всем хостам, убедиться что данные идут, подкрутить центральный Logstash. Результат ощутимый - агенты теперь не видны в top на серверах, что само по себе приятно.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.