Настройка логирования серверных компонент
Серверные компоненты кластера YTsaurus пишут подробные логи, которые можно использовать для аудита и анализа проблем при эксплуатации. В продакшн-инсталляциях рекомендуется выделять под логи отдельные локации на персистентных томах. Отсутствие логов может существенно ограничить возможности поддержки.
Для анализа работы подсистемы логирования можно воспользоваться prometheus-метриками с префиксом yt_logging_*.
Отладочные логи
Отладочные логи описываются в секции loggers спецификации компонент YTsaurus.
Таблица 1 — Настройки отладочных логгеров YTsaurus
| Поле | Возможные значения | Описание |
|---|---|---|
name |
произвольная строка | Имя логгера; рекомендуется выбирать короткие и понятные названия debug, info и т. п. |
format |
plain_text (default), yson, json |
Формат строки лога. |
minLogLevel |
trace, debug, info, error |
Минимальный уровень записей, попадающих в лог. |
categoriesFilter |
Фильтр, позволяющий писать логи только от некоторых подсистем, см. ниже. | |
writerType |
file, stderr |
Писать логи в файл или в stderr. При записи в stderr настройки ротации будут игнорироваться. |
compression |
none (default), gzip, zstd |
Если задано значение, отличное от none, сервер YTsaurus будет писать сжатые логи. |
useTimestampSuffix |
true, false (default) |
Если true, к имени файла в момент открытия или ротации дописывается timestamp. При этом механизм нумерации старых сегментов при ротации не используется. Имеет смысл только при записи в файл. |
rotationPolicy |
Настройки ротации логов, см. ниже. Имеет смысл только при записи в файл. |
Путь к каталогу, куда будут записываться логи с writerType=file , задаётся в описании локации типа Logs. В случае, если локация Logs не указана, логи будут записываться в каталог /var/log.
Имена файлов с логом формируются следующим образом: [component].[name].log(.[format])(.[compression])(.[timestamp_suffix]). Примеры:
controller-agent.error.logmaster.debug.log.gzipscheduler.info.log.json.zstd.2023-01-01T10:30:00
Записи отладочных логов содержат следующие поля:
instant— время в локальной временной зоне;level— уровень записи:T— trace,D— debug,I— info,W— warning,E— error;category— имя подсистемы, к которой относится запись, напримерChunkClient,ObjectServerилиRpcServer;message— тело сообщения;thread_id— id (или имя) треда, породившего запись; пишется только в форматеplain_text;fiber_id— id файбера, породившего запись; пишется только в форматеplain_text;trace_id— trace_context id, в контексте которого появилась запись; пишется только в форматеplain_text.
Пример записи
2023-09-15 00:00:17,215385 I ExecNode Artifacts prepared (JobId: d15d7d5f-164ff08a-3fe0384-128e0, OperationId: cd56ab80-d21ef5ab-3fe03e8-d05edd49, JobType: Map) Job fff6d4149ccdf656 2bd5c3c9-600a44f5-de721d58-fb905017
Рекомендации по настройке категорий
Существует два вида фильтра по категориям (categoriesFilter):
- включающий — пишутся записи только тех категорий, которые были явно перечислены;
- исключающий — пишутся записи любых категорий, кроме тех, которые были перечислены.
Зачастую, в больших инсталляциях приходится исключать категории Bus и Concurrency.
Примеры фильтров
categoriesFilter:
type: exclude
values: ["Bus", "Concurrency"]
categoriesFilter:
type: include
values: ["Scheduler", "Strategy"]
Структурированные логи
Некоторые компоненты YTsaurus способны писать структурированные логи, которые можно использовать впоследствии для аудита, аналитики и автоматической обработки. Структурированные логи описываются в секции structured_loggers спецификации компонент YTsaurus.
Для описания структурированных логгеров используются те же поля, что и для отладочных логов, кроме:
writerType— не задаётся; структурированные логи всегда пишутся в файл;categoriesFilter— вместо него задаётся обязательное полеcategory— равно одна категория.
Структурированные логи рекомендуется всегда писать в одном из структурированных форматов — json или yson. События в структурированный лог обычно пишутся на уровне info. Набор полей структурированного лога зависит от конкретного типа лога.
Основные типы структурированных логов:
master_access_log— лог доступа к данным; пишется на мастере, категорияAccess;master_security_log— лог событий безопасности, например добавление пользователя в группу или изменение ACL; пишется на мастере, категорияSecurityServer;structured_http_proxy_log— лог запросов к http proxy, по одной строке на запрос; пишется на http proxy, категорияHttpStructuredProxy;chyt_log— лог запросов к CHYT, по одной строке на запрос; пишется на http proxy, категорияClickHouseProxyStructured;structured_rpc_proxy_log— лог запросов к rpc proxy, по одной строке на запрос; пишется на rpc proxy, категорияRpcProxyStructuredMain;scheduler_event_log— лог событий планировщика; пишется планировщиком, категорияSchedulerEventLog;controller_event_log— лог событий контроллер-агента; пишется на контроллер-агенте, категорияControllerEventLog.
Лог доступа к таблице
Иногда возникает необходимость узнать, кто пользуется той или иной таблицей, — например, чтобы оценить последствия ее удаления или перемещения. Задача осложняется тем, что доступ может осуществляться посредством ссылок.
Для решения подобных задач существует специальный лог, в котором журналируются события с узлами Кипариса, которые могут представлять интерес для пользователей.
Лог пишут мастер-серверы, причем в силу технических особенностей несколько различных серверов производят одинаковую последовательность записей, так что дублирования стоит ожидать. Кроме того, некоторая активность (например, запись в таблицы) выглядит как последовательность нескольких разных событий на разных мастер-серверах (из разных шардов). Подробнее об этом далее.
Каждая запись в логе (каждая строка в таблице) фиксирует одну команду. Это может быть либо команда, примененная к тому или иному кипарисному узлу, либо команда, управляющая той или иной транзакцией.
В журнал попадают следующие команды, управляющие транзакциями:
- StartTransaction
- CommitTransaction
- AbortTransaction
Команды, применяемые к узлам, журналируются только в том случае, если они применены к следующим типам узлов:
- таблица;
- файл;
- документ;
- журнал;
- ссылка;
- директория.
Журналируются следующие команды для работы с узлами:
- базовые (CRUD):
- Create
- Get
- GetKey
- Exists
- List
- Set
- Remove
- создание символической ссылки:
- Link
- блокировки:
- Lock
- Unlock
- копирование и перемещение:
- Copy
- Move
- BeginCopy, EndCopy
- чтение и запись данных:
- GetBasicAttributes
- Fetch
- BeginUpload
- EndUpload
- изменение состояния динамической таблицы:
- PrepareMount, CommitMount, AbortMount
- PrepareUnmount, CommitUnmount, AbortUnmount
- PrepareRemount, CommitRemount, AbortRemount
- PrepareFreeze, CommitFreeze, AbortFreeze
- PrepareUnfreeze, CommitUnfreeze, AbortUnfreeze
- PrepareReshard, CommitReshard, AbortReshard
- прочие:
- CheckPermission
Некоторые комментарии касательно семантики команд можно найти далее.
Содержательная часть записи в логе имеет поля (колонки в таблице), представленные в таблице 1.
Таблица 1 — Описание полей лога
| Поле | Описание |
|---|---|
instant |
Время события в формате YYYY-MM-DD hh:mm:ss,sss |
cluster |
Короткое имя кластера |
method |
Команда (см. список выше) |
path (см. примечание) |
Путь, переданный команде в качестве аргумента |
original_path (см. примечание) |
Путь, переданный команде в качестве аргумента |
destination_path (см. примечание) |
Для команд «Copy», «Move» и «Link» — путь назначения (для других команд отсутствует) |
original_destination_path (см. примечание) |
Для команд «Copy», «Move» и «Link» — путь назначения (для других команд отсутствует) |
user |
Пользователь, давший команду |
type |
Для команды «Create» — тип создаваемого узла (для других команд отсутствует) |
transaction_info |
Сведения о транзакции, в контексте которой была выполнена команда (если команда выполнялась вне транзакции, поле отсутствует) |
Примечание
Отличие поля original_path от path (а также original_destination_path от destination_path) заключается в следующем:
- если в качестве пути была указана ссылка (симлинк), в
original_pathбудет путь к ссылке, а вpath— «настоящий» путь к узлу; - далее, если этот путь ведет в шард, то в логе этого шарда в качестве
original_pathбудет указан «настоящий» путь, а в качествеpath— путь относительно корня шарда.
В общей сложности это означает, что условный grep по пути к симлинку всегда найдёт записи, содержащие настоящий путь к узлу, а grep по настоящему пути найдёт обращения в том числе и через симлинки. Важно лишь выполнять поиск как по path, так и по original_path.
Для команд, управляющих транзакциями, все поля, содержащие пути, пусты. Информация о целевой транзации представлена, как и в других случаях, в поле transaction_info.
Структура поля transaction_info представлена в таблице 2.
Таблица 2 — Структура поля transaction_info
| Поле | Описание |
|---|---|
transaction_id |
ID транзакции |
transaction_title |
Человекочитаемое описание транзакции (указывается клиентом при запуске транзакции; поле отсутствует, если описание не было указано) |
operation_id |
ID операции, ассоциированной с транзакцией |
operation_title |
Человекочитаемое описание операции, ассоциированной с транзакцией |
parent |
Для вложенной транзакции — описание ее родителя (для верхнеуровневой транзакции поле отсутствует) |
Следует отметить, что поле parent устроено так же, как и transaction_info. Таким образом, transaction_info содержит полное рекурсивное описание родословной транзакции, из-под которой была выполнена команда.
Замечания
- Стоит отличать чтение/запись метаданных от чтения/записи данных (чанков) в таблицы и файлы.
- С точки зрения мастера, чтение/запись данных выглядит как следующая последовательность команд:
- чтение:
- GetBasicAttributes — получение некоторых служебных атрибутов, без которых чтение невозможно;
- Fetch — получение списка чанков, из которых состоит файл или таблица;
- запись:
- GetBasicAttributes — получение некоторых служебных атрибутов, без которых запись невозможна;
- BeginUpload — открытие заливочной транзакции;
- EndUpload — завершение заливочной транзакции.
- чтение:
- При чтении/записи данных команда GetBasicAttributes приходит на один селл, а Fetch, BeginUpload и EndUpload — на другой; это нормально.
- В подавляющем большинстве случаев копирование или перемещение таблицы выглядят как команды Copy или Move. Команды BeginCopy и EndCopy используются, когда копирование/перемещение пересекает границы шардирования Кипариса. На практике пользователи с таким должны сталкиваться редко.
Лог запросов к HTTP-проксе
В данном логе журналируются записи о всех запросах, которые были обслужены HTTP-прокси.
Таблица 2 — Описание полей лога
| Поле | Описание |
|---|---|
instant |
Время события в формате YYYY-MM-DD hh:mm:ss,sss |
cluster |
Короткое имя кластера |
request_id |
Идентификатор данного запроса |
correlation_id |
Специальный идентификатор запроса, который генерируется клиентом и не изменяется в случае ретраев |
user |
Пользователь, выполняющий запрос |
method |
Метод HTTP-запроса |
http_path |
Путь HTTP-запроса |
user_agent |
Содержимое хедера User-Agent в запросе |
command |
Команда |
parameters |
Параметры данной команды |
path |
Значение параметра path |
error |
Стуктурированное описание ошибки, в случае если запрос завершился неуспешно |
error_code |
Код ошибки, в случае если запрос завершился неуспешно |
http_code |
HTTP-код ответа на данный запрос |
start_time |
Фактическое время начала исполнения запроса на проксе |
cpu_time |
Время, потраченное проксей на исполнение запроса (в него не входит время исполнения запроса в других компонентах кластера) |
duration |
Общая длительность запроса |
in_bytes |
Размер входных данных запроса в байтах |
out_bytes |
Размер выходных данных запроса в байтах |
remote_address |
Адрес, с которого пришел данный запрос |
Поставка структурированных логов мастера в Кипарис
Kubernetes-оператор YTsaurus, начиная с версии 0.28.0, поддерживает поставку структурированных логов мастера, настраиваемую непосредственно в спецификации кластера.
Поставка осуществляется при помощи sidecar, в котором запущен timbertruck.
Для его работы необходимо выполнить следующие действия:
-
На кластере запустить HTTP Proxy и Queue Agent.
-
Включить запись нужного структурированного лога мастера:
spec:
primaryMasters:
structuredLoggers:
- name: access
minLogLevel: info
category: Access
format: json
rotationPolicy:
maxTotalSizeToKeep: 5_000_000_000
rotationPeriodMilliseconds: 900000
- Указать локация типа
Logs:
spec:
primaryMasters:
locations:
- locationType: Logs
path: /yt/master-logs
volumeMounts:
- name: master-logs
mountPath: /yt/master-logs
volumeClaimTemplates:
- metadata:
name: master-logs
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Gi
- Указать образ для
timbertruck:
Важно
При применении этих изменений будет запущено полное обновление кластера с даунтаймом, как и при обычном обновлении мастеров.
spec:
primaryMasters:
timbertruck:
image: ghcr.io/ytsaurus/sidecars:0.0.1
- Применить изменения.
kubectl apply -f your_config.yaml -n <namespace>
Штатная работа сайдкара
- Созданы очереди под каждый из структурированных логов:
yt exists //sys/admin/logs/master-access/producer
yt exists //sys/admin/logs/master-access/queue
- В
producerимеется строчка с информацией о поставке с мастеров:
yt select-rows "SELECT session_id FROM [//sys/admin/logs/master-access/producer]" --format json
Пример ожидаемого вывода
{
"session_id": "ms-0.masters.ytsaurus-dev.svc.cluster.local:/yt/master-logs/timbertruck/master-access/staging/2025-12-01T11:07:46_ino:46696359.access.log.json"
}
- Настроен экспорт очереди
//sys/admin/logs/master-access/queueв статические таблицы::
yt get //sys/admin/logs/master-access/queue/@static_export_config
Ожидается настроенный экспорт в существующую ноду:
{
"default" = {
"export_directory" = "//sys/admin/logs/export/master-access";
"export_ttl" = 1209600000;
"export_period" = 1800000;
"export_name" = "default";
};
}
Поиск проблем
Чтобы посмотреть логи сайдкара, выполните:
kubectl -n <namespace> logs ms-0 -c timbertruck
Настройка ротации логов
Для отладочных и структурированных логов, которые пишутся в файл, можно настроить встроенный механизм ротации (поле rotationPolicy). Настройки ротации приведены в таблице. Если не используется опция useTimestampSuffix, в момент ротации файлы старых сегментов переименовываются, с дописыванием порядкового номера.
Таблица 3 — Настройки ротации логов
| Поле | Описание |
|---|---|
rotationPeriodMilliseconds |
Период ротации, в миллисекундах. Может задаваться вместе с maxSegmentSize. |
maxSegmentSize |
Ограничение на размер одного сегмента лога, в байтах. Может задаваться вместе с rotationPeriodMilliseconds. |
maxTotalSizeToKeep |
Ограничение на размер всех сегментов, в байтах. В момент ротации, удаляются самые старые логи так, чтобы уложиться в заданное ограничение. |
maxSegmentCountToKeep |
Ограничение на количество хранимых сегментов лога, в штуках. Самые старые сегменты сверх ограничения удаляются. |
Динамическая конфигурация
Компоненты, поддерживающие динамическую конфигурацию, позволяют дополнительно уточнить настройки системы логирования с помощью динамического конфига в Кипарисе, секция logging.
Основные параметры:
enable_anchor_profiling— включает prometheus-метрики по отдельным префиксам записей;min_logged_message_rate_to_profile— минимальная частота сообщения, для попадания в отдельную метрику;suppressed_messaged— список префиксов сообщений отладочных логов, которые будут исключены из логирования.
Пример конфигурации:
{
logging = {
enable_anchor_profiling = %true;
min_logged_message_rate_to_profile = 100;
suppressed_messaged = [
"Skipping out of turn block",
"Request attempt started",
"Request attempt acknowledged"
];
}
}
Пример настройки логирования
primaryMasters:
...
loggers:
- name: debug
compression: zstd
minLogLevel: debug
writerType: file
rotationPolicy:
maxTotalSizeToKeep: 50_000_000_000
rotationPeriodMilliseconds: 900000
categoriesFilter:
type: exclude
values: ["Bus", "Concurrency", "ReaderMemoryManager"]
- name: info
minLogLevel: info
writerType: file
rotationPolicy:
maxTotalSizeToKeep: 10_000_000_000
rotationPeriodMilliseconds: 900000
- name: error
minLogLevel: error
writerType: stderr
structuredLoggers:
- name: access
minLogLevel: info
category: Access
rotationPolicy:
maxTotalSizeToKeep: 5_000_000_000
rotationPeriodMilliseconds: 900000
locations:
- locationType: Logs
path: /yt/logs
- ...
volumeMounts:
- name: master-logs
mountPath: /yt/logs
- ...
volumeClaimTemplates:
- metadata:
name: master-logs
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 100Gi
- ...