Сбор логов с помощью FluentBit

В разделе представлена реализация интеграции между YDB и инструментом захвата логов FluentBit с целью сохранения данных логов в YDB для последующего просмотра или анализа.

Введение

FluentBit – инструмент, который может собирать текстовые данные, манипулировать ими (изменять, преобразовывать, объединять) и отправлять в различные хранилища для дальнейшей обработки. Для поставки логов в таблицы YDB с помощью FluentBit разработана библиотека-плагин. Исходный код библиотеки доступен здесь.

Чтобы развернуть схему доставки логов с помощью FluentBit с последующим сохранением их в YDB, необходимо:

  1. Создать таблицы YDB для хранения логов
  2. Развернуть FluentBit и библиотеку-плагин для поддержки YDB
  3. Сконфигурировать FluentBit для сбора и обработки логов в соответствии с документацией
  4. Настроить сохранение логов в таблицы YDB

Создание таблиц для хранения логов

Для сохранения логов необходимо создать таблицы в выбранной базе данных YDB. Структура создаваемых таблиц определяется набором полей конкретного лога, поставляемого с помощью FluentBit. Типичный набор полей включает в себя:

  • метку времени;
  • уровень критичности сообщения;
  • имя хоста, с которого получено сообщение;
  • наименование сервиса;
  • текст сообщения либо его структурированные данные в формате JSON.

В таблицах YDB обязательно наличие первичного ключа, уникально идентифицирующего конкретную запись. Поскольку метка времени не обеспечивает уникальной идентификации записи лога, в состав хранимых полей обычно добавляют значение хеш-кода над данными сообщения, которое включают в состав первичного ключа.

Поддерживается хранение логов как в строковых, так и колоночных таблицах. Рекомендуется использование колоночных таблиц, как обеспечивающих более эффективное сканирование данных при выполнении запросов.

Пример команды создания строковой таблицы для хранения логов:

CREATE TABLE `fluent-bit/log` (
    `timestamp`         Timestamp NOT NULL,
    `hostname`          Text NOT NULL,
    `input`             Text NOT NULL,
    `datahash`          Uint64 NOT NULL,
    `level`             Text NULL,
    `message`           Text NULL,
    `other`             JsonDocument NULL,
    PRIMARY KEY (
         `datahash`, `timestamp`, `hostname`, `input`
    )
);

Пример команды создания колоночной таблицы для хранения логов:

CREATE TABLE `fluent-bit/log` (
    `timestamp`         Timestamp NOT NULL,
    `hostname`          Text NOT NULL,
    `input`             Text NOT NULL,
    `datahash`          Uint64 NOT NULL,
    `level`             Text NULL,
    `message`           Text NULL,
    `other`             JsonDocument NULL,
    PRIMARY KEY (
         `timestamp`, `hostname`, `input`, `datahash`
    )
) PARTITION BY HASH(`timestamp`, `hostname`, `input`)
  WITH (STORE = COLUMN);

Команда создание колоночной таблицы отличается от команды создания строковой таблицы следующими деталями:

  • указанием в двух последних строках колоночного режима хранения и отдельного ключа партиционирования;
  • колонка timestamp указана первой в составе первичного ключа таблицы, что является оптимальным и рекомендованным для колоночных таблиц, и не рекомендовано для строчных таблиц. См. также рекомендации по выбору первичного ключа для колоночных таблиц и для строчных таблиц.

Опционально можно настроить TTL для строк таблицы, ограничив срок хранения и обеспечив автоматическое удаление устаревших данных. Для этого при создании таблицы в секции WITH указываются настройки TTL, например TTL = Interval("P14D") ON timestamp устанавливает срок хранения записей в 14 дней на основе значения поля timestamp.

Развертывание FluentBit и настройка сбора логов

Развертывание FluentBit осуществляется в соответствии с собственной документацией.

Плагин для поддержки YDB в FluentBit доступен в репозитории вместе с инструкциями по сборке. Для установки в формате контейнера предусмотрен Docker-образ ghcr.io/ydb-platform/fluent-bit-ydb.

Общая логика и порядок настройки процессов получения, обработки и поставки логов в среде FluentBit изложены в документации FluentBit.

Настройка записи логов в YDB

Перед использованием выходного плагина для YDB, его необходимо включить в настройках FluentBit. Перечень используемых плагинов FluentBit определяется в отдельном файле (например, plugins.conf), путь к которому устанавливается параметром plugins_file секции SERVICE основного файла настроек FluentBit. Пример файла плагинов со ссылкой на библиотеку плагина для записи в YDB (путь к библиотеке в вашей системе может отличаться):

# plugins.conf
[PLUGINS]
    Path /usr/lib/fluent-bit/out_ydb.so

Состав конфигурационных параметров, поддерживаемых выходным плагином YDB для FluentBit, приведен в таблице ниже.

