ADG Оставить заявку
Блог DevOps 4 мин чтения

Fluent Bit 1.0 в Kubernetes DaemonSet: потребление памяти с 512MB до 30MB без потери throughput

Заменили Logstash на Fluent Bit 1.0 в Kubernetes-кластере клиента. Потребление памяти DaemonSet упало с 512MB до ~30MB на узел при тех же 50K событий в секунду.

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

Fluent Bit 1.0 GA вышел в декабре 2018 как зрелый легковесный агент сбора логов, готовый к production в Kubernetes

В одном из managed-проектов у нас Kubernetes-кластер на восьми рабочих нодах с приличной нагрузкой по логам: суммарно около 50 тысяч событий в секунду от нескольких десятков сервисов. Логи идут в Elasticsearch. Агентом сбора до недавнего времени был Logstash - задеплоен DaemonSet-ом, по одному поду на ноду, и потреблял примерно 512MB RAM на каждой. Итого - чуть больше 4GB живой памяти только на сбор и пересылку логов, без какой-либо обработки данных.

Когда в декабре вышел Fluent Bit 1.0 GA, мы решили проверить, стоит ли переходить. Результат оказался убедительным.

Почему Logstash выглядел странно на этой роли

Logstash - инструмент мощный, но в первую очередь для трансформации данных: фильтры, grok, мутации, условия. В нашем сценарии DaemonSet на Kubernetes делал три простые вещи: читал логи контейнеров из /var/log/containers/, добавлял метаданные пода (namespace, имя, labels) и отправлял в Elasticsearch. Никаких сложных трансформаций.

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

Fluent Bit: что это такое

Fluent Bit - это легковесный агент из семейства Fluentd, написанный на C. Не замена Fluentd с его богатой экосистемой плагинов, а именно агент для collection и forwarding - туда, где нужны маленький footprint и высокая производительность без сложной обработки.

Нулевая точка: 1.0 GA вышел именно сейчас, и это не просто версионный bump. До этого проект развивался довольно активно, но 1.0 означает стабильный API плагинов и декларацию production-готовности от CNCF-сообщества. Для нас это был сигнал смотреть серьёзнее.

Что делали

Подняли тестовый стенд на двух нодах - полная копия production по нагрузке, но изолированная. Развернули Fluent Bit как DaemonSet рядом с Logstash, направили на тот же Elasticsearch-кластер в отдельный индекс.

Конфиг для K8s стандартный - официальный Helm chart от команды Fluent Bit с минимальными правками. Из коробки он умеет читать /var/log/containers/, обогащать записи метаданными через kubernetes filter (namespace, pod name, container name, labels, annotations) и писать в Elasticsearch с правильным index pattern.

Единственное что пришлось настроить руками: парсер для мультилайн-логов от одного из сервисов, который пишет Java stack traces. В Logstash у нас был готовый multiline codec, в Fluent Bit - Multiline parser через MULTILINE_FLUSH_TIMEOUT и regex для начала новой записи. Заняло час, включая тестирование.

Через сутки на тестовом стенде сравнили:

  • Потребление RAM. Logstash - стабильно 480-520MB на ноду. Fluent Bit - 25-35MB. Разница примерно в 15 раз.
  • Throughput. На обоих потоке одинаковая нагрузка - около 6K событий в секунду на ноду. Fluent Bit справлялся без drop-ов, метрики в Elasticsearch показывали одинаковый объём событий.
  • CPU. Logstash в среднем ~0.3 CPU core на ноду. Fluent Bit - ~0.05. Тоже в 5-6 раз меньше.
  • Задержка доставки. Замерили по timestamp события в приложении vs timestamp в Elasticsearch. На обоих агентах - единицы секунд, без статистически значимой разницы.

Переход на production

После недели на тестовом стенде без единого инцидента перенесли на production. Порядок: развернули Fluent Bit DaemonSet рядом с Logstash, подождали час чтобы убедиться что события доходят в Elasticsearch, потом убрали Logstash.

Освободили чуть больше 4GB RAM на кластере. Это не абстрактные гигабайты - на этих нодах теперь есть место для рабочих workload-ов, и в нескольких случаях мы убрали pending-поды, которые раньше не влезали на ноды из-за resource requests.

Что осталось открытым: у нас есть один сервис с нестандартным форматом логов, где сейчас через Fluent Bit идёт более простая обработка чем была в Logstash. Функциональность не потеряна, но там была пара grok-паттернов, которые в Fluent Bit придётся перетащить аккуратнее. Пока живём с «достаточно хорошим» форматом в этом индексе, полную миграцию допилим на следующей итерации.

Итого про архитектуру

Fluent Bit на ноде + Elasticsearch напрямую - для нашего случая это оказался правильный выбор. Если нужна серьёзная обработка логов по пути, Fluentd как агрегатор между Fluent Bit и Elasticsearch - тоже разумная схема: Fluent Bit собирает и пересылает, Fluentd трансформирует. Но добавлять слой сложности стоит когда он действительно нужен.

В нашем текущем кластере этот слой не нужен - и убрав его, мы избавились от 4GB overhead и JVM-капризов на 8 нодах. Для K8s-логирования в проектах где нет экзотических требований к трансформации это теперь наш рабочий стандарт.

Контакт

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

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