Доставка логов с ВМ из systemd в Yandex Cloud Logging

от автора

Одна из самых частых и понятных задач в разработке и эксплуатации — доставка логов. И дальше в статье мы с вами используем Fluent Bit для доставки логов из виртуальной машины в сервис Yandex Cloud Logging.

Шаг 1. Пишем логи в systemd

Возможно, у вас уже есть сервис, поставку чьих логов вы хотели бы настроить. Тогда переходите к шагу 2. Если же нет, то можно воспользоваться следующим кодом на Python, чтобы генерировать тестовые логи, которые впоследствии мы будем отправлять.

Итак, нам понадобится Python 3.6 и выше.

1. Заведём директорию, куда сложим все необходимые файлы:

sudo mkdir /usr/local/bin/logtest cd /usr/local/bin/logtest

2. Добавим следующий код в файл logtest.py:

import logging import random import sys import time  from systemdlogging.toolbox import check_for_systemd from systemdlogging.toolbox import SystemdFormatter from systemdlogging.toolbox import SystemdHandler  # Следующие несколько строк могут быть заменены на вызов `systemdlogging.toolbox.init_systemd_logging` # Но я приведу этот код полностью в целях демонстрации.  # Проверяем доступен ли systemd systemd_ok = check_for_systemd()  if systemd_ok:     handler = SystemdHandler()     # syslog_id: значение которое будет использовано в поле SYSLOG_IDENTIFIER.     handler.syslog_id = ''     handler.setFormatter(SystemdFormatter())      # получаем инстанс объекта логгера     logger = logging.getLogger()     logger.addHandler(handler)  else:     # Ветка будет использована для локальной отладки, если у вас нет systemd (MacOS, Windows)     logger = logging.getLogger(__name__)     # Выводить логи будем в STDOUT     handler = logging.StreamHandler(stream=sys.stdout)     handler.setFormatter(logging.Formatter(         '[%(levelname)s] %(code)d %(message)s'     ))     logger.addHandler(handler)  # Опционально можно настроить уровень логирования по умолчанию logger.setLevel(logging.DEBUG)  # Мы могли бы обойтись и простым логированием случайных чисел, но я решил генерировать URL-подобные значения. PATHS = [     '/',     '/admin',     '/hello',     '/docs', ]  PARAMS = [     'foo',     'bar',     'query',     'search',     None ]   def fake_url():     path = random.choice(PATHS)     param = random.choice(PARAMS)     if param:         val = random.randint(0, 100)         param += '=%s' % val     code = random.choices([200, 400, 404, 500], weights=[10, 2, 2, 1])[0]     return '?'.join(filter(None, [path, param])), code   if __name__ == '__main__':     while True:         # создаем пару код и значение URL         path, code = fake_url()         # Если код 200, то пишем в  лог с уровнем Info         # Cloud Logging ориентируется на текстовое написание уровня логирования, поэтому в `context` передадим         # дополнительное значение `SEVERITY`. Оно попадет в journald и сможет быть прочитано в плагине yc-logging.         # В продуктовом коде это стоит вынести в `SystemdHandler`, чтобы не потерять,         # но в примере я оставлю так для наглядности.         if code == 200:             logger.info(                 'Path: %s',                 path,                 extra={"code": code, "context": {"SEVERITY": "info"}},             )         # Иначе с уровнем Error         else:             logger.error(                 'Error: %s',                 path,                 extra={"code": code, "context": {"SEVERITY": "error"}},             )          # Ждем 1 секунду, чтобы излишне не засорять журнал         time.sleep(1)

3. Заведём virtualenv и установим в него все нужные зависимости:

sudo apt install python3-pip python3.8-venv python -m venv venv  source venv/bin/activate pip3 install systemd-logging

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

#!/bin/bash  SCRIPT_PATH=$(dirname "$(realpath "$0")") . "$SCRIPT_PATH/venv/bin/activate" python "$SCRIPT_PATH/logtest.py"

4. Создадим файл logtest.service с описанием нашего сервиса:

[Unit] Description=Sample to show logging from a Python application to systemd After=network.target  [Service] Type=simple ExecStart=/usr/local/bin/logtest/logtest.sh Restart=on-abort  [Install] WantedBy=multi-user.target

