Передача логов с Container Optimized Image в Yandex Cloud Logging
Обработчик логов Fluent Bit
Чтобы настроить передачу логов с ВМ, созданной из образа Container Optimized Image:
- Создайте приложение, генерирующее логи.
- Создайте Docker-образ и загрузите его в реестр.
- Настройте Fluent Bit.
- Создайте ВМ из образа Container Optimized Image.
Перед началом работы
- Создайте сервисный аккаунт с ролями
logging.writer
иcontainer-registry.images.puller
на каталог. - Создайте реестр Yandex Container Registry.
- Создайте облачную сеть. При создании выберите опцию Создать подсети.
Создайте приложение, генерирующее логи
Создайте файл logs.py
:
import logging
import random
import sys
import time
import uuid
logger = logging.getLogger(__name__)
# Задаем формат логов.
formatter = logging.Formatter(
'[req_id=%(req_id)s] [%(levelname)s] %(code)d %(message)s'
)
handler = logging.StreamHandler(stream=sys.stdout)
handler.setFormatter(formatter)
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:
req_id = uuid.uuid4()
# Создаем пару — код и значение URL.
path, code = fake_url()
extra = {"code": code, "req_id": req_id}
# Если код 200, пишем в лог с уровнем Info.
if code == 200:
logger.info(
'Path: %s',
path,
extra=extra,
)
# Иначе с уровнем Error.
else:
logger.error(
'Error: %s',
path,
extra=extra,
)
# Чтобы было несколько сообщений с одинаковым request id, в 30% случаев пишем вторую запись в лог с уровнем Debug.
if random.random() > 0.7:
logger.debug("some additional debug log record %f", random.random(), extra=extra)
# Ждем одну секунду, чтобы не засорять журнал.
time.sleep(1)
Создайте Docker-образ и загрузите его в реестр
-
Создайте файл Dockerfile и добавьте в него следующие строки:
FROM python:3.10 WORKDIR /usr/src/app COPY logs.py . CMD [ "python", "./logs.py" ]
Dockerfile описывает Docker-образ, который содержит приложение, генерирующее логи.
-
Соберите Docker-образ:
docker build . \ -t cr.yandex/<идентификатор_реестра>/coi:logs
-
Аутентифицируйтесь в реестре и загрузите в него Docker-образ:
docker push cr.yandex/<идентификатор_реестра>/coi:logs
Настройте Fluent Bit
-
Создайте файл
spec.yaml
. Он описывает спецификацию двух контейнеров: с приложением, генерирующим логи, и агентом Fluent Bit.Укажите в поле:
image
— URL Docker-образа. Чтобы узнать его, в консоли управления перейдите на страницу Обзор Docker-образа и скопируйте значение из поля Теги.YC_GROUP_ID
— идентификатор лог-группы по умолчаниюdefault
.
В секции
fluentbit
, в полеimage
, указан актуальный на момент написания инструкции образ контейнера с агентом Fluent Bit. Список всех доступных образов можно найти по ссылке .version: '3.7' services: logs: container_name: logs-app image: <URL_Docker-образа> restart: always depends_on: - fluentbit logging: # Fluent Bit понимает логи в этом формате. driver: fluentd options: # Fluent Bit слушает логи на порту 24224. fluentd-address: localhost:24224 # Теги используются для маршрутизации логов. tag: app.logs fluentbit: container_name: fluentbit image: cr.yandex/yc/fluent-bit-plugin-yandex:v1.0.3-fluent-bit-1.8.6 ports: - 24224:24224 - 24224:24224/udp restart: always environment: YC_GROUP_ID: <идентификатор_лог-группы> volumes: - /etc/fluentbit/fluentbit.conf:/fluent-bit/etc/fluent-bit.conf - /etc/fluentbit/parsers.conf:/fluent-bit/etc/parsers.conf
-
Создайте файл
user-data.yaml
. Он описывает правила, по которым будут читаться логи контейнера. Если необходимо, в секцииusers
измените имя пользователя и SSH-ключ. Подробнее о том, как сгенерировать SSH-ключи.#cloud-config write_files: - content: | [SERVICE] Flush 1 Log_File /var/log/fluentbit.log Log_Level error Daemon off Parsers_File /fluent-bit/etc/parsers.conf [FILTER] Name parser Match app.logs Key_Name log Parser app_log_parser Reserve_Data On [INPUT] Name forward Listen 0.0.0.0 Port 24224 Buffer_Chunk_Size 1M Buffer_Max_Size 6M [OUTPUT] Name yc-logging Match * group_id ${YC_GROUP_ID} message_key text level_key severity default_level WARN authorization instance-service-account path: /etc/fluentbit/fluentbit.conf - content: | [PARSER] Name app_log_parser Format regex Regex ^\[req_id=(?<req_id>[0-9a-fA-F\-]+)\] \[(?<severity>.*)\] (?<code>\d+) (?<text>.*)$ Types code:integer path: /etc/fluentbit/parsers.conf users: - name: username groups: sudo shell: /bin/bash sudo: 'ALL=(ALL) NOPASSWD:ALL' ssh_authorized_keys: - ssh-ed25519 AAAA
В секции
SERVICE
указаны настройки приложения Fluent Bit. Подробнее о настройках .В секции
INPUT
указано, откуда и как забирать логи. Для работы с логами в формате Fluentd и Fluent Bit используется протоколforward
. Fluent Bit слушает логи на порту 24224.В секции
PARSER
описан парсерregex
. В нем задано регулярное выражение, с помощью которого обрабатываются записи:req_id
— уникальный идентификатор запроса.severity
— уровень логирования.code
— HTTP-код ответа.text
— весь остальной текст.
В секции
FILTER
указано, что ищутся только записи с тегомapp.logs
. Полеlog
каждой записи обрабатывается парсеромregex
, все остальные поля сохраняются вReserve_Data On
.
Создайте ВМ из образа Container Optimized Image
Укажите в поле:
--zone
— зону доступности, напримерru-central1-a
.--subnet-name
— имя подсети в указанной зоне.--service-account-name
— имя сервисного аккаунта.
IMAGE_ID=$(yc compute image get-latest-from-family container-optimized-image --folder-id standard-images --format=json | jq -r .id)
yc compute instance create \
--name coi-vm \
--zone=<зона> \
--network-interface subnet-name=<имя_подсети>,nat-ip-version=ipv4 \
--metadata-from-file user-data=user-data.yaml,docker-compose=spec.yaml \
--create-boot-disk image-id=${IMAGE_ID} \
--service-account-name <имя_сервисного_аккаунта>
Посмотрите логи
- В консоли управления
перейдите в каталог, в котором находится лог-группаdefault
, идентификатор которой вы указали в файлеspec.yaml
. - Выберите сервис Cloud Logging.
- Выберите лог-группу
default
. На открывшейся странице отобразятся записи.
Если у вас еще нет интерфейса командной строки Yandex Cloud, установите и инициализируйте его.
По умолчанию используется каталог, указанный в профиле CLI. Вы можете указать другой каталог с помощью параметра --folder-name
или --folder-id
.
Чтобы посмотреть записи в лог-группе, выполните команду:
yc logging read --group-id=<идентификатор_лог-группы>
Где --group-id
— идентификатор лог-группы default
, который указан в файле spec.yaml
.
Посмотреть записи в лог-группе можно с помощью вызова gRPC API LogReadingService/Read.
Удалите созданные ресурсы
Если созданные ресурсы вам больше не нужны, удалите их: