Загрузка данных


Шаг 1. Добавить Fluent Bit в compose

Создать новую директорию:

fluent-bit/
├── fluent-bit.conf
└── parsers.conf

Добавить сервис:

fluent-bit-ma:
  container_name: fluent-bit-ma
  hostname: fluent-bit-ma
  image: it-infradev.repository.avp.ru:443/shared/fluent-bit:<version>
  restart: unless-stopped

  depends_on:
    - django-ma-app
    - apache-ma-rproxy

  volumes:
    - ./fluent-bit:/fluent-bit/etc:ro

    # Docker logs
    - /var/lib/docker/containers:/var/lib/docker/containers:ro

    # Apache logs
    - ./logs/apache2:/logs/apache2:ro

    # Если понадобится читать Django из файлов
    #- ./logs/django:/logs/django:ro

    # База состояния tail
    - ./fluent-bit-state:/var/fluent-bit

  environment:
    ELK_ENV: {{ branch }}

  networks:
    - MailArchive
Шаг 2. Настроить INPUT
Docker
[INPUT]
    Name tail
    Path /var/lib/docker/containers/*/*-json.log

    Parser docker

    Tag docker

    DB /var/fluent-bit/docker.db

    Read_from_Head On

Это автоматически соберет

Django
Celery Worker
Celery Beat
Kerberos
Redis
Exporters
Apache access
[INPUT]
    Name tail

    Path /logs/apache2/mailarchive_access.log

    Parser apache2

    Tag apache.access

    DB /var/fluent-bit/apache-access.db
Apache error
[INPUT]
    Name tail

    Path /logs/apache2/mailarchive_error.log

    Tag apache.error

    DB /var/fluent-bit/apache-error.db
Шаг 3. Парсеры

Подключить

[SERVICE]

    Parsers_File parsers.conf

И создать минимум два парсера

[PARSER]
    Name docker
    Format json

    Time_Key time
    Time_Format %Y-%m-%dT%H:%M:%S.%LZ
    Time_Keep On

и

[PARSER]
    Name apache2

    Format regex

    Regex ^(?<host>[^ ]*) [^ ]* [^ ]* \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>\d{3}) (?<size>\d+|-)$

    Time_Key time

    Time_Format %d/%b/%Y:%H:%M:%S %z
Шаг 4. Добавить полезные поля

Например

[FILTER]

    Name modify

    Match *

    Add application mailarchive

    Add environment {{ branch }}

Тогда каждая запись будет содержать

{
    "application": "mailarchive",
    "environment": "dev"
}

или

{
    "application": "mailarchive",
    "environment": "stage"
}
Шаг 5. Отправка в OpenSearch

Я бы использовал Logstash Format.

[OUTPUT]

    Name opensearch

    Match *

    Host {{ elk_host }}

    Port 9200

    HTTP_User {{ elk_user }}
    HTTP_Passwd {{ elk_password }}

    tls on
    tls.verify off

    Logstash_Format On

    Logstash_Prefix mailarchive-{{ branch }}

    Suppress_Type_Name On

Получатся индексы

mailarchive-dev-2026.08.05

mailarchive-stage-2026.08.05

mailarchive-prod-2026.08.05
Шаг 6. Проверить работу

Запустить

docker compose up -d fluent-bit-ma

Посмотреть

docker logs -f fluent-bit-ma

Там должны появиться сообщения о начале чтения логов и успешной отправке данных.

Шаг 7. Проверить OpenSearch

Убедиться, что появились индексы

mailarchive-dev-*

или

mailarchive-stage-*

и что документы содержат поля вроде:

application
environment
log
container_name (если добавишь обогащение)
@timestamp
Шаг 8. Что можно улучшить позже

После того как базовая схема заработает, можно добавить:

фильтрацию шумных контейнеров (redis, node-exporter, cadvisor и т.п.), чтобы не засорять индексы;
раздельные индексы для apache.access, apache.error и логов приложений, если это потребуется для аналитики;
обогащение Docker-логов метаданными контейнера (имя сервиса, образ, compose-проект) через Docker API или дополнительные фильтры;
парсинг Django-логов в структурированные поля, если они имеют стабильный формат.
Итоговая архитектура
                    Docker JSON logs
          +--------------------------------+
          | Django                         |
          | Celery Worker                  |
          | Celery Beat                    |
          | Kerberos                       |
          +--------------------------------+
                     │
                     │
                     ▼
                Fluent Bit
                     ▲
                     │
      Apache access/error log files
                     │
                     ▼
                OpenSearch
                     │
                     ▼
                   Kibana

Для твоего текущего проекта это выглядит наиболее практичным: минимальные изменения в существующих контейнерах, сохранение файловых логов Apache для локальной диагностики и единая отправка всех журналов в OpenSearch.

А где мне настраивать INPUT? 
Просто все блоками кидать в конфиг Fluentbit?

Да, именно так. Fluent Bit устроен довольно просто: весь пайплайн описывается в конфигурационных файлах.

Обычно делают так:

fluent-bit/
├── fluent-bit.conf
├── parsers.conf
└── scripts/

Основной файл — fluent-bit.conf. В нем просто последовательно идут секции:

[SERVICE]

...

[INPUT]
...

[INPUT]
...

[FILTER]
...

[FILTER]
...

[OUTPUT]
...

То есть ты действительно просто добавляешь блоки один за другим.

Например, для твоего проекта fluent-bit.conf на первом этапе мог бы выглядеть так:

[SERVICE]
    Flush         5
    Daemon        Off
    Log_Level     info
    Parsers_File  parsers.conf

#
# Docker контейнеры
#
[INPUT]
    Name              tail
    Path              /var/lib/docker/containers/*/*-json.log
    Parser            docker
    Tag               docker
    DB                /var/fluent-bit/docker.db
    Read_from_Head    On

#
# Apache access.log
#
[INPUT]
    Name              tail
    Path              /logs/apache2/mailarchive_access.log
    Parser            apache2
    Tag               apache.access
    DB                /var/fluent-bit/apache-access.db

#
# Apache error.log
#
[INPUT]
    Name              tail
    Path              /logs/apache2/mailarchive_error.log
    Tag               apache.error
    DB                /var/fluent-bit/apache-error.db

#
# Добавляем общие поля
#
[FILTER]
    Name    modify
    Match   *
    Add     application mailarchive
    Add     environment {{ branch }}

#
# Отправляем в ELK
#
[OUTPUT]
    Name              opensearch
    Match             *
    Host              {{ elk_host }}
    Port              9200

    HTTP_User         {{ elk_user }}
    HTTP_Passwd       {{ elk_password }}

    tls               on
    tls.verify        off

    Logstash_Format   On
    Logstash_Prefix   mailarchive-{{ branch }}

    Suppress_Type_Name On

А parsers.conf будет отдельным файлом, например:

[PARSER]
    Name        docker
    Format      json
    Time_Key    time
    Time_Format %Y-%m-%dT%H:%M:%S.%LZ
    Time_Keep   On

[PARSER]
    Name        apache2
    Format      regex
    ...
Я бы предложил сделать в несколько этапов

Не пытаться сразу добавить FILTER, Lua, парсинг и прочее.

Этап 1 (15 минут):

один INPUT для Docker;
один INPUT для Apache access;
один INPUT для Apache error;
один OUTPUT в OpenSearch.

Проверить, что логи вообще появились в OpenSearch.

Этап 2:

добавить парсеры;
добавить поля environment, application;
при необходимости исключить лишние контейнеры (redis, cadvisor, node-exporter).

Так гораздо проще отлаживать: если что-то не работает, сразу понятно, проблема в чтении логов, парсинге или отправке.