В отличии от других систем логирования, которых развелось уже уйма разработчики Loki решили, что он не будет индексировать ваши логи а будет индексировать только их метаданные (labels). Сами данные затем сжимаются и сохраняются фрагментами (chunks) в различных файловых хранилищах, например, таких как S3, GCS или в файловой системе. Индекс имеющий минимальный размер и данные, которые хорошо сжаты упрощают работу и также снижают цену, так как для хранения не нужно много дискового пространства (расскажите это людям с ELK).

Скажу сразу то, что я здесь описываю актуально для версий Loki после Loki 2.0. Там было немного иначе, но смысла описывать я это не вижу так как продукт на рынке недавно и скорее всего вы будете работать с более новой версией, как и я.

Loki 2.0 дал возможность использовать одно единое хранилище для индекса и фрагмента, благодаря механизму под названием boltdb-shipper. Люди близкие к этому творению дали ему имя Single Store Loki.

Индексы и фрагменты

Как мы уже знаем данные хранятся в фрагментах (chunks). Loki принимает логи в отдельных потоках (streams), каждый из которых имеет свой уникальный идентификатор (ID) и его набор меток (labels). Далее всё сжимается в фрагментах (chunks) и записывается в хранилище данных.

Индексы же хранят информацию о наборе меток (labels) и их связях с отдельными фрагментами (chunks).

Table Manager

Table Manager - это один из субкомпонентов в Loki. Loki поддерживает хранение индексов и фрагментов (chunks) в табличных хранилищах данных. Благодаря этому создаётся множество таблиц за определённое время. Каждая такая таблица также называется периодической таблицей, в которой хранятся данные за определённое время. Это время конечно же можно изменить.

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

  1. Изменения конфигурации схемы: каждая таблица привязана к конфигурации и версии схемы, благодаря чему вы можете вносить изменения в схему в любой момент. Если проще новые данные принимают новую схему, а старые используют старую, вы просто указываете с какого времени применяется та или иная схема.
  2. Операции удаления происходят гораздо быстрее

Не все типы хранилищ поддерживают использование Table Manager, список поддерживающих можно проверить на офф сайте.

Таблицы и конфигурация схемы

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

schema_config:
  configs:
    - from: 2023-02-23
      store: boltdb-shipper
      object_store: filesystem
      schema: v12
      index:
        prefix: index_
        period: 24h | default = 168h    <<<<<<<<<<<<<<<<
	  chunks:
        prefix: chunk_
	    period: 24h | default = 168h	<<<<<<<<<<<<<<<<

Также раздел schema_config может содержать не только одну конфигурацию схемы, как мы уже и говорили. Всё благодаря from где вы как раз и указываете с какого момента начинает действовать схема. Самая ближняя конфигурация по дате к сегодняшнему числу является активной конфигурацией схемы. Значение period должно быть кратно 24 часам.

Т.е. если мы возьмём промежуток в неделю, то у нас с конфигурацией как выше должно быть 7 таблиц.

Loki Tables and schema config

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

Поэтому по умолчанию вы не сможете загрузить в Loki данные с устаревшей меткой времени. С одной стороны это выглядит странно, но с другой это фича.

Если вам нужно залить старые данные, то можно изменить конфигурацию:

reject_old_samples: true | default = false
reject_old_samples_max_age: 168h | default = 336h

Создание таблицы

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

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

table_manager:
  creation_grace_period: 20m | default = 10m

Хранение (Retention)

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

table_manager:
  retention_deletes_enabled: true
  retention_period: 4d

Т.е. при такой конфигурации Table Manager будет хранить только те таблицы, в которых данные не старее 4 дней с сегодняшнего дня. Причём мы помним что удаляется таблица целиком, поэтому не удивляемся если данные за 5 день всё еще присутствуют, если period конечно в schema_config 24h. Нужно дождаться чтобы день закончился полностью.

В целом чтобы узнать за какое время будут сохранены ваши данные можно воспользоваться формулой:

number_of_tables_to_keep = (retention_period / table_period) + 1

Т.е. если брать во внимание все настройки как в этой статье мы получаем 5 дней. Получается что всё старее 5 дней будет удаленно, но не сразу.

5 дней = (4 дня / 1 день) + 1 день

Loki Tables retention period

И последняя ремарка значение retention_period должно быть кратно 24 часам как и значение period.

Всё настроено, на индексы не удаляются

Во время тестирования я столкнулся с тем что после истечения времени мои старые индексы не удалялись. Т.е. время жизни индекса превышало number_of_tables_to_keep но сами индексы не удалялись.

И вот я наткнулся на информацию об обновлении где сказано что The single binary no longer runs a table-manager. Т.е. возможно table-manager у меня и не работает?

Но вот при каких условиях он собственно и не работает:

  • Вы запускаете бинарный файл loki с опцией -target=all
  • Вы запускаете бинарный файл loki без опции, но по умолчанию значение всё также -target=all
  • Запуск одного бинарного Loki с любым типом индекса, кроме boltdb-shipper или boltdb
  • Если вы активировали опции retention_deletes_enabled и retention_period

Первый способ выйти из положения это запустить с -target=all,table-manager, что кстати сами разработчики не рекомендуют делать.

Но суть в в том что в моем случае я и так запускал без -target=all а именно -target=write и -target=read. Но как только я добавил table-manager старые индексы удалились.

И второй способ это отказаться от table-manager и использовать compactor, который кстати работает только с хранилищем boltdb-shipper.

На самом деле тут мне кажется ребята немного перемудрили и это первое что мне не совсем понравилось в этом продукте.

Активные/неактивные таблицы

Как вы уже поняли таблицы могут быть как активными так и не активными. Ну и я думаю логично что активной является та таблица, период которой попадает под сегодняшний день. Но на момент написания статьи это актуально только для DynamoDB storage.