Fluent Bit — легковесный агент логов, который отлично чувствует себя на небольших VDS. Его сильные стороны: низкое потребление памяти и CPU, богатый набор входов/фильтров/выходов и надёжная схема буферизации. В этой статье разберём боевую конфигурацию под типичный стек: Nginx + systemd‑сервисы, отгрузка в Loki и/или Elasticsearch (ELK), и акцент на экономию ресурсов без потери данных.
Почему Fluent Bit на VDS и как избежать лишней нагрузки
На небольших инстансах важны два фактора: предсказуемая память и устойчивость к пикам. Fluent Bit позволяет:
- Писать части буфера на диск при сетевых проблемах (filesystem storage), не раздувая RAM.
- Лимитировать объём памяти на каждый выход (
Mem_Buf_Limit), чтобы избежать OOM. - Фильтровать шум до отгрузки (например, health‑checks, статические ответы 200).
- Аккуратно парсить JSON‑логи Nginx без тяжёлых регэкспов.
- Собрать journald/systemd‑логи без лишнего «мусора» по unit‑фильтрам.
Дальше — практическая конфигурация, которую можно взять за основу и адаптировать под свои каталоги логов и приёмники.
Установка и структура конфигурации
На современных дистрибутивах достаточно обычной установки пакета. Сервисный unit и базовые конфиги ставятся автоматически.
sudo apt update
sudo apt install fluent-bit
# Проверить версию и плагины
fluent-bit --version
fluent-bit --help
Рекомендуемая структура конфигурации: один «корневой» /etc/fluent-bit/fluent-bit.conf с Service и @INCLUDE на отдельные файлы входов/фильтров/выходов, плюс /etc/fluent-bit/parsers.conf для парсеров.
Базовый fluent-bit.conf с дисковым буфером
Сервисная секция задаёт тайминги, лог‑уровень и каталог для файлам буфера. HTTP‑сервер удобен для локальной диагностики метрик агента.
# /etc/fluent-bit/fluent-bit.conf
[SERVICE]
Flush 5
Daemon Off
Log_Level info
Parsers_File /etc/fluent-bit/parsers.conf
HTTP_Server On
HTTP_Listen 127.0.0.1
HTTP_Port 2020
# Дисковый сторедж для устойчивости при сбоях сети
storage.path /var/lib/fluent-bit/storage
storage.sync normal
storage.checksum On
storage.backlog.mem_limit 64M
@include inputs.conf
@include filters.conf
@include outputs.conf
Создайте каталог для хранения буфера и убедитесь, что у процесса есть права на запись. В системных пакетах путь зачастую создаётся автоматически, но проверить стоит.

