ADG Оставить заявку
Блог DevOps 5 мин чтения

Envoy Proxy 1.6: разбираем xDS API и sidecar-паттерн для observability без правок в коде

Погружаемся в архитектуру Envoy 1.6: как xDS API и sidecar-паттерн дают полную observability между микросервисами без единого изменения в коде приложений.

Контекст момента

Envoy Proxy 1.6 - рост популярности как data plane для service mesh на базе xDS API и sidecar-паттерна

Когда мы в феврале разбирались с Istio 0.5, Envoy там был как данность - «sidecar-прокси, который инжектируется в поды». Мы его не трогали, просто пользовались. После нескольких недель работы с Istio возникло ощущение что не понимаем ключевой части механизма: как именно Envoy получает конфигурацию, как он решает куда слать трафик, и почему за этим стоит целый слой абстракции который называется xDS API. Решили разобраться.

Envoy 1.6 вышел в начале апреля. Lyft разработал его изначально для себя, сейчас он под крышей CNCF и используется как data plane в Istio, в Ambassador, и в ряде других проектов. Мы потратили несколько дней на то чтобы понять архитектуру - не как пользователи Istio, а как люди которые хотят понимать что происходит под капотом.

Что такое data plane и причём тут xDS

Service mesh делится на две части: data plane (собственно трафик) и control plane (управление). Envoy - это data plane. Он перехватывает трафик, применяет правила, собирает метрики. Control plane (в случае Istio - Pilot) говорит ему что делать.

Разговаривают они через xDS API - набор gRPC-стримов, где «x» - это разные типы дескрипторов:

  • LDS (Listener Discovery Service). Envoy получает описание listeners - на каких портах слушать и что с входящими соединениями делать.
  • RDS (Route Discovery Service). Правила маршрутизации: какой URL куда направлять, веса для traffic splitting, retry-политики.
  • CDS (Cluster Discovery Service). Описание upstream-кластеров - набор эндпоинтов к которым Envoy будет подключаться.
  • EDS (Endpoint Discovery Service). Конкретные IP:port для каждого кластера - обновляется динамически когда меняется состав подов.

Важное свойство xDS: это push-модель через gRPC bidirectional streaming. Pilot не ждёт пока Envoy спросит - он сам толкает обновления при изменении конфигурации. Новый под появился в кластере - EDS-обновление прилетает в Envoy за секунды. Это сильно отличается от poll-based подходов где прокси периодически ходит за конфигом.

Sidecar-паттерн: как это выглядит изнутри пода

В Kubernetes схема такая. В каждый pod кроме контейнера с приложением добавляется контейнер с Envoy. Трафик перехватывается через iptables-правила - init-контейнер при старте пода прописывает правила которые редиректят все входящие и исходящие соединения на Envoy (порт 15001 в случае Istio).

Приложение об этом не знает. Оно открывает соединение на service-b:8080 - ядро перехватывает его и отдаёт Envoy. Envoy смотрит в свою конфигурацию, находит cluster для service-b, выбирает эндпоинт через load balancing, устанавливает реальное соединение. В обратную сторону - входящий трафик тоже идёт через Envoy прежде чем попасть в приложение.

Это даёт кое-что важное: Envoy видит весь трафик в обоих направлениях и может собирать по нему статистику. Без изменений в коде приложения.

Что Envoy даёт по observability

Вот здесь начинается практически полезная часть. Каждый Envoy-sidecar автоматически генерирует:

  • Метрики - request rate, error rate, latency percentiles (p50/p95/p99) для каждой пары (источник, назначение). Экспортируются в Prometheus-формате.
  • Access logs - структурированные логи каждого запроса: timestamp, source, destination, HTTP-метод, статус, latency, bytes.
  • Distributed tracing - Envoy инжектирует и пробрасывает заголовки для Zipkin/Jaeger (b3-заголовки). Приложение должно только пробрасывать эти заголовки дальше при исходящих вызовах - это минимальное требование к коду.

На практике это означает что в кластере с Envoy-sidecar у вас есть service dependency graph с реальным трафиком, а не нарисованный вручную. Istio визуализирует это через Servicegraph, и первый раз когда видишь живой граф с метриками - это производит впечатление. Особенно если в кластере сервисов пятнадцать и раньше про некоторые связи никто особо не задумывался.

Администрирование: что можно посмотреть в runtime

У Envoy есть admin-интерфейс на порту 9901 (по умолчанию). Там можно посмотреть:

  • /config_dump - полная текущая конфигурация: все listeners, routes, clusters, endpoints. Это отладочный инструмент первого выбора когда что-то идёт не так с маршрутизацией.
  • /clusters - состояние каждого upstream-кластера: количество активных соединений, статистика запросов, статус health check.
  • /stats - все метрики в текстовом формате. Их несколько тысяч, зато там есть буквально всё.

Когда мы разбирали проблему с неработающим traffic shifting в Istio - /config_dump показал что Pilot не успел раздать обновлённый RouteConfiguration в sidecar проблемного пода. Это была гонка при рестарте пода, не баг в конфигурации. Без admin API это было бы сложно поймать.

Overhead: честная оценка

По нашим наблюдениям на тестовом стенде Envoy потребляет порядка 50 MB памяти per pod при базовой нагрузке, и ощутимо меньше CPU чем мы ожидали при умеренном RPS. Latency-overhead - единицы миллисекунд на hop, на нашей нагрузке это в пределах погрешности. При высоком RPS картина другая - нужно мерять конкретно.

Главный overhead не технический, а операционный. Когда у вас сотня подов, каждый с Envoy, и что-то идёт не так - нужно понимать где искать: в приложении, в Envoy, в Pilot. Это другая модель отладки. kubectl logs показывает только половину картины. К этому надо привыкнуть и надо иметь правильные инструменты рядом.

Где мы сейчас

Для managed-кластеров Envoy выглядит как серьёзная история. Не для каждого клиента и не прямо сейчас, но для крупных инсталляций где десятки сервисов и observability - реальная боль, а не теоретическая проблема, это уже рабочий вариант.

Istio с Envoy под капотом даёт observability-слой который раньше нужно было собирать из нескольких разных инструментов и кода в каждом сервисе. Это реальная ценность. Вопрос в том готова ли операционная команда к дополнительной сложности - потому что Envoy добавляет её честно, без скидок.

Следующий шаг у нас - нагрузочный тест на реальном профиле трафика и проверка поведения при сбое Pilot: что происходит с трафиком если control plane недоступен. Это критичный сценарий для production, и документация по нему пока скупая.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.