5. Этот файл может лежать в любом каталоге, который вам нравится. Я бы предложил положить его с исходным кодом на Python для этого приложения. Но чтобы systemd нашёл файл, нам нужно придерживаться соглашения о том, куда складывать unit-файлы. Не буду вдаваться в подробности о systemd (тут на целую книгу хватит, это выходит за рамки поста в блоге) — убедимся, что наш файл модуля имеет symlink в /etc/systemd/system. Для этого выполним команду:

sudo ln -s "$(pwd)/logtest.service" \   /etc/systemd/system/logtest.service

6. Теперь можно перезагрузить systemd:

sudo systemctl daemon-reload

7. Проверим, что всё ОК:

systemctl status logtest.service

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

8. Запустим systemd:

systemctl start logtest.service

Теперь, если снова посмотреть статус, то там должно быть active (running).

Шаг 2. Ставим Fluent Bit

Но сначала проясним пару моментов.

И там и там птичка, так в чём же разница?
И там и там птичка, так в чём же разница?

Fluent Bit vs Fluentd

Чтобы упростить работу с логами, когда-то появился Fluentd. Он был написан на Ruby и со временем вырос в целую экосистему, которая включает и Fluent Bit. Быстрое сравнение приведено в таблице:

https://docs.fluentbit.io/manual/about/fluentd-and-fluent-bit
https://docs.fluentbit.io/manual/about/fluentd-and-fluent-bit

Как видно, для установки Fluent Bit не нужны никакие зависимости типа Ruby. И хотя к нему есть меньше плагинов, чем для Fluentd, зато он потребляет значительно меньше памяти.

Теперь разберёмся, как его поставить

1. Добавим GPG-ключ, которым подписаны пакеты в репозитории Fluent Bit.

$ wget -qO - https://packages.fluentbit.io/fluentbit.key | sudo apt-key add -

2. В Ubuntu добавим в файл /etc/apt/sources.list строчку:

deb https://packages.fluentbit.io/ubuntu/focal focal main

3. Затем обновим индексы:

sudo apt-get update

4. Теперь можно установить последнюю версию td-agent-bit:

sudo apt-get install td-agent-bit

5. После этого его остаётся только перезапустить:

sudo service td-agent-bit start

6. Что всё ОК, можно проверить командой:

sudo service td-agent-bit status

Там должно быть active (running).

Шаг 3. Подключаем плагин

Fluent Bit поддерживает плагины, написанные на Go. Это экспериментальный, но вполне рабочий API.

1. Итак, клонируем репозиторий с кодом плагина:

git clone https://github.com/yandex-cloud/fluent-bit-plugin-yandex.git

2. Для начала нам понадобится Go. Инструкция по установке тут.

3. Теперь скомпилируем библиотеку:

export fluent_bit_version=1.8.6 export plugin_version=dev CGO_ENABLED=1 go build     -buildmode=c-shared \   -o ./yc-logging.so \   -ldflags "-X main.PluginVersion=${plugin_version}" \   -ldflags "-X main.FluentBitVersion=${fluent_bit_version}"

4. Копируем полученную библиотеку:

sudo cp yc-logging.so /usr/lib/td-agent-bit/yc-logging.so

5. И регистрируем её в файле с конфигурацией плагинов /etc/td-agent-bit/plugins.conf:

[PLUGINS]     Path /usr/lib/td-agent-bit/yc-logging.so

6. Вносим изменения в конфиг самого сервиса. folder_id укажите свой. Если к ВМ привязан service account с правами писать в Yandex Cloud Logging, то authorization укажите instance-service-account. Другие варианты авторизации и значение остальных параметров можно посмотреть тут.

[INPUT]     Name  systemd     Tag   host.*     Systemd_Filter  _SYSTEMD_UNIT=logtest.service  [OUTPUT]     Name            yc-logging     Match           *     resource_type   logtest     folder_id       b1g***     message_key     MESSAGE     level_key       SEVERITY     default_level   WARN     authorization   instance-service-account

7. Перезагружаем сервис td-agent-bit:

sudo systemctl restart td-agent-bit

8. Отлично. Теперь можно убедиться, что логи поступают:

Yandex Cloud Logging
Yandex Cloud Logging

P. S. Yandex Cloud Logging — это serverless-сервис в Yandex.Cloud. Если вам интересна экосистема Serverless-сервисов и все, что с этим связано, заходите в сообщество в Telegram, где можно обсудить serverless в целом.

Настройка работы Fluent Bit в контейнерах ещё проще. Но о ней я расскажу в следующей публикации. 


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


Комментарии

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

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