Парсеры: JSON для Nginx и мультилайн
Лучше сформировать JSON прямо в Nginx, чтобы отказаться от тяжёлых регэкспов. Пример формата:
# В nginx.conf (фрагмент)
log_format json escape=json '{"time":"$time_iso8601","remote":"$remote_addr","method":"$request_method","uri":"$request_uri","status":$status,"size":$body_bytes_sent,"ua":"$http_user_agent","referer":"$http_referer","host":"$host","req_time":$request_time}';
access_log /var/log/nginx/access.json json;
В парсерах ничего «выдумывать» не нужно — используем встроенный JSON‑парсер, лишь укажем ключ времени и формат.
# /etc/fluent-bit/parsers.conf
[PARSER]
Name nginx_json
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S%z
Time_Keep On
# Пример мультилайна для ошибок/трейсов (адаптируйте под свой софт)
[MULTILINE_PARSER]
Name php_trace
Type regex
Flush_Timeout 2000
# Первая строка трейс-сообщения: дата в начале
Rule "start_state" "/^\d{4}\/\d{2}\/\d{2} /" "cont"
Rule "cont" "/^(\s|#|Stack trace:|PHP )/" "cont"
Если приложение уже пишет чистый JSON, достаточно указать Format json. Для текстовых трейс‑логов настраивайте мультилайн под реальный шаблон первой строки.
Inputs: tail для Nginx и systemd для journald
Опишем входы в отдельном файле. Важные моменты для tail:
storage.type filesystem— чтобы куски уходили в дисковый буфер при проблемах сети.DBиDB.Sync— надёжное хранение оффсетов, чтобы не пропускать строки после рестартов.Buffer_Chunk_SizeиBuffer_Max_Size— контроль размера чанков и памяти.
# /etc/fluent-bit/inputs.conf
[INPUT]
Name tail
Tag nginx.access
Path /var/log/nginx/access.json
Parser nginx_json
Skip_Long_Lines On
Refresh_Interval 5
Rotate_Wait 5
DB /var/lib/fluent-bit/nginx-access.db
DB.Sync Full
Mem_Buf_Limit 16M
Buffer_Chunk_Size 64k
Buffer_Max_Size 256k
storage.type filesystem
[INPUT]
Name tail
Tag nginx.error
Path /var/log/nginx/error.log
Multiline On
Multiline.Parser php_trace
Skip_Long_Lines On
Refresh_Interval 5
DB /var/lib/fluent-bit/nginx-error.db
DB.Sync Full
Mem_Buf_Limit 16M
Buffer_Chunk_Size 64k
Buffer_Max_Size 256k
storage.type filesystem
# journald через systemd input: фильтруем по unit, чтобы не тащить весь системный шум
[INPUT]
Name systemd
Tag sysd.*
Systemd_Filter _SYSTEMD_UNIT=nginx.service
Systemd_Filter _SYSTEMD_UNIT=php-fpm.service
Read_From_Tail On
Mem_Buf_Limit 32M
storage.type filesystem
Если у вас несколько пуулов PHP‑FPM или сервисов приложений, добавьте дополнительные Systemd_Filter. Так вы избежите лишней нагрузки и индексации ненужных сообщений.
Фильтры: чистим шум и ограничиваем кардинальность
Главная экономия — не отправлять то, что не нужно анализировать. Для HTTP‑доступов это, как правило, статические 200‑ответы к ассетам, а для сервисов — шумное debug‑логирование. Ещё одна статья затрат в Loki/ELK — кардинальность меток/полей, так что аккуратно выбираем, что поднимаем до labels/fields.
# /etc/fluent-bit/filters.conf
# Удалим самые шумные записи статического кеша (примерный паттерн)
[FILTER]
Name grep
Match nginx.access
Regex uri ^(?!.*\.(css|js|png|jpg|gif|svg|ico|mp4)$).+
# Нормализуем и удалим чувствительные ключи, если они встречаются
[FILTER]
Name modify
Match *
Remove_Key authorization
Remove_Key cookie
# Снижаем объем при бурстах: дропаут повторяющихся строк
[FILTER]
Name throttle
Match nginx.error
Rate 200
Window 5
Print_Status Off
# Преобразуем типы полей (числа и время) для ES
[FILTER]
Name parser
Match nginx.access
Key_Name log
Parser nginx_json
Reserve_Data On
grep с отрицательной проверкой сэкономит трафик и место в хранилище по доступам. throttle спасает при шторме идентичных ошибок: например, одно и то же сообщение миллион раз за минуту. Фильтр modify — быстрый способ убирать потенциально приватные поля.
Выход в Loki: минимальные и безопасные лейблы
В Loki критично держать низкую кардинальность labels. Не используйте динамичные поля (URI с query, user‑agent) в labels — их оставляем частью строки или JSON. Подробно про метки и пайплайны см. материал Лейблы и пайплайны в Loki: практический разбор.
# /etc/fluent-bit/outputs.conf
[OUTPUT]
Name loki
Match nginx.*
Host 127.0.0.1
Port 3100
Labels job=nginx, host=${HOSTNAME}, stream=access
Line_Format json
Remove_Keys ua,referer
Auto_Kubernetes_Labels Off
Http_User loki_user
Http_Passwd loki_pass
TLS On
TLS.Verify On
Workers 1
Mem_Buf_Limit 16M
Retry_Limit False
[OUTPUT]
Name loki
Match sysd.*
Host 127.0.0.1
Port 3100
Labels job=systemd, host=${HOSTNAME}
Line_Format json
TLS On
TLS.Verify On
Workers 1
Mem_Buf_Limit 16M
Retry_Limit False
Line_Format json позволит передавать структуру, но помните: чем больше полей в записи, тем тяжелее индексация downstream. Метки держите минимальными и стабильными.