Ключ Описание
Name Тип плагина, константа ydb
Match (опционально) Выражение для отбора тегов записей, направляемых в YDB
ConnectionURL URL для подключения к БД, включая протокол, хост, номер порта и путь к базе данных (см. документацию)
TablePath Путь к таблице, начиная от корня базы данных (пример: fluent-bit/log)
Columns JSON-структура, состоящая из пар имен колонок, и устанавливающая соответствие между исходными колонками записи и целевыми колонками таблицы. Может включать перечисленные далее служебные псевдо-колонки
CredentialsAnonymous Устанавливается в значение 1 для использования анонимной аутентификации
CredentialsToken Значение токена аутентификации, для использования аутентификации непосредственно по значению токена
CredentialsYcMetadata Устанавливается в значение 1 для использования аутентификации через метаданные виртуальной машины
CredentialsStatic Логин и пароль для использования статического режима аутентификации, указанные в формате Логин:Пароль@
CredentialsYcServiceAccountKeyFile Путь к файлу ключа сервисного аккаунта, для аутентификации по ключу сервисного аккаунта
CredentialsYcServiceAccountKeyJson JSON-данные ключа сервисного аккаунта, для аутентификации по ключу сервисного аккаунта без указания имени файла (удобно в среде K8s)
Certificates Путь к файлу с сертификатом CA, либо непосредственно содержимое сертификата CA
LogLevel Уровень логирования для плагина, одно из значений disabled (по умолчанию), trace, debug, info, warn, error, fatal либо panic

Для использования в карте сопоставления колонок (параметр Columns), в дополнение к полям записи FluentBit, доступны следующие служебные псевдо-колонки:

  • .timestamp - метка времени сообщения (обязательная)
  • .input - имя входного потока сообщений (обязательная)
  • .hash - uint64 хеш-код, вычисленный над всеми полями сообщения, кроме псевдо-колонок (опциональная)
  • .other - документ JSON, содержащий все поля сообщения, которые не были явным образом сопоставлены с конкретной выходной колонкой (опциональная)

Пример значения параметра Columns:

{".timestamp": "timestamp", ".input": "input", ".hash": "datahash", "log": "message", "level": "level", "host": "hostname", ".other": "other"}

Сбор логов в кластере Kubernetes

FluentBit очень часто используется для сбора логов в кластерах Kubernetes. Принципиальная схема доставки логов запущенных приложений в Kubernetes с помощью FluentBit с последующим сохранением их в YDB выглядит следующим образом:

FluentBit in Kubernetes cluster

На этой схеме:

  • Поды приложений пишут логи в stdout/stderr

  • Текст из stdout/stderr сохраняется в виде файлов на рабочих узлах Kubernetes

  • Под с FluentBit:

    • Монтирует каталог с лог-файлами рабочего узла Kubernetes
    • Вычитывает из лог-файлов содержимое
    • Обогащает записи дополнительными метаданными
    • Сохраняет записи в базу данных YDB

Таблица для хранения логов Kubernetes

Структура таблицы YDB для хранения логов Kubernetes:

CREATE TABLE `fluent-bit/log` (
    `timestamp`         Timestamp NOT NULL,
    `file`              Text NOT NULL,
    `pipe`              Text NOT NULL,
    `message`           Text NULL,
    `datahash`          Uint64 NOT NULL,
    `message_parsed`    JSON NULL,
    `kubernetes`        JSON NULL,

    PRIMARY KEY (
         `timestamp`, `file`, `datahash`
    )
) PARTITION BY HASH(`timestamp`, `file`)
  WITH (STORE = COLUMN, TTL = Interval("P14D") ON `timestamp`);

Предназначение колонок:

  • timestamp – временная метка лога;
  • file – название источника, из которого прочитан лог. В случае Kubernetes это будет имя файла, на worker ноде, в который записываются логи определенного pod;
  • pipe – stdout или stderr поток, куда была осуществлена запись на уровне приложения;
  • datahash – хеш-код, вычисленный над записью лога;
  • message – текстовая часть записи лога;
  • message_parsed – структурированное представление записи лога, если его удалось разобрать из текстовой части с помощью настроенных парсеров FluentBit;
  • kubernetes – информация о pod, включая название, неймспейс и аннотации.

Опционально, можно установить TTL для строк таблицы, как показано в примере выше.

Конфигурация FluentBit

Перед развертыванием FluentBit в среде Kubernetes необходимо подготовить файл настроек (обычно values.yaml), в котором указываются параметры сбора и обработки логов. В этом разделе представлены необходимые пояснения по заполнению этого файла с примерами.

Необходимо указать репозиторий и версию образа контейнера FluentBit:

image:
  repository: ghcr.io/ydb-platform/fluent-bit-ydb
  tag: latest

В данном образе, по сравнению со стандартным, добавлена библиотека-плагин для поддержки YDB.

В следующих строках определены правила монтирования папок с логами в поды FluentBit:

volumeMounts:
  - name: config
    mountPath: /fluent-bit/etc/conf

