В прошлом году я писал на Хабре про Telescope — инструмент для просмотра логов через веб‑интерфейс. Тогда основной сценарий был связан с ClickHouse, и в комментариях логично возник вопрос: не «прибит» ли инструмент к одной базе данных.
Технически — нет. Модель источников изначально задумывалась расширяемой. Позже появилась поддержка Docker, чтобы Telescope можно было использовать и в локальной разработке, без централизованного хранилища логов.
В версии 0.0.24 добавлен ещё один тип источника логов — Kubernetes. Теперь Telescope может напрямую читать логи pod‑ов через Kubernetes API, сохраняя ту же модель прав доступа и язык фильтрации.
В этом посте хочу показать, что было добавлено в проект и чем это может быть полезно на практике.
Зачем нужен Kubernetes как источник логов
Telescope изначально задумывался как инструмент для работы с логами в ClickHouse. В продакшене это по-прежнему правильная модель: централизованное хранение, индексация, ротация, политики доступов.
Агрегация логов - это база =). Telescope для Kubernetes её не заменяет и не пытается заменить.
Но на практике регулярно возникают ситуации, когда это не применимо:
логи ещё не доехали до ClickHouse
пайплайн доставки сломан (коллектор упал / задержки в обработке)
локальный кластер (например, kind) вообще работает пайплайна сбора логов
нужно быстро посмотреть, что происходит прямо сейчас внутри pod’а.
Обычно дальше начинается вот это: kubectl logs -n namespace pod-name
Потом еще один pod. А потом другой namespace.
Работает? Да.
Удобно? Не всегда
Если нужно посмотреть логи сразу с нескольких pod-ов, отфильтровать их, ограничить по времени - всё это превращается kubectl/grep/bash/awk кунг-фу.
Поэтому и появился Kubernetes как отдельный источник в Telescope.
Чтобы можно было напрямую читать логи pod-ов через API кластера и работать с ними так же, как с другими источниками.
Это не замена централизованному сбору логов, а дополнение к нему.
Возможности работы с логами Kubernetes pod-ов в Telescope
После добавления поддержки Kubernetes в Telescope можно:
Читать логи сразу с нескольких pod-ов
Можно выбрать несколько pod-ов одновременно.
Они могут быть из разных namespace и даже из разных кластеров.
Логи объединяются в один поток и сортируются по времени.
Использовать язык фильтрации
Можно фильтровать логи с помощью языка запросов. Например:
namespace !~ kube-system and pod ~ 'nginx' and pod not ~ 'nginx-debug' and context !~ production
Показать логи из namespace, который не содержит kube-system, из pod-ов, в имени которых есть nginx, но при этом исключить pod’ы с nginx-debug, и не брать кластеры (contexts), которые относятся к production.
Также для подов доступны все аннотации и лейблы, и их тоже можно использовать в выражениях.
Подробнее про язык запросов FlyQL в документации или в репозитарии проекта.
Ограничивать Context, Namespace и Pod’ы при фильтрации
Можно заранее ограничить область поиска:
выбрать нужные context из kubeconfig
отфильтровать namespace и pod-ы на стороне Kubernetes API
дополнительно применить фильтрацию внутри Telescope через FlyQL
Это может быть удобно, если у вас большие кластеры с большим количеством pod/namespace и/или разросшийся kubeconfig.
В моём, например, сейчас 286 контекстов:
cat ~/.kube/config|yq -r '.contexts[].name'|wc -l 286
Нормализовать уровень логирования (severity)
В неструктурированных логах уровень логирования может быть в разном формате.
В Telescope можно настроить правила извлечения severity из строки.
После этого уровень логирования отображается одинаково для всех записей.

Смотреть график распределения по severity
Можно отобразить график количества логов по уровням.
Это помогает быстро понять, что происходит - например, если резко выросло число ошибок.

Сохранять представления (Saved views)
Можно сохранить текущую настройку:
фильтр,
выбранные поля,
диапазон времени,
группировку.
И потом открыть её одной ссылкой.
Это удобно для повторяющихся сценариев.
Как это работает внутри
Чтобы всё это работало без отдельного режима и костылей, Kubernetes встроен в общую модель источников Telescope.
Connections и Sources
В первых версиях Telescope настройки подключения и описание источника логов находились в одном месте. Отдельного разделения не было.
Позже я решил разделить эти сущности. Причина простая: одно и то же подключение может использоваться для разных источников логов.
Например:
один сервер ClickHouse - несколько таблиц
один Kubernetes-кластер - разные namespace
Держать всё это в одной сущности оказалось неудобно и небезопасно.
Например, в реальной команде роли могут быть разделены:
DBA - настраивают саму базу данных и пользователей в ней.
DevOps / Администраторы - настраивают Source: выбирают таблицы, колонки, правила отображения. При этом они не обязаны знать логины, пароли и детали подключения к конкретной базе.
Разработчики - просто используют log-viewer для просмотра логов. Они могут даже не знать, откуда именно приходят данные.
Если всё хранить в одной сущности, такое разделение становится сложным или вообще невозможным.
Чтобы добиться нормального разграничения доступа, в Telescope появились две отдельные концепции — Connection и Source.
Connection - это только способ подключения. Хранит технические параметры.
Например, для ClickHouse это:
Пользователь / Пароль
Хост / Порт
Настройки TLS
Подробнее в документации
Source, в свою очередь - это уже описание конкретного источника логов.
Он использует Connection и определяет:
где именно брать данные (таблица в ClickHouse, контейнеры Docker, pod’ы в Kubernetes)
какие поля доступны
какая колонка отвечает за время
какая - за уровень логирования
какие настройки применяются при отображении.
Source не хранит логины и пароли - он просто использует уже настроенный Connection.
Работа с Kubernetes API
Kubernetes API позволяет получать логи только для конкретного pod-а.
Поэтому перед тем как запросить сами логи, Telescope сначала определяет, с какими pod-ами нужно работать.
При выполнении поиска происходит примерно следующее:
загружается список context из kubeconfig (применяя правила фильтрации для context)
загружается список namespace для каждого context (применяя правила фильтрации для namespace)
запрашивается список pod-ов (применяя правила фильтрации для pod)
для выбранных pod-ов запрашиваются логи
к строкам применяется фильтрация через язык запросов.
записи объединяются и сортируются по времени
Kubernetes API не умеет фильтровать логи по содержимому, поэтому эта фильтрация выполняется внутри Telescope после получения данных.
Списки namespace и pod-ов временно кешируются, чтобы не перегружать API кластера.
Запросы логов для разных pod-ов выполняются параллельно, при этом количество одновременных запросов можно ограничить в настройках Source.
Ограничения
Kubernetes-источник в Telescope - это прямой доступ к логам через API кластера. И у такого подхода есть ограничения.
Во-первых, Telescope не хранит эти логи.
Он запрашивает их напрямую у Kubernetes API. Если pod уже удалён - получить его логи не получится.
Во-вторых, нет индексации и полнотекстового поиска на уровне хранения, как в ClickHouse.
Фильтрация выполняется уже после получения логов.
В-третьих, производительность зависит от API кластера.
Если запрашивать логи сразу для большого количества pod-ов или за большой период времени, количество API-запросов может быть значительным.
Планы
Telescope не разрабатывается фуллтайм - это мой pet-project. Тем не менее, работа продолжается.
К счастью, в проект уже приходят pull request-ы от сообщества, чему я очень рад. Например, недавно принесли поддержку StarRocks как ещё одного источника.
Есть и задачи, которые хотелось бы довести до релизной версии:
отображение записей «в контексте» (например, соседние строки, что-то в духе
grep -A 10 -B 10)сохранение snapshot-ов логов, чтобы можно было сохранить какие-то логи на долгосрок для дальнейшего изучения
Live tail aka real time updates
аудит изменений внутри системы
Ссылки
Если интересно попробовать - ссылки ниже.
Код проекта на GitHub
Рабочая инсталляция (требуется авторизация через GitHub) - где можно потыкать палочкой интерфейс для ClickHouse demo source.