Выход в Elasticsearch (ELK): экономим на батчах и компрессии
Для ELK полезны логсташ‑совместимые индексы и gzip‑компрессия. Правильно выбирайте количество worker‑потоков: на маленьком VDS 1–2 обычно достаточно.
[OUTPUT]
Name es
Match nginx.*
Host 127.0.0.1
Port 9200
HTTP_User es_user
HTTP_Passwd es_pass
Logstash_Format On
Logstash_Prefix nginx
Replace_Dots On
Time_Key @timestamp
Generate_ID On
Compress gzip
Workers 1
Mem_Buf_Limit 32M
Retry_Limit False
[OUTPUT]
Name es
Match sysd.*
Host 127.0.0.1
Port 9200
HTTP_User es_user
HTTP_Passwd es_pass
Logstash_Format On
Logstash_Prefix systemd
Replace_Dots On
Time_Key @timestamp
Generate_ID On
Compress gzip
Workers 1
Mem_Buf_Limit 16M
Retry_Limit False
При необходимости прикрутите ingest‑pipeline в ES (например, для гео‑IP или user‑agent), но помните, что это удорожает обработку. Иногда выгоднее парсить заранее и хранить только необходимое.
Запуск, проверка и метрики
После редактирования конфигов проверьте синтаксис и запустите службу:
sudo fluent-bit -c /etc/fluent-bit/fluent-bit.conf -t
sudo systemctl enable --now fluent-bit
sudo systemctl status fluent-bit
Метрики доступны на локальном HTTP‑эндпоинте агента. Полезно смотреть чередование памяти и количество ретраев/дисковых чанков при тестовых отключениях сети.
Тонкая настройка под низкую нагрузку
Ниже — список практик, которые реально снижают потребление ресурсов на VDS, не теряя устойчивости.
- Увеличьте
Flushдо 5–10 секунд, если latency не критична. Это уменьшит количество сетевых запросов. - Дисковый буфер обязателен:
storage.pathв[SERVICE], а в входахstorage.type filesystem. Это предотвращает рост RAM при недоступности Loki/ES. - Ограничьте
Mem_Buf_Limitу каждого выхода. Типичные значения на маленьком инстансе: 16–64 МБ. - Тщательно подберите поля в labels для Loki и индексы в ES. Избыточные метки = взрыв кардинальности и высокая нагрузка downstream.
- Отбрасывайте шум через
grep/throttleдо отгрузки. Дешевле удалить строку локально, чем индексировать её в кластере. - Без нужды не используйте тяжёлые regex‑парсеры: лучше писать JSON на стороне приложения или веб‑сервера.
- В
tailдержите небольшие чанки:Buffer_Chunk_Size 64kиBuffer_Max_Size 256kобычно достаточно. - Храните оффсеты tail в SQLite:
DB+DB.Sync Full— меньше дублирования строк при рестартах.
Надёжность: что происходит при сбое сети
С включённым дисковым стореджем Fluent Bit делает следующее:
При временной недоступности Loki/ES исходящие чанки откладываются на диск, не заполняя память. После восстановления связи агент по ретраям дозагружает данные, сохраняя порядок внутри чанков.
Убедитесь, что диска хватит на типичный объём логов за время простоя и что на файловой системе включён мониторинг свободного места. Retry_Limit False полезен, если данные нельзя терять, но следите за накоплением «хвостов».
Производительность: ориентиры для маленькой машины
Схема вроде «Nginx JSON + journald, grep/throttle, 1–2 выхода» на инстансе с 1 vCPU и 1–2 ГБ RAM обычно укладывается:
- CPU: 1–3% при скорости 1–2 тыс. строк/сек для Nginx JSON.
- RAM: 20–60 МБ при
Mem_Buf_Limit16–32 МБ и включённом дисковом буфере. - Диск: десятки мегабайт в обычном режиме; при длительном простое сетевого приёмника — по фактическому объёму логов.
На пиках увеличивайте лимиты поэтапно и проверяйте метрики. Если downstream перегружен, агрессивнее фильтруйте шум и уменьшайте кардинальность меток.
Траблшутинг и практические советы
- Пропуски строк после ротации: проверьте
Rotate_Waitвtailи корректность логротейта для Nginx. - Дубли после рестартов: включите
DB.Sync Fullи убедитесь, что путь к базе tail на постоянном диске. - «Сыпется» парсер: временно поставьте
Log_Level debugи посмотрите метрикиparserна HTTP‑эндпоинте агента. - Большие сообщения от приложений: увеличьте
Buffer_Max_Sizeу соответствующего входа и проверьте мультилайн‑правила. - ES отклоняет документы из‑за типов: настроьте
Time_Key,Replace_Dotsи фильтрparserдля корректной типизации. - Высокая латентность приёмника: увеличьте
Flush, включите компрессию (ES), уменьшите количество воркеров до устойчивого уровня.
Мини‑чеклист перед продом
- JSON‑логи Nginx включены и валидны; мультилайн настроен под реальные трейсы.
- Фильтры
grep/modify/throttleрежут шум и приватные поля. - Дисковый буфер включён, места достаточно;
Mem_Buf_Limitпроставлен у выходов. - Labels для Loki — только стабильные и малокардинальные.
- ES: включена компрессия, корректные индексы и ключи времени.
- Метрики агента доступны локально, есть базовый мониторинг RAM/CPU/диска.
Итого
Fluent Bit позволяет собрать логи на одном VDS и надёжно доставить их в Loki или ELK без лишней нагрузки. Секрет — отдавать предпочтение JSON‑логам, вовремя фильтровать шум, ограничивать память через Mem_Buf_Limit и всегда включать дисковый буфер. Такая конфигурация упрощает эксплуатацию и предсказуемо ведёт себя при сбоях сети, что особенно важно на небольших инстансах.


