Организация сбора и парсинга логов при помощи Filebeat

от автора

В комментариях к моему туториалу, рассказывающему о парсинге логов с помощью Fluent-bit, было приведено две альтернативы: Filebeat и Vector. Этот туториал рассказывает как организовать сбор и парсинг лог-сообщений при помощи Filebeat.

Цель туториала: Организовать сбор и парсинг лог-сообщений с помощью Filebeat.

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

Кому данная тема интересна, прошу под кат:)

Тестовое приложение будем запускать с помощью docker-compose.

Общая информация

Filebeat — это легковесный доставщик лог-сообщений. Принцип его работы состоит в мониторинге и сборе лог-сообщений из лог-файлов и пересылки их в elasticsearch или logstash для индексирования.

Filebeat состоит из ключевых компонентов:

  • сборщики (harvesters) — отвечают за чтение лог-файлов и отправку лог-сообщений в заданный выходной интерфейс, на каждый лог-файл задается отдельный сборщик;
  • входные интерфейсы (inputs) — отвечают за поиск источников лог-сообщений и управление сборщиками.

Подробнее о принципе работы можно почитать в официальном руководстве.

Организация сбора лог-сообщений

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

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

Сбор лог-сообщений с помощью volume

Для начала клонируем репозиторий. В нем находится тестовое приложение, конфигурационный файл Filebeat и docker-compose.yml.
Настройка сбора лог-сообщений с помощью volume состоит из следующих шагов:

  1. Настройка логгера приложения на запись лог-сообщений в файл:
    app/api/main.py
    logger.add(     "./logs/file.log",     format="app-log - {level} - {message}",     rotation="500 MB" )
  2. Создание volume для хранения лог-файлов вне контейнеров:
    docker-compose.yml

    version: "3.8"  services:   app:     ...     volumes:       # создаем volume, для хранения лог-файлов вне контейнера       - app-logs:/logs    log-shipper:     ...     volumes:       # заменяем конфигурационный файл в контейнере       - ./filebeat.docker.yml:/usr/share/filebeat/filebeat.yml:ro       # подключаем volume с лог-файлами в контейнер       - app-logs:/var/app/log  volumes:   app-logs:

  3. Определение входного и выходного интерфейсов filebeat:
    filebeat.docker.yml

    filebeat.inputs: - type: log   # Определяем путь к лог-файлам   paths:     - /var/app/log/*.log  # Пока будем выводить лог-сообщения в консоль output.console:   pretty: true

    Запускаем тестовое приложение, генерируем лог-сообщения и получаем их в следующем формате:

    { "@timestamp": "2021-04-01T04:02:28.138Z", "@metadata": { "beat": "filebeat", "type": "_doc", "version": "7.12.0" }, "ecs": { "version": "1.8.0" }, "host": { "name": "aa9718a27eb9" }, "message": "app-log - ERROR - [Item not found] - 1", "log": { "offset": 377, "file": {   "path": "/var/app/log/file.log" } }, "input": { "type": "log" }, "agent": { "version": "7.12.0", "hostname": "aa9718a27eb9", "ephemeral_id": "df245ed5-bd04-4eca-8b89-bd0c61169283", "id": "35333344-c3cc-44bf-a4d6-3a7315c328eb", "name": "aa9718a27eb9", "type": "filebeat" } }

Сбор лог-сообщений с помощью входного интерфейса container

Сontainer позволяет осуществлять сбор лог-сообщений с лог-файлов контейнеров.
Настройка сбора лог-сообщений с помощью входного интерфейса container состоит из следующих шагов:

  1. Удаление настроек входного интерфейса log, добавленного на предыдущем этапе, из конфигурационного файла.
  2. Определение входного интерфейса container в конфигурационном файле:
    filebeat.docker.yml

    filebeat.inputs: - type: container   # путь к лог-файлам контейнеров   paths:     - '/var/lib/docker/containers/*/*.log'  # Пока будем выводить лог-сообщения в консоль output.console:   pretty: true

  3. Отключаем volume app-logs из сервисов app и log-shipper и удаляем его, он нам больше не понадобиться.
  4. Подключаем к сервису log-shipper лог-файлы контейнеров и сокет докера:
    docker-compose.yml

    version: "3.8"  services:   app:     ...    log-shipper:     ...     volumes:       # заменяем конфигурационный файл в контейнере       - ./filebeat.docker.yml:/usr/share/filebeat/filebeat.yml:ro       - /var/lib/docker/containers:/var/lib/docker/containers:ro       - /var/run/docker.sock:/var/run/docker.sock:ro

  5. Настройка логгера приложения на запись лог-сообщений в стандартный вывод:
    app/api/main.py
    logger.add(     sys.stdout,     format="app-log - {level} - {message}", )

Входной интерфейс container, настроенный таким образом, будет собирать лог-сообщения со всех контейнеров, однако может потребоваться собирать лог-сообщения только с определенных контейнеров.
Это можно сделать описанным ниже способом.