daemonSetVolumes:
  - name: varlog
    hostPath:
      path: /var/log
  - name: varlibcontainers
    hostPath:
      path: /var/lib/containerd/containers
  - name: etcmachineid
    hostPath:
      path: /etc/machine-id
      type: File

daemonSetVolumeMounts:
  - name: varlog
    mountPath: /var/log
  - name: varlibcontainers
    mountPath: /var/lib/containerd/containers
    readOnly: true
  - name: etcmachineid
    mountPath: /etc/machine-id
    readOnly: true

Также необходимо переопределить команду и аргументы запуска FluentBit:

command:
  - /fluent-bit/bin/fluent-bit

args:
  - --workdir=/fluent-bit/etc
  - --plugin=/fluent-bit/lib/out_ydb.so
  - --config=/fluent-bit/etc/conf/fluent-bit.conf

Требуется настроить пайплайн сбора, преобразования и доставки логов:

config:
  inputs: |
    [INPUT]
        Name tail
        Path /var/log/containers/*.log
        multiline.parser cri
        Tag kube.*
        Mem_Buf_Limit 5MB
        Skip_Long_Lines On

  filters: |
    [FILTER]
        Name kubernetes
        Match kube.*
        Keep_Log On
        Merge_Log On
        Merge_Log_Key log_parsed
        K8S-Logging.Parser On
        K8S-Logging.Exclude On

    [FILTER]
        Name modify
        Match kube.*
        Remove time
        Remove _p

  outputs: |
    [OUTPUT]
        Name ydb
        Match kube.*
        TablePath fluent-bit/log
        Columns {".timestamp":"timestamp",".input":"file",".hash":"datahash","log":"message","log_parsed":"message_structured","stream":"pipe","kubernetes":"metadata"}
        ConnectionURL ${OUTPUT_YDB_CONNECTION_URL}
        CredentialsToken ${OUTPUT_YDB_CREDENTIALS_TOKEN}

Описание конфигурационных блоков:

  • inputs - в этом блоке указываются откуда считывать и как разбирать логи. В данном случае, будет осуществляться чтение файликов *.log из папки /var/log/containers/, которая была смонтирована с хоста
  • filters - в этом блоке указывается как будет осуществляться обработка логов. В данном случае: для каждого лога будут найдены соответствующие метаданные (в помощью kubernetes фильтра), а также, вырезаны неиспользуемые поля (_p, time)
  • outputs - в этом блоке указывается, куда будут отгружены логи. В данном случае в таблицу fluent-bit/log в базе данных YDB. Параметры подключения к базе данных (в данном случае ConnectionURL и CredentialsToken) задаются с помощью переменных окружения – OUTPUT_YDB_CONNECTION_URL, OUTPUT_YDB_CREDENTIALS_TOKEN. При необходимости настройки аутентификации и состав используемых переменных окружения корректируются в зависимости от настроек используемого кластера YDB.

Переменные окружения определяются следующим образом:

env:
  - name: OUTPUT_YDB_CONNECTION_URL
    value: grpc://ydb-endpoint:2135/path/to/database
  - name: OUTPUT_YDB_CREDENTIALS_TOKEN
    valueFrom:
      secretKeyRef:
        key: token
        name: fluent-bit-ydb-plugin-token

Данные аутентификации необходимо сохранить в конфигурации кластера Kubernetes в виде секрета. Пример команды для создания секрета:

kubectl create secret -n ydb-fluent-bit-integration generic fluent-bit-ydb-plugin-token --from-literal=token=<YDB TOKEN>

Развертывание FluentBit в кластере Kubernetes

HELM – это инструмент пакетирования и установки приложений в кластере Kubernetes. Для развертывания FluentBit необходимо добавить репозиторий с соответствующим чартом (сценарием установки) с помощью команды:

helm repo add fluent https://fluent.github.io/helm-charts

После этого установка FluentBit в кластер Kubernetes выполняется с помощью следующей команды:

helm upgrade --install fluent-bit fluent/fluent-bit \
  --version 0.37.1 \
  --namespace ydb-fluent-bit-integration \
  --create-namespace \
  --values values.yaml

В команде выше в аргументе --values указывается ранее подготовленный файл с настройками FluentBit.

Проверка установки

Проверяем что FluentBit запустился, читая его логи (должны отсутствовать записи уровня [error]):

kubectl logs -n ydb-fluent-bit-integration -l app.kubernetes.io/instance=fluent-bit

Проверяем, что записи в таблице YDB есть (появятся спустя примерно несколько минут после запуска FluentBit):

SELECT * FROM `fluent-bit/log` LIMIT 10 ORDER BY `timestamp` DESC

Очистка ресурсов

Для удаления FluentBit достаточно удалить Kubernetes namespace, в который была выполнена установка:

kubectl delete namespace ydb-fluent-bit-integration

Далее можно удалить таблицу с логами в базе данных YDB:

DROP TABLE `fluent-bit/log`
Предыдущая
Следующая