Интеграция OpenTelemetry для сбора данных
Любое решение для обеспечения наблюдаемости требует средства для сбора и экспорта логов и трасс. Для этой цели ClickHouse рекомендует проект OpenTelemetry (OTel).
"OpenTelemetry - это платформа и набор инструментов для обеспечения наблюдаемости, предназначенные для создания и управления телеметрическими данными, такими как трассы, метрики и логи."
В отличие от ClickHouse или Prometheus, OpenTelemetry не является бэкендом для обеспечения наблюдаемости и в большей степени сосредотачивается на генерации, сборе, управлении и экспорте телеметрических данных. Хотя первоначальная цель OpenTelemetry заключалась в том, чтобы позволить пользователям легко инструментировать свои приложения или системы с помощью специализированных SDK, он расширил свои функции, включив сбор логов через OpenTelemetry collector - агент или прокси, который принимает, обрабатывает и экспортирует телеметрические данные.
Компоненты, относящиеся к ClickHouse
OpenTelemetry состоит из нескольких компонентов. Кроме предоставления спецификации данных и API, стандартизованного протокола и наименований для полей/столбцов, OTel предлагает две возможности, которые являются основополагающими для построения решения по обеспечению наблюдаемости с использованием ClickHouse:
- OpenTelemetry Collector - это прокси, который принимает, обрабатывает и экспортирует телеметрические данные. Решение на основе ClickHouse использует этот компонент как для сбора логов, так и для обработки событий перед их пакетной загрузкой и вставкой.
- Языковые SDK, которые реализуют спецификацию, API и экспорт телеметрических данных. Эти SDK эффективно обеспечивают правильную запись трасс в коде приложения, создавая составные отрезки и гарантируя, что контекст передается между службами через метаданные, тем самым формируя распределенные трассы и обеспечивая корреляцию отрезков. Эти SDK дополняются экосистемой, которая автоматически реализует общие библиотеки и фреймворки, благодаря чему пользователю не требуется изменять свой код, и он получает встроенную инструментализацию "из коробки".
Решение для обеспечения наблюдаемости на основе ClickHouse использует оба этих инструмента.
Дистрибутивы
OpenTelemetry collector имеет несколько дистрибутивов. Приемник filelog вместе с экспортером ClickHouse, необходимым для решения ClickHouse, присутствует только в OpenTelemetry Collector Contrib Distro.
Этот дистрибутив содержит множество компонентов и позволяет пользователям экспериментировать с различными конфигурациями. Однако при запуске в производственной среде рекомендуется ограничить collector только теми компонентами, которые необходимы для данной среды. Некоторые причины для этого:
- Уменьшить размер collector, что сократит время развертывания
- Улучшить безопасность collector, уменьшая доступную площадь атаки
Создание пользовательского collector можно осуществить с помощью OpenTelemetry Collector Builder.
Прием данных с использованием OTel
Роли развертывания collector
Для того чтобы собирать логи и вставлять их в ClickHouse, мы рекомендуем использовать OpenTelemetry Collector. OpenTelemetry Collector можно развернуть в двух основных ролях:
- Агент - Экземпляры агента собирают данные на краю, например, на серверах или узлах Kubernetes, или получают события напрямую от приложений - инструментированных с помощью OpenTelemetry SDK. В последнем случае экземпляр агента работает вместе с приложением или на том же хосте, что и приложение (например, как сайдкар или DaemonSet). Агенты могут либо отправлять свои данные напрямую в ClickHouse, либо к экземпляру шлюза. В первом случае это называется шаблоном развертывания агента.
- Шлюз - Экземпляры шлюза предоставляют автономную службу (например, развертывание в Kubernetes), обычно на кластер, центр обработки данных или регион. Они получают события от приложений (или других collectors в качестве агентов) через единую точку OTLP. Обычно развертывается набор экземпляров шлюза, с использованием готового балансировщика нагрузки для распределения нагрузки. Если все агенты и приложения отправляют свои сигналы на эту единичную точку, это часто называется шаблоном развертывания шлюза.
В дальнейшем мы рассматриваем простой агентский collector, который отправляет свои события непосредственно в ClickHouse. См. Масштабирование с использованием шлюзов для получения дополнительных сведений о использовании шлюзов и о том, когда они применимы.
Сбор логов
Основным преимуществом использования collector является то, что он позволяет вашим службам быстро разгружать данные, передавая обработку дополнительным операциям, таким как повторы, пакетирование, шифрование или даже фильтрация чувствительных данных.
Collector использует термины приемник, процессор и экспортер для трех основных этапов обработки. Приемники используются для сбора данных и могут быть основаны как на вытягивании, так и на отправке. Процессоры обеспечивают возможность выполнения преобразований и обогащения сообщений. Экспортеры отвечают за отправку данных в нижестоящую службу. Хотя эта служба теоретически может быть другим collector, ниже мы предполагаем, что все данные отправляются непосредственно в ClickHouse для первоначального обсуждения.

Мы рекомендуем пользователям ознакомиться с полным набором приемников, процессоров и экспортеров.
Collector предоставляет два основных приемника для сбора логов:
Через OTLP - В этом случае логи отправляются (отправляются) непосредственно в collector из OpenTelemetry SDK через протокол OTLP. Демонстрация OpenTelemetry использует такой подход, при этом экспортёры OTLP в каждом языке предполагают локальную конечную точку collector. В этом случае collector должен быть настроен с приемником OTLP — смотрите выше демонстрацию для конфигурации. Преимуществом этого подхода является то, что данные логов автоматически будут содержать идентификаторы трасс, позволяя пользователям позже идентифицировать трассы для конкретного лога и наоборот.

Этот подход требует от пользователей инструментирования их кода с использованием их соответствующего языкового SDK.
- Скрейпинг через приемник Filelog - Этот приемник отслеживает файлы на диске и формирует сообщения логов, отправляя их в ClickHouse. Этот приемник обрабатывает сложные задачи, такие как определение многострочных сообщений, обработка переключений логов, контрольная запись для обеспечения устойчивости к перезапуску и извлечение структуры. Этот приемник также может отслеживать логи контейнеров Docker и Kubernetes, разворачиваемый как helm chart, извлекая структуру из них и обогащая их деталями пода.

Большинство развертываний будет использовать комбинацию приведенных выше приемников. Мы рекомендуем пользователям ознакомиться с документацией collector и изучить основные концепции, а также структуру конфигурации и методы установки.
Структурированные и неструктурированные логи
Логи могут быть структурированными или неструктурированными.
Структурированный лог будет использовать формат данных, такой как JSON, определяя метаполя, такие как код HTTP и IP-адрес источника.
Неструктурированные логи, хотя обычно также имеют некоторую структурированность, которую можно извлечь с помощью регулярного выражения, будут представлять лог просто как строку.
Мы рекомендуем пользователям использовать структурированное логирование и логировать в JSON (т.е. ndjson), где это возможно. Это упростит последующую обработку логов, либо перед отправкой в ClickHouse с помощью процессоров Collector, либо во время вставки с использованием материализованных представлений. Структурированные логи в конечном итоге сэкономят ресурсы на последующей обработке, снижая необходимую производительность CPU в вашем решении ClickHouse.
Пример
Для примера мы предоставляем структурированный (JSON) и неструктурированный наборы логов, каждый из которых содержит примерно 10 миллионов строк, доступных по следующим ссылкам:
Мы используем структурированный набор данных для приведенного ниже примера. Убедитесь, что этот файл загружен и извлечен, чтобы воспроизвести следующие примеры.
Ниже представлена простая конфигурация для OTel Collector, который читает эти файлы на диске, используя приемник filelog, и выводит полученные сообщения на стандартный вывод. Мы используем оператор json_parser
, так как наши логи структурированы. Измените путь к файлу access-structured.log.
Ниже приведенный пример извлекает временную метку из лога. Это требует использования оператора json_parser
, который преобразует всю строку лога в строку JSON, помещая результат в LogAttributes
. Это может быть вычислительно затратным и может быть выполнено более эффективно в ClickHouse - Извлечение структуры с помощью SQL. Эквивалентный неструктурированный пример, который использует regex_parser
для достижения этой цели, можно найти здесь.
Пользователи могут следовать официальным инструкциям для установки collector локально. Важно, чтобы инструкции были изменены для использования дистрибутива contrib (в который входит приемник filelog
), например, вместо otelcol_0.102.1_darwin_arm64.tar.gz
пользователи должны загрузить otelcol-contrib_0.102.1_darwin_arm64.tar.gz
. Релизы можно найти здесь.
После установки OTel Collector можно запустить с помощью следующих команд:
При использовании структурированных логов сообщения будут иметь следующую форму на выводе:
Выше представлено одно сообщение лога, созданное OTel collector. Мы будем загружать эти же сообщения в ClickHouse в последующих разделах.
Полная схема сообщений логов, вместе с дополнительными столбцами, которые могут быть присутствовать при использовании других приемников, поддерживается здесь. Мы настоятельно рекомендуем пользователям ознакомиться с этой схемой.
Ключ состоит в том, что строка лога сама по себе хранится как строка в поле Body
, но JSON был автоматически извлечен в поле Attributes благодаря json_parser
. Этот же оператор использовался для извлечения временной метки в соответствующий столбец Timestamp
. Для рекомендаций по обработке логов с OTel смотрите Обработка.
Операторы - это базовая единица обработки логов. Каждый оператор выполняет единую задачу, такую как чтение строк из файла или парсинг JSON с поля. Операторы затем связываются в цепочку в конвейере для достижения желаемого результата.
Вышеупомянутые сообщения не имеют полей TraceID
или SpanID
. Если они присутствуют, например, в случаях, когда пользователи реализуют распределенное трассирование, их можно извлечь из JSON с помощью тех же техник, показанных выше.
Для пользователей, которым нужно собирать локальные или Kubernetes файлы логов, мы рекомендуем ознакомиться с доступными опциями конфигурации для приемника filelog и тем, как обрабатываются сдвиги и парсинг многострочных логов.
Сбор логов Kubernetes
Для сбора логов Kubernetes мы рекомендуем использовать документацию Open Telemetry. Рекомендуется использовать Kubernetes Attributes Processor для обогащения логов и метрик метаданными подов. Это может потенциально создать динамические метаданные, такие как метки, сохраненные в столбце ResourceAttributes
. В ClickHouse в настоящее время используется тип Map(String, String)
для этого столбца. См. Использование карт и Извлечение из карт для получения дополнительных сведений о работе с этим типом и его оптимизации.
Сбор трасс
Для пользователей, желающих инструментировать свой код и собирать трассы, мы рекомендуем следовать официальной документации OTel.
Чтобы доставлять события в ClickHouse, пользователям необходимо развернуть OTel collector для получения событий трасс через протокол OTLP с помощью соответствующего приемника. Демонстрация OpenTelemetry предоставляет пример инструментирования каждого поддерживаемого языка и отправки событий в collector. Пример соответствующей конфигурации collector, который выводит события на стандартный вывод, приведен ниже:
Пример
Поскольку трассы должны быть получены через OTLP, мы используем инструмент telemetrygen
для генерации данных трасс. Следуйте инструкциям здесь для установки.
Следующая конфигурация принимает события трасс на приемнике OTLP, а затем отправляет их на стандартный вывод.
Запустите эту конфигурацию с помощью:
Отправьте события трасс в collector через telemetrygen
:
Это приведет к сообщениям трасс, подобным приведённому ниже примеру, выводимым на стандартный вывод:
Выше представлено одно сообщение трассы, созданное OTel collector. Мы будем загружать эти же сообщения в ClickHouse в следующих разделах.
Полная схема сообщений трасс поддерживается здесь. Мы настоятельно рекомендуем пользователям ознакомиться с этой схемой.
Обработка - фильтрация, преобразование и обогащение
Как показано в предыдущем примере с установкой временной метки для события лога, пользователи, безусловно, захотят фильтровать, преобразовывать и обогащать сообщения событий. Это можно достичь с помощью нескольких возможностей Open Telemetry:
-
Процессоры - Процессоры берут данные, собранные приемниками, и модифицируют или преобразовывают их перед отправкой экспортеру. Процессоры применяются в порядке, указанном в разделе
processors
конфигурации collector. Эти процессоры являются необязательными, но минимальный набор, как правило, рекомендуется обычно. При использовании OTel collector с ClickHouse мы рекомендуем ограничить процессоры:- Процессор memory_limiter используется для предотвращения ситуаций с переполнением памяти в collector. См. Оценка ресурсов для рекомендаций.
- Любой процессор, который выполняет обогащение на основе контекста. Например, Kubernetes Attributes Processor позволяет автоматически устанавливать атрибуты ресурсов для отрезков, метрик и логов с метаданными k8s, т.е. обогащать события их идентификатором источника пода.
- Сэмплинг по хвостам или головам при необходимости для трасс.
- Базовая фильтрация - сбрасывание событий, которые не нужны, если это нельзя сделать через операторы (см. ниже).
- Пакетирование - важно при работе с ClickHouse, чтобы гарантировать, что данные отправляются пакетами. См. "Экспорт в ClickHouse".
-
Операторы - Операторы предоставляют самую базовую единицу обработки, доступную на приемнике. Поддерживается базовый парсинг, позволяющий устанавливать такие поля, как уровень и временная метка. Поддерживаются парсинг JSON и регулярных выражений, а также фильтрация событий и простые преобразования. Мы рекомендуем выполнять фильтрацию событий здесь.
Мы рекомендуем пользователям избегать чрезмерной обработки событий с помощью операторов или трансформационных процессоров. Эти операции могут вызывать значительные затраты по памяти и CPU, особенно при парсинге JSON. Все мощения можно выполнить в ClickHouse во время вставки с помощью материализованных представлений и столбцов, за некоторыми исключениями - в частности, контекстно-осведомленного обогащения, т.е. добавления метаданных k8s. Для получения дополнительных сведений смотрите Извлечение структуры с помощью SQL.
Если обработка ведется с помощью OTel collector, мы рекомендуем выполнять преобразования на экземплярах шлюзов и минимизировать любую работу, выполняемую на экземплярах агентов. Это гарантирует, что ресурсы, необходимые агентам на краю, работающим на серверах, будут как можно меньше. Обычно мы видим, что пользователи выполняют только фильтрацию (чтобы минимизировать ненужное использование сети), установку временной метки (через операторы) и обогащение, что требует контекста в агентах. Например, если экземпляры шлюзов находятся в другом кластере Kubernetes, необходимо будет выполнить обогащение k8s в агенте.
Пример
Следующая конфигурация демонстрирует сбор неструктурированного файла логов. Обратите внимание на использование операторов для извлечения структуры из строк логов (regex_parser
) и фильтрации событий, а также на процессор для пакетирования событий и ограничения использования памяти.
config-unstructured-logs-with-processor.yaml
Экспорт в ClickHouse
Экспортеры отправляют данные в один или несколько бэкендов или мест назначения. Экспортеры могут быть основаны на извлечении (pull) или отправке (push). Для отправки событий в ClickHouse пользователи должны использовать экспортер на основе push - ClickHouse exporter.
Экспортер ClickHouse является частью OpenTelemetry Collector Contrib, а не основной дистрибуции. Пользователи могут использовать как дистрибуцию contrib, так и собрать собственный коллектор.
Полный файл конфигурации показан ниже.
Обратите внимание на следующие ключевые настройки:
- pipelines - В приведенной выше конфигурации подчеркивается использование pipelines, состоящих из набора приемников, процессоров и экспортеров для логов и траекторий.
- endpoint - Связь с ClickHouse настраивается через параметр
endpoint
. Строка подключенияtcp://localhost:9000?dial_timeout=10s&compress=lz4&async_insert=1
обеспечивает связь по TCP. Если пользователи предпочитают HTTP по причинам переключения трафика, измените эту строку подключения, как описано здесь. Полные детали подключения, включая возможность указания имени пользователя и пароля внутри этой строки подключения, описаны здесь.
Важно: Обратите внимание, что приведенная выше строка подключения включает как сжатие (lz4), так и асинхронные вставки. Рекомендуется всегда включать оба параметра. См. Batching для получения дополнительных деталей об асинхронных вставках. Сжатие должно всегда указываться и по умолчанию не будет включено на более старых версиях экспортера.
- ttl - значение здесь определяет, как долго данные сохраняются. Дополнительные детали в "Управление данными". Это должно быть указано в виде единицы времени в часах, например, 72h. Мы отключаем TTL в следующем примере, так как наши данные датируются 2019 годом и будут немедленно удалены ClickHouse при вставке.
- traces_table_name и logs_table_name - определяют имя таблицы для логов и траекторий.
- create_schema - определяет, создаются ли таблицы с помощью схем по умолчанию при запуске. По умолчанию это установлено в true для начала работы. Пользователи должны установить его в false и определить свою собственную схему.
- database - целевая база данных.
- retry_on_failure - настройки для определения того, должны ли неудачные пакеты повторно обрабатываться.
- batch - процессор пакетов обеспечивает отправку событий в пакетах. Рекомендуем использовать значение около 5000 с таймаутом 5s. Любой из этих параметров, если он будет достигнут первым, запустит пакет для отправки экспортеру. Снижением этих значений будет означать более низкую задержку конвейера с доступными данными для запроса быстрее, но за счет большего количества соединений и пакетов, отправляемых в ClickHouse. Это не рекомендуется, если пользователи не используют асинхронные вставки, так как это может привести к проблемам с слишком большим количеством частей в ClickHouse. Напротив, если пользователи используют асинхронные вставки, доступность данных для запросов также будет зависеть от настроек асинхронных вставок, хотя данные все равно будут сброшены из коннектора раньше. См. Batching для получения дополнительных деталей.
- sending_queue - управляет размером очереди отправки. Каждый элемент в очереди содержит пакет. Если эта очередь превышена, например, из-за недоступности ClickHouse, но события продолжают поступать, пакеты будут отброшены.
Предполагая, что пользователи извлекли структурированный файл логов и имеют локальную инстанцию ClickHouse, работающую (с настройками аутентификации по умолчанию), пользователи могут запустить эту конфигурацию с помощью команды:
Для отправки данных трассировки в этот коллектор выполните следующую команду, используя инструмент telemetrygen
:
После запуска подтвердите существование событий логов с помощью простого запроса:
Схема по умолчанию
По умолчанию экспортер ClickHouse создает целевую таблицу лога как для логов, так и для траекторий. Это можно отключить с помощью настройки create_schema
. Более того, имена как таблицы логов, так и таблицы траекторий можно изменить от их значений по умолчанию otel_logs
и otel_traces
через указанные выше настройки.
В схеме ниже мы предполагаем, что TTL был включен на 72 часа.
Схема по умолчанию для логов показана ниже (otelcol-contrib v0.102.1
):
Столбцы здесь соответствуют официальной спецификации OTel для логов, документированной здесь.
Несколько важных заметок по этой схеме:
- По умолчанию таблица разделена по дате через
PARTITION BY toDate(Timestamp)
. Это делает эффективным удаление данных, которые истекают. - TTL установлен через
TTL toDateTime(Timestamp) + toIntervalDay(3)
и соответствует значению, установленному в конфигурации коллектора.ttl_only_drop_parts=1
означает, что только целые части удаляются, когда все содержащиеся строки истекли. Это более эффективно, чем удаление строк внутри частей, что связано с дорогими операциями удаления. Мы рекомендуем всегда устанавливать это значение. См. Управление данными с помощью TTL для получения дополнительных деталей. - Таблица использует классический
MergeTree
engine. Это рекомендуется для логов и траекторий и не должно требовать изменения. - Таблица упорядочена по
ORDER BY (ServiceName, SeverityText, toUnixTimestamp(Timestamp), TraceId)
. Это означает, что запросы будут оптимизированы для фильтров поServiceName
,SeverityText
,Timestamp
иTraceId
- более ранние столбцы в списке будут фильтроваться быстрее, чем более поздние, например, фильтрация поServiceName
будет значительно быстрее, чем фильтрация поTraceId
. Пользователи должны изменить это упорядочение в зависимости от своих ожидаемых паттернов доступа - см. Выбор первичного ключа. - В приведенной схеме применяется
ZSTD(1)
к столбцам. Это обеспечивает наилучшее сжатие для логов. Пользователи могут увеличить уровень сжатия ZSTD (выше значения по умолчанию 1) для лучшего сжатия, хотя это редко бывает полезно. Увеличение этого значения приведет к большему использованию ресурсов CPU во время вставки (в процессе сжатия), хотя декомпрессия (и, следовательно, запросы) должны оставаться сопоставимыми. Подробности см. здесь. Дополнительное delta encoding применяется к Timestamp с целью уменьшить его размер на диске. - Обратите внимание, что
ResourceAttributes
,LogAttributes
иScopeAttributes
являются картами. Пользователи должны ознакомиться с различиями между ними. Для того чтобы узнать, как получить доступ к этим картам и оптимизировать доступ к ключам в них, смотрите Использование карт. - Большинство других типов здесь, например,
ServiceName
как LowCardinality, оптимизированы. Обратите внимание, что Body, хотя и является JSON в наших примерах логов, хранится как строка. - Фильтры Блума применяются к ключам и значениям карт, а также к столбцу Body. Они направлены на улучшение времени выполнения запросов для доступа к этим столбцам, но обычно не требуются. См. Вторичные/индексы для пропуска данных.
Снова, это будет коррелировать со столбцами, которые соответствуют официальной спецификации OTel для трассировок, документированным здесь. Схема здесь применяет многие те же настройки, что и вышеуказанная схема логов, с дополнительными колонками Link, специфичными для спанов.
Мы рекомендуем пользователям отключить автоматическое создание схемы и создать свои таблицы вручную. Это позволяет изменить первичные и вторичные ключи, а также предоставляет возможность добавить дополнительные столбцы для оптимизации производительности запросов. Для получения дополнительных деталей смотрите Проектирование схемы.
Оптимизация вставок
Чтобы достичь высокой производительности вставок при обеспечении надежных гарантий согласованности, пользователи должны следовать простым правилам при вставке данных Об наблюдаемости в ClickHouse через коллектор. С правильной конфигурацией коллектора OTel следующие правила должны быть простыми для выполнения. Это также позволяет избежать распространенных проблем, с которыми пользователи сталкиваются при первом использовании ClickHouse.
Пакетирование
По умолчанию каждая вставка, отправляемая в ClickHouse, немедленно создает часть хранилища, содержащую данные из вставки вместе с другими метаданными, которые необходимо сохранить. Поэтому отправка меньшего количества вставок, каждая из которых содержит больше данных, по сравнению с отправкой большего количества вставок, каждая из которых содержит меньше данных, снизит количество необходимых записей. Мы рекомендуем вставлять данные достаточно большими пакетами, содержащими не менее 1000 строк за раз. Дополнительные детали здесь.
По умолчанию вставки в ClickHouse являются синхронными и идемпотентными, если идентичны. Для таблиц из семейства движков merge tree ClickHouse по умолчанию автоматически дедуплицирует вставки. Это означает, что вставки являются устойчивыми в случаях, подобных следующим:
- (1) Если узел, получающий данные, имеет проблемы, запрос вставки истечет (или получит более конкретную ошибку) и не получит подтверждение.
- (2) Если данные были записаны узлом, но подтверждение не может быть возвращено отправителю запроса из-за сетевых перебоев, отправитель либо получит тайм-аут, либо ошибку сети.
С точки зрения коллектора (1) и (2) могут быть трудны для различения. Однако в обоих случаях неполученная вставка может просто быть сразу повторена. Если повторенный запрос вставки содержит те же данные в том же порядке, ClickHouse автоматически проигнорирует повторенный запрос, если оригинальная вставка (неподтвержденная) прошла успешно.
Мы рекомендуем пользователям использовать процессор пакетов, показанный в предыдущих конфигурациях, для удовлетворения вышеуказанных требований. Это гарантирует, что вставки отправляются как последовательные пакеты строк, удовлетворяющие вышеуказанным требованиям. Если ожидается, что коллектор будет иметь высокую пропускную способность (событий в секунду), и по крайней мере 5000 событий могут быть отправлены в каждой вставке, это обычно единственное пакетирование, необходимое в конвейере. В этом случае коллектор будет очищать пакеты, прежде чем истечет тайм-аут timeout
процессора пакетов, что гарантирует, что задержка от начала до конца в конвейере остается низкой, а пакеты имеют последовательный размер.
Использование асинхронных вставок
Обычно пользователи вынуждены отправлять меньшие пакеты, когда пропускная способность коллектора низка, а данные все равно должны достичь ClickHouse в пределах минимальной задержки от начала до конца. В этом случае небольшие пакеты отправляются, когда истекает тайм-аут процессора пакетов. Это может вызвать проблемы, и в этом случае требуются асинхронные вставки. Эта ситуация обычно возникает, когда коллекторы, играющие роль агента, настроены для отправки непосредственно в ClickHouse. Шлюзы, выступая в качестве агрегаторов, могут облегчить эту проблему - см. Масштабирование с помощью шлюзов.
Если большие пакеты нельзя гарантировать, пользователи могут делегировать пакетирование ClickHouse с использованием Асинхронных вставок. При асинхронных вставках данные сначала вставляются в буфер, а затем записываются в хранилище базы данных позже или асинхронно соответственно.

С включенными асинхронными вставками в момент, когда ClickHouse ① получает запрос на вставку, данные запроса ② немедленно записываются сначала в буфер в памяти. Когда ③ происходит следующее очищение буфера, данные буфера сортируются и записываются как часть в хранилище базы данных. Обратите внимание, что данные не могут быть доступны для поиска запросами, пока они не будут очищены в хранилище базы данных; процесс сброса буфера настраиваемый.
Чтобы включить асинхронные вставки для коллектора, добавьте async_insert=1
в строку подключения. Мы рекомендуем пользователям использовать wait_for_async_insert=1
(значение по умолчанию) для получения гарантий доставки - смотрите здесь для получения дополнительных деталей.
Данные из асинхронной вставки вставляются после того, как буфер ClickHouse очищается. Это происходит либо после превышения async_insert_max_data_size
, либо после async_insert_busy_timeout_ms
миллисекунд с момента первого запроса INSERT. Если async_insert_stale_timeout_ms
установлено в ненулевое значение, данные вставляются после async_insert_stale_timeout_ms миллисекунд
с момента последнего запроса. Пользователи могут настроить эти параметры, чтобы контролировать задержку от начала до конца в своем конвейере. Дополнительные параметры, которые можно использовать для настройки сброса буфера, задокументированы здесь. Обычно значения по умолчанию являются подходящими.
В случаях, когда используется небольшое количество агентов с низкой пропускной способностью, но строгими требованиями к задержке от начала до конца, адаптивные асинхронные вставки могут быть полезны. Обычно они не применимы к сценариям наблюдаемости с высокой пропускной способностью, как это видно с ClickHouse.
Наконец, предыдущее поведение дедупликации, связанное с синхронными вставками в ClickHouse, по умолчанию не включается при использовании асинхронных вставок. Если это необходимо, смотрите параметр async_insert_deduplicate
.
Полные детали по настройке этой функции можно найти здесь, с глубоким погружением здесь.
Архитектуры развертывания
Существует несколько архитектур развертывания, возможных при использовании коллектора OTel с ClickHouse. Мы описываем каждую из них ниже и когда она вероятно имеет применение.
Только агенты
В архитектуре только с агентами пользователи развертывают коллектор OTel в качестве агентов на краю. Эти агенты принимают трассировки от локальных приложений (например, в качестве контейнера sidecar) и собирают логи с серверов и узлов Kubernetes. В этом режиме агенты отправляют свои данные непосредственно в ClickHouse.

Эта архитектура подходит для малых и средних развертываний. Ее основное преимущество заключается в том, что она не требует дополнительного оборудования и сохраняет общий ресурсный след решения по наблюдаемости ClickHouse на минимальном уровне, с простым соответствием между приложениями и коллекторами.
Пользователи должны рассмотреть возможность миграции на архитектуру, основанную на шлюзах, как только количество агентов превысит несколько сотен. Эта архитектура имеет несколько недостатков, которые сделают ее сложной для масштабирования:
- Масштабирование соединений - Каждый агент будет устанавливать соединение с ClickHouse. В то время как ClickHouse способен поддерживать сотни (если не тысячи) одновременных соединений вставки, это в конечном итоге станет ограничивающим фактором и сделает вставки менее эффективными - т.е. ClickHouse будет использовать больше ресурсов на поддержание соединений. Использование шлюзов минимизирует количество соединений и делает вставки более эффективными.
- Обработка на краю - Любые преобразования или обработка событий должны выполняться на краю или в ClickHouse в этой архитектуре. Кроме того, что это ограничивает, это может означать сложные материализованные представления ClickHouse или значительное вычисление на краю - где критические службы могут быть затронуты, а ресурсы ограничены.
- Малые пакеты и задержки - Коллекторы-агенты могут по отдельности собирать очень мало событий. Это обычно означает, что их необходимо настраивать так, чтобы очищать с установленным интервалом для удовлетворения SLA доставки. Это может привести к тому, что коллектор будет отправлять малые пакеты в ClickHouse. Хотя это является недостатком, это можно смягчить за счет асинхронных вставок - смотрите Оптимизация вставок.
Масштабирование с помощью шлюзов
OTel коллекторы могут быть развернуты в качестве экземпляров шлюза, чтобы решить вышеупомянутые ограничения. Они предоставляют отдельную службу, обычно на уровне дата-центра или региона. Эти экземпляры принимают события от приложений (или других коллекторов в роли агента) через единую конечную точку OTLP. Обычно развертывается набор экземпляров шлюзов, и для распределения нагрузки среди них используется готовый балансировщик нагрузки.

Цель этой архитектуры — разгрузить вычислительно интенсивную обработку от агентов, тем самым минимизируя использование их ресурсов. Эти шлюзы могут выполнять трансформации, которые иначе должны были бы выполняться агентами. Кроме того, агрегируя события от многих агентов, шлюзы могут гарантировать, что большие пакеты отправляются в ClickHouse — что позволяет эффективно вставлять данные. Эти коллекторы шлюзов можно легко масштабировать по мере добавления новых агентов и увеличения пропускной способности событий. Пример конфигурации шлюза с сопутствующей конфигурацией агента, потребляющего пример структурированного файла журнала, приведен ниже. Обратите внимание на использование OTLP для общения между агентом и шлюзом.
clickhouse-gateway-config.yaml
Эти конфигурации можно запустить с помощью следующих команд.
Основным недостатком этой архитектуры является сопутствующая стоимость и накладные расходы на управление набором коллекторов.
Для примера управления более крупными архитектурами на основе шлюзов с сопутствующими обучающими материалами, мы рекомендуем этот блог-пост.
Добавление Kafka
Читатели могут заметить, что вышеупомянутые архитектуры не используют Kafka в качестве очереди сообщений.
Использование очереди Kafka в качестве буфера сообщений является популярным шаблоном проектирования, наблюдаемым в архитектурах журналирования, и было популяризировано стеком ELK. Это дает несколько преимуществ; прежде всего, это помогает обеспечить более надежные гарантии доставки сообщений и помогает справляться с обратным давлением. Сообщения отправляются от агентов сбора в Kafka и записываются на диск. В теории, кластерный экземпляр Kafka должен обеспечивать высокую пропускную способность буфера сообщений, так как ему требуется меньше вычислительных ресурсов для линейной записи данных на диск, чем для их разбора и обработки – в Elastic, например, токенизация и индексация требуют значительных ресурсов. Убирая данные от агентов, вы также снижаете риск потери сообщений в результате ротации журнала на исходном уровне. Наконец, он предлагает некоторые возможности повторной передачи сообщений и репликации между регионами, что может быть привлекательным для некоторых случаев использования.
Тем не менее, ClickHouse может быстро обрабатывать вставку данных — миллионы строк в секунду на умеренном оборудовании. Обратное давление от ClickHouse является редким. Часто использование очереди Kafka означает большую архитектурную сложность и затраты. Если вы можете принять принцип, что журналы не нуждаются в тех же гарантиях доставки, что и банковские транзакции или другие критически важные данные, мы рекомендуем избегать сложности Kafka.
Однако, если вам нужны высокие гарантии доставки или возможность повторного воспроизведения данных (возможно, к нескольким источникам), Kafka может быть полезным архитектурным дополнением.

В этом случае можно настроить OTel агентов для отправки данных в Kafka через Kafka exporter. Экземпляры шлюзов, в свою очередь, потребляют сообщения, используя Kafka receiver. Мы рекомендуем ознакомиться с документацией Confluent и OTel для получения более подробной информации.
Оценка ресурсов
Требования к ресурсам для OTel коллектора будут зависеть от пропускной способности событий, размера сообщений и объема выполняемой обработки. Проект OpenTelemetry поддерживает бенчмарки, которые пользователи могут использовать для оценки требований к ресурсам.
На нашем опыте, экземпляр шлюза с 3 ядрами и 12 ГБ ОЗУ может обрабатывать около 60k событий в секунду. Это предполагает минимальный конвейер обработки, отвечающий за переименование полей и без регулярных выражений.
Для экземпляров агентов, отвечающих за отправку событий в шлюз и только устанавливающих временную метку на событие, мы рекомендуем пользователям ориентироваться на предполагаемое количество журналов в секунду. Следующие показатели представляют собой приблизительные числа, которые пользователи могут использовать в качестве отправной точки:
Частота журналирования | Ресурсы для коллектора агента |
---|---|
1k/секунда | 0.2 CPU, 0.2 GiB |
5k/секунда | 0.5 CPU, 0.5 GiB |
10k/секунда | 1 CPU, 1 GiB |