Настройка Distributed Tracing через Jaeger: инструментирование и деплой

Когда сбой идёт по цепочке сервисов, поиск причины растягивается на часы ручных сверок. Мы настраиваем Jaeger под ключ: инструментируем сервисы, разворачиваем сбор и хранение трассировок, передаём команде регламенты работы. Время поиска причины инцидента сокращается в разы.
Часто задаваемые вопросы

Почему трассировка теряется: что ломается без Jaeger

В распределённой системе один запрос проходит через шлюз, несколько сервисов, очередь и базу. Но общей нити между ними нет: идентификатор запроса не передаётся дальше по цепочке, метки времени на разных узлах расходятся, а часть вызовов уходит асинхронно и вовсе не попадает в журнал вызывающей стороны. Собрать из этого путь запроса нельзя — можно только предполагать, где он сломался.

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

Цена такой диагностики сбоев — не только часы дежурного. Пока источник не найден, растут задержки, копятся ошибки на стороне клиентов, а изменения вносятся наугад: правка, которая «должна была помочь», закрывает симптом и маскирует причину.

Сквозная трассировка закрывает это иначе: каждый запрос получает единый идентификатор, который передаётся по всей цепочке вызовов, а Jaeger собирает из этих данных дерево операций с длительностью каждой. Ниже разбираем, как это разворачивается и что даёт в момент реального инцидента.

Что даёт сквозная трассировка распределённой системы

В распределённой системе один запрос проходит через несколько сервисов, и при сбое логи показывают лишь фрагменты: видно, что сервис ответил долго, но не видно, из-за чего. Наблюдаемость без сквозной трассировки упирается в ручной перебор сервисов, а каждая минута поиска — это минута недоступности.

Сквозная трассировка собирает весь путь запроса в единую цепочку с длительностью каждого шага. Jaeger хранит такие цепочки и раскладывает запрос на интервалы: какой вызов занял основное время, где накопилась очередь, какая зависимость отвечала с задержкой. Инженер открывает конкретный медленный запрос и видит узкое место по времени и объёму обращений — без перебора сервисов вручную.

Практический эффект измерим: поиск причины сбоя сокращается с часов перебора гипотез до минут, а доля отказов, которые не удаётся объяснить, падает — цепочка либо показывает проблемный участок, либо доказывает, что дело вне системы.

Меняется и класс разбираемых отказов. Вместо «иногда всё тормозит» появляется конкретный участок с превышением времени, привязанный к версии, конфигурации и объёму нагрузки. Время восстановления определяется уже не поиском виноватого, а исправлением.

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

Режимы развёртывания Jaeger: сравнение вариантов

Выбор режима развёртывания определяет не только то, как быстро трасса попадает в интерфейс, но и сколько ресурсов закладывать в кластер и как разводить окружения. Само инструментирование сервисов от этого не зависит, а вот хранилище трасс, отказоустойчивость и масштабирование — зависят полностью. Ниже — варианты, между которыми реально выбирают на старте и при росте потока спанов.

Вариант Когда подходит Ограничения
Один процесс со хранением в памяти Локальная отладка, проверка корректности инструментирования, демо Трассы исчезают при перезапуске, нет горизонтального роста, не годится для общего контура
Коллектор и хранилище Elasticsearch внутри рабочего кластера Команда среднего размера, глубина хранения 14–30 дней, окружения разводятся пространствами имён Ресурсы делят с рабочими сервисами, обязательны настройки ретенции и число реплик
Отдельный контур трассировки на Cassandra Высокий поток спанов, хранение месяцами, отдельный контур эксплуатации Дороже в сопровождении, нужна экспертиза по схеме и обновлениям, сложнее разворачивать окружения
Коллектор как буфер (Kafka) перед внешним хранилищем Пиковые нагрузки, просадка хранилища не должна ронять приём трасс Трассы появляются с задержкой, добавляются точки отказа, нужен мониторинг очереди
Управляемый сервис трассировки Малая команда без выделенного дежурного по хранилищу Меньше контроля над схемой и сроком хранения, привязка к поставщику

Коллектор не хранит состояние: его экземпляры масштабируются горизонтально за балансировщиком, а агент на каждой ноде буферизует спаны и переживает перезапуск. Отказоустойчивость упирается в хранилище — реплики и кворум настраиваются на стороне базы, а не на стороне трассировки.

Изоляцию окружений лучше делать отдельными инстансами коллектора и отдельными индексами на среду, иначе тестовый поток размывает выборку и раздувает объём хранения. Частота сэмплирования задаётся для каждой среды отдельно: в разработке пишем всё, в проде — долю с гарантированным сохранением медленных и ошибочных запросов, иначе разбор инцидента остаётся без данных.

Внедрение Jaeger: этапы инженерной работы

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

  1. Обследование сервисов и точек входа. Фиксируем список сервисов, протоколы обмена и места, где теряется контекст: очереди, фоновые задания, внешние вызовы. На выходе — карта, по которой видно, какие участки пути сейчас не наблюдаемы.

  2. Схема потоков трасс. Договариваемся о едином формате передачи контекста между сервисами, правилах именования операций и атрибутов. Без этого трассы склеиваются в обрывки и не показывают полное время ответа.

  3. Развёртывание Jaeger. Коллектор приёма, хранилище, интерфейс поиска: разносим приём и запись, задаём срок хранения трасс и очистку старых, решаем, где ставить агентов — на узлах или рядом с приложением.

  4. Инструментирование сервисов. Включаем автоматический сбор на стандартных библиотеках, критичные участки размечаем вручную, чтобы в трассе появились бизнес-атрибуты. Здесь же задаём правила выборки: сплошной сбор на пике раздувает хранилище, редкий — теряет аномалии.

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

  6. Передача документации и регламентов. Отдаём схемы потоков, конфигурацию, панели мониторинга, правила оповещений и порядок действий при деградации. Команда добавляет новый сервис в наблюдаемость уже без нас.

Дальше остаются только правки: подключение сервиса или смена хранилища — это изменение конфигурации, а не пересборка системы.

Комплект передачи: схемы трассировки, политики отбора и регламенты

Комплект передаём не архивом настроек, а как работающий контур: у каждого документа есть владелец и сценарий использования. Ниже — что остаётся в вашей инфраструктуре вместе с развёрнутым Jaeger и как этим пользоваться без нас.

  • Конфигурации сбора — файлы приёма и обработки трасс с правилами выборки: какие сервисы трассируются целиком, какие по доле запросов, какие исключены из-за объёма.
  • Схема потока трасс — диаграмма пути данных от сервиса до хранилища и интерфейса поиска, с отмеченными точками отказа и местами, где трасса теряется.
  • Политики доступа — роли и области видимости: кто видит все сервисы, кто только свои, как выдаются и отзываются права, где лежат ключи.
  • Правила хранения — сроки жизни трасс по типам, условия досрочной очистки, разбиение по индексам и сжатие; отдельно долгий срок для трасс разобранных инцидентов.
  • Инструкции дежурной смены — как за минуту проверить, что трассировка жива, что делать при задержке приёма и как откатить правку конфигурации.
  • Регламент плановых проверок — сверка объёма хранилища, контроль доли отброшенных трасс, сквозной тест после обновления сервисов.
  • Карта инструментирования — сервисы и библиотеки с версиями, чтобы при обновлении не потерять совместимость и не остаться без трасс.
  • Журнал изменений — кто и зачем правил правила выборки; без него через полгода никто не объяснит пропажу трасс конкретного сервиса.

Кейс: как сократили время поиска причины сбоя

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

Локализация причины занимала 3-4 часа, ещё столько же — на подтверждение гипотезы. Около трети инцидентов закрывали без объяснённой причины: симптом убирали, корень не находили, и через несколько недель он проявлялся в другом месте. Среднее время восстановления держалось на уровне нескольких часов.

Что изменили

Внедрили Jaeger и сквозной идентификатор запроса, который пробрасывается через все вызовы, включая асинхронные. Инструментировали места, где чаще всего терялось время: обращения к базе, внешние вызовы, постановку и обработку сообщений в очередях. Сэмплирование настроили адаптивно — медленные и редкие запросы сохраняются целиком, поток рутинных не раздувает хранилище.

Что стало

Ссылка на трейс прикладывается к карточке инцидента — разбор начинается с факта, а не с перебора версий. Локализация сократилась до 10-15 минут, время восстановления — в разы, доля инцидентов без объяснённой причины упала до единичных случаев. Повторяющиеся сбои стало видно по общей картине вызовов, и их закрывают на разборе, а не после третьего обращения.

Чем Jaeger отличается от сбора логов и метрик

Журналы и числовые показатели отвечают на разные вопросы, но оба смотрят на систему фрагментами. Метрика показывает, что выросла задержка или упала доля успешных ответов, — но не говорит, на каком шаге это произошло. Журнал фиксирует событие с текстом и контекстом отдельного сервиса, и в распределённом контуре его приходится вручную сопоставлять с записями соседей по времени.

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

Граница применимости простая. Журналы незаменимы, когда нужен точный текст ошибки или значение поля. Числовые показатели — когда важны тренды, оповещения и стоимость хранения: они компактны и дёшевы на длинном горизонте. Путь запроса нужен там, где потери времени рождаются на стыке сервисов: метрика находит всплеск, трассировка указывает конкретный шаг и его долю в общей задержке, а журнал по тому же идентификатору даёт причину.

Дополняют они друг друга, а не заменяют: связка «всплеск → конкретный шаг → сообщение об ошибке» сокращает поиск причины с часов до минут. При этом трассировать всё подряд не нужно — семплирование на входе задаёт долю записываемых запросов, а отбор по ошибкам и медленным ответам оставляет именно те, что стоит разбирать.

Технические сомнения: нагрузка, объём данных, совместимость

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

Насколько вырастет время ответа?

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

Как быстро растёт объём хранилища?

Объём задают три вещи: число инструментированных операций, коэффициент выборки и срок хранения. Сырые интервалы держим несколько дней, агрегаты — дольше, на каждое имя сервиса настраиваем политику удаления. Реестр перестаёт расти бесконтрольно, а разбор инцидента за прошлую неделю остаётся возможным.

Совместимо ли это с нашими окружениями и стеками?

Сбор идёт в едином формате для контейнеров, виртуальных машин и бессерверных функций: агент ставится рядом с приложением, поэтому перенос между средами не меняет схему данных. Стек тоже не критичен — библиотеки инструментирования есть для основных языков, а нестандартные обвязки закрываем ручными интервалами или шлюзом-посредником.

Что делать с частично инструментированными сервисами?

Их подключаем поэтапно: крайние точки — балансировщик, шлюз, база — дают сквозную картину сразу, а промежуточные звенья добавляем по мере правок в код. Разрыв в цепочке виден как отдельный интервал и помечается в схемах как незакрытый участок, но поиску узкого места это не мешает.

Можно ли снизить сбор без пересборки сервисов?

Да. Выборка и приём управляются на стороне сборщика: при нештатной нагрузке достаточно уменьшить коэффициент или временно отключить источник — приложения продолжают работать. Возврат к предыдущей конфигурации агента тоже не требует релиза.

Обсудим задачу: что понадобится с вашей стороны

Агент собирает трейсы и отправляет их в Jaeger, но чтобы развернуть коллектор и связать его с вашими сервисами, нужен доступ к инфраструктуре и понимание того, как устроены контуры. Ниже — что запрашиваем на старте работ: этого хватает, чтобы вернуться с планом и оценкой, без уточняющих раундов в середине внедрения.

  • Доступы: учётные записи к кластеру и реестру образов, права на создание объектов в отдельном пространстве имён — без прав на изменение боевых рабочих нагрузок.
  • Перечень сервисов: какие приложения инструментируем, на каких языках и библиотеках они написаны, есть ли уже выгрузка трейсов хоть в каком-то виде.
  • Окружения: сколько контуров — разработка, предпродуктивный, боевой; нужен ли Jaeger в каждом или достаточно одного с разделением по подразделениям.
  • Требования к срокам хранения: сколько дней трейсы должны оставаться доступными для разбора инцидентов и кто по ним ходит.
  • Порядок согласования изменений: когда можно выкатывать правки в конфигурацию сервисов, кто подтверждает, нужен ли откат в один шаг.
  • Схема связей между сервисами: есть ли прокси и балансировщики, которые нужно учесть, чтобы контекст не терялся.
  • Ответственный за приёмку: инженер, который проверит, что трейсы собираются сквозными и находятся по идентификатору запроса.

Опишите задачу и пришлите эти данные — вернёмся с планом работ: этапы, границы нашей ответственности, порядок выката по окружениям и точки, где нужно ваше подтверждение.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1393
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    815
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139