Сбор лог-сообщений с помощью автообнаружения

При сборе лог-сообщений контейнеров, могут возникнуть трудности, так как контейнеры могут перезапускаться, удаляться и т.д. В связи с этим в filebeat есть автообнаружение контейнеров, с возможностью определения настроек сбора лог-сообщений для каждого обнаруженного контейнера. Механизм автообнаружения состоит из двух частей:

  • шаблона поиска контейнера;
  • конфигурации сбора лог-сообщений.

Подробнее можно почитать здесь.

Настройка состоит из следующих шагов:

  1. Удаление настроек входного интерфейса container, добавленного на предыдущем этапе, из конфигурационного файла.
  2. Определение настроек автообнаружение в конфигурационном файле:
    filebeat.docker.yml

    filebeat.autodiscover:   providers:     # искать docker контейнер     - type: docker       templates:         - condition:             contains:               # имя которого fastapi_app               docker.container.name: fastapi_app           # определим конфигурацию сбора для этого контейнера           config:             - type: container               paths:                 - /var/lib/docker/containers/${data.docker.container.id}/*.log               # исключим лог-сообщения asgi-сервера               exclude_lines: ["^INFO:"]  # Пока будем выводить лог-сообщения в консоль output.console:   pretty: true

Вот и все. Теперь filebeat будет собирать лог-сообщения только с указанного контейнера.

Сбор лог-сообщений с использованием подсказок (hints)

Filebeat поддерживает автообнаружение на основе подсказок.
Он ищет информацию (подсказки) о конфигурации сбора в лейблах контейнера.
Как только контейнер запустится, Filebeat проверит, содержит ли он какие-либо подсказки, и запустит для него сбор с правильной конфигурацией.

Подробнее можно почитать здесь.

Настройка сбора состоит из следующих шагов:

  1. Удаляем шаблон обнаружения сервиса app и включаем подсказки:
    filebeat.docker.yml

    filebeat.autodiscover:   providers:     - type: docker       hints.enabled: true  # Пока будем выводить лог-сообщения в консоль output.console:   pretty: true

  2. Отключаем сбор лог-сообщения для сервиса log-shipper:
    docker-compose.yml

    version: "3.8"  services:   app:     ...    log-shipper:     ...     labels:       co.elastic.logs/enabled: "false"

Парсинг лог-сообщений

Для обработки лог-сообщений в Filebeat есть большое количество обработчиков (processors).
Их можно подключить с помощью лейблов контейнеров либо определить в конфигурационном файле.
Воспользуемся вторым способом.

  1. Для начала очистим лог-сообщения от метаданных. Для этого в конфигурационный файл добавим обработчик drop_fields:
    filebeat.docker.yml

    processors:   - drop_fields:       fields: ["agent", "container", "ecs", "log", "input", "docker", "host"]       ignore_missing: true

    Теперь лог-сообщение выглядит следующим образом:

    {   "@timestamp": "2021-04-01T04:02:28.138Z",   "@metadata": {     "beat": "filebeat",     "type": "_doc",     "version": "7.12.0"   },   "message": "app-log - ERROR - [Item not found] - 1",   "stream": ["stdout"] }

  2. Для отделения лог-сообщений API от лог-сообщений asgi-сервера, добавим к ним тег с помощью обработчика add_tags:
    filebeat.docker.yml

    processors:   - drop_fields:       ...   - add_tags:     when:       contains:         "message": "app-log"     tags: [test-app]     target: "environment"

  3. Структурируем поле message лог-сообщения с помощью обработчика dissect и удалим его с помощью drop_fields:
    filebeat.docker.yml

    processors:   - drop_fields:     ...   - add_tags:     ...  - dissect:      when:        contains:          "message": "app-log"      tokenizer: 'app-log - %{log-level} - [%{event.name}] - %{event.message}'      field: "message"      target_prefix: ""  - drop_fields:      when:        contains:          "message": "app-log"      fields: ["message"]      ignore_missing: true

    Теперь лог-сообщение выглядит следующим образом:

    {   "@timestamp": "2021-04-02T08:29:07.349Z",   "@metadata": {     "beat": "filebeat",     "type": "_doc",     "version": "7.12.0"   },   "log-level": "ERROR",   "event": {     "name": "Item not found",     "message": "Foo"   },   "environment": [     "test-app"   ],   "stream": "stdout" }

Дополнение

Filebeat так же имеет готовые решения сбора и парсинга лог-сообщений для широко используемых инструментов таких, как Nginx, Postgres и т.д.
Они называются модулями.
К примеру для сбора лог-сообщений Nginx, достаточно добавить к его контейнеру лейбл:

  co.elastic.logs/module: "nginx"

и включить подсказки в конфигурационном файле. После этого мы получим готовое решение для сбора и парсинга лог-сообщений + удобный dashboard в Kibana.

Всем спасибо за внимание!

ссылка на оригинал статьи https://habr.com/ru/post/550352/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *