linkerd-destination: архитектура и мониторинг меша

Где происходит магия: роль linkerd-destination

Недавно в ходе повседневной эксплуатации мы детально разобрали внутреннее устройство linkerd-destination — одного из ключевых компонентов плоскости управления (control plane) Linkerd.

Причина была проста: по мере роста кластера и увеличения трафика вопрос сместился с «Работает ли Linkerd?» на «Как именно он реагирует, когда всё меняется одновременно?». Частые деплои, масштабирование в продакшене, применение политик безопасности — и в центре всего этого сервис destination.

В процессе анализа я совмещал изучение кода, наблюдение за поведением в продакшене и обращение к документации. Чтобы структурировать этот процесс, я использовал метод Zettelkasten: связывал атомарные идеи до тех пор, пока не сложилось чёткое представление об интеллекте, стоящем за мешем. Эта статья — итог того синтеза. Погружаемся?

Где происходит магия: роль linkerd-destination

Современная микросервисная архитектура требует выделенного инфраструктурного слоя для управления коммуникациями — сервисного меша (Service Mesh). Linkerd, один из пионеров в этой области, выделяется операционной простотой и высокой производительностью.

Чтобы понять, как Linkerd работает на практике, необходимо разобрать его плоскость управления, и прежде всего компонент linkerd-destination. Он выступает центральным органом маршрутизации и применения политик для всего меша: переводит динамическое состояние Kubernetes в конкретные решения и распространяет их в реальном времени на тысячи прокси. Три основные функции компонента:

  • Service Discovery (обнаружение сервисов): переводит логические DNS-имена в наборы реальных эндпоинтов, обогащая каждый адрес метаданными (mTLS-идентичность, локальность/зона, протокол).

  • Policy Distribution (распространение политик): сообщает прокси, какие соединения авторизованы, опираясь на современные ресурсы Gateway API и CRD политик (Server, AuthorizationPolicy).

  • Service Profiles (L7-конфигурация): предоставляет расширенные правила седьмого уровня — маршруты на основе регулярных выражений, бюджеты повторных попыток и таймауты.

На диаграмме ниже показан поток взаимодействия между плоскостью управления и прокси в плоскости данных:

Диаграмма взаимодействия между control plane и прокси в data plane

Важно понимать последствия деградированного состояния (Degraded State): если сервис destination выходит из строя, прокси продолжают работать на основе последней известной конфигурации (кэширование). Однако кластер теряет способность реагировать на новые деплои и оперативные изменения политик безопасности — канал обновлений, показанный выше, прерывается.

Внутренняя архитектура: разделение ответственности

Чтобы понять поведение linkerd-destination при высокой нагрузке, нужно заглянуть внутрь пода. Это вовсе не монолитный контроллер — Linkerd чётко разделяет ответственность между несколькими взаимодействующими контейнерами.

На следующей диаграмме подробно показано, как Destination API внутренне разделён для одновременной обработки обнаружения сервисов, профилей и политик авторизации:

Внутренняя структура Destination API с разделением контейнеров
  1. Контейнер Destination: сердце системы (Go). Реализован на Go и работает как контроллер, управляемый событиями. Использует паттерн Informer/Reflector из библиотеки client-go, избегая дорогостоящего поллинга Kubernetes API.

  2. Контейнер SP-Validator: страж. Работает как Validating Admission Webhook — блокирует синтаксические ошибки в Service Profiles ещё до того, как они попадут в etcd.

  3. Контейнер Policy: судья. Оценивает политики безопасности (MeshTLSAuthentication) независимо от остальных компонентов.

  4. Прокси внутри прокси. Сам под destination содержит инжектированный linkerd-proxy. Это гарантирует, что трафик плоскости управления защищён mTLS и полностью наблюдаем.

Производительность: события и трансляция

Сервис destination не опрашивает API периодически — он реагирует на Watches. Когда под появляется в кластере, генерируется событие, которое обрабатывает EndpointTranslator.

Этот «мозг» обогащает сырые данные Kubernetes: сопоставляет IP-адреса для извлечения идентичностей и определяет зоны доступности для оптимизации маршрутизации. Кроме того, использование EndpointSlices позволяет системе обрабатывать только «дельты» (частичные изменения) — это критически важно для здоровья системы в крупных кластерах.

Destination API и gRPC-стриминг

Взаимодействие между прокси и destination — это непрерывный поток. При вызове destination.Get() сервер удерживает стрим открытым и отправляет:

  • Initial Batch (начальный пакет): полное состояние на момент подключения.

  • Incremental Updates (инкрементальные обновления): только дельты (add / remove).

  • NoEndpoints: критическое сообщение, которое заставляет прокси выполнить fail fast, если здоровых экземпляров нет.

Диаграмма последовательности ниже отражает весь этот жизненный цикл и демонстрирует эффективность коммуникации на основе push-модели:

Диаграмма последовательности gRPC-стриминга между прокси и destination

Наблюдаемость: что мониторить?

В ходе нашего глубокого погружения мы выявили конкретные сигналы, которые служат «ЭКГ» плоскости управления:

  • services_informer_lag_seconds: задержка между изменением в K8s и тем, как Linkerd его воспринимает.

  • endpoint_updates_queue_overflow: значение больше 0 означает, что система отбрасывает обновления из-за перегрузки.

  • grpc_server_handled_total: следите за ростом кодов ошибок (всё, что отличается от OK).

  • proxy_inject_admission_responses_total: отражает успешность инжекции сайдкаров по всему кластеру.

  • control_response_total: показывает успешность ответов плоскости управления в реальном времени.

  • identity_cert_expiration_timestamp_seconds: обратный отсчёт безопасности. Игнорировать эту метрику — значит принять риск полного простоя из-за истёкших mTLS-сертификатов.

Примечание: дополнительные метрики можно получить командой:

$ linkerd diagnostics controller-metrics

Заключение

Сервис linkerd-destination — это точка соединения между динамизмом Kubernetes и предсказуемостью сервисного меша. Понимание его событийно-ориентированной архитектуры и роли EndpointTranslator необходимо для уверенной эксплуатации Linkerd в высоконагруженных средах.

Если вы используете Linkerd в продакшене или вам когда-либо приходилось расследовать поведение плоскости управления под нагрузкой, глубокое понимание компонента destination полностью меняет подход к отладке и масштабированию меша.

© 2026 meganuke