lenec ru

← все посты

API gateway против service mesh: где провести границу в реальной архитектуре

18K

«Нам нужен gateway» и «мы переезжаем на service mesh» — две фразы, которые я слышу на проектах с микросервисами с одинаковой регулярностью. И каждый раз приходится разбираться, что именно команда хочет: маршрутизацию, авторизацию, наблюдаемость, отказоустойчивость или всё сразу. Потому что gateway и mesh решают пересекающиеся, но разные задачи.

Полтора года назад на одном из проектов я разбирал слой инфраструктуры, где жили оба: NGINX-based gateway и Istio. Часть функций дублировалась, часть конфликтовала, и команда честно не могла объяснить, кто за что отвечает. Решение пришло после того, как мы вернулись к базовым вопросам: что такое north-south трафик, что такое east-west, и почему их разделение — это не теория, а способ принять решение.

North-south и east-west

Проще всего разделить так. North-south — трафик из внешнего мира в систему: пользователи, мобильные приложения, партнёры по API. East-west — трафик между сервисами внутри системы: orders зовёт payments, payments зовёт notifications.

API gateway традиционно живёт на границе — обрабатывает north-south. Service mesh работает внутри — управляет east-west. На картинке это два разных слоя, и если у вас оба, они логически не пересекаются.

Проблема в том, что обе технологии умеют похожие вещи: оба делают маршрутизацию, оба умеют retry, circuit breaker, mTLS, распределённую трассировку. Разница — в зоне ответственности и в том, как они подключаются.

Что делает gateway

API gateway — это reverse proxy с дополнительной логикой, через который проходит весь внешний трафик. Типичный набор функций:

  • Маршрутизация: /api/orders/* → orders-service, /api/users/* → users-service.
  • Аутентификация: проверка JWT, OAuth2-токенов, API-ключей.
  • Rate limiting на пользователя или API-ключ.
  • Терминация TLS: внешний HTTPS, внутрь — HTTP или mTLS.
  • Трансформация: версионирование URL, склейка/разделение параметров.
  • Логирование и метрики на уровне публичного API.

Реализации: Kong, NGINX Ingress, Traefik, AWS API Gateway, Spring Cloud Gateway. Все делают примерно одно — отличаются стеком и моделью конфигурации.

Gateway знает про публичный API. Внутреннее устройство системы — какие сервисы между собой ходят и как — его не касается.

Что делает service mesh

Service mesh — слой инфраструктуры, который перехватывает весь трафик между сервисами через sidecar-прокси (обычно Envoy), стоящий рядом с каждым подом.

Каждый исходящий запрос сервиса A к сервису B сначала уходит в sidecar A, оттуда — в sidecar B, оттуда — в сам сервис B. Сами сервисы не знают, что между ними кто-то стоит. Mesh добавляет:

  • mTLS между всеми сервисами автоматически.
  • Трассировку: каждый sidecar добавляет/прокидывает trace headers.
  • Метрики: latency, request rate, error rate на каждом коннекте без кода в сервисе.
  • Управление трафиком: canary, mirroring, fault injection.
  • Retry, circuit breaker, timeout — на уровне sidecar.
  • Авторизация между сервисами: «orders может звать payments, но не billing».

Реализации: Istio, Linkerd, Consul Connect, AWS App Mesh, Cilium Service Mesh.

Mesh знает про внутреннюю топологию. Он не предназначен быть точкой входа для внешнего трафика — для этого у него есть отдельные ingress-компоненты (Istio Gateway, Linkerd для ingress).

Где они пересекаются

Главное пересечение — авторизация и наблюдаемость. И то и другое умеют оба слоя, но по-разному.

Gateway проверяет JWT клиента и передаёт результат дальше: X-User-Id в заголовке. Сервис верит этому заголовку. Mesh может дополнительно проверять, что вызов идёт от правильного сервиса (mTLS-идентичность), но не знает про конечного пользователя.

Логика разделяется так: identity пользователя — gateway, identity сервиса — mesh. Двойная защита: внешний клиент аутентифицирован, и каждый внутренний хоп подписан mTLS. Если кто-то прорвался через gateway с фейковым JWT, он не сможет подделать mTLS-сертификат сервиса.

Когда хватает только gateway

Gateway без mesh — рабочая конфигурация для:

  • Стартапов и небольших систем (до 10–15 сервисов).
  • Команд, у которых нет выделенного platform-ops ресурса.
  • Случаев, когда mTLS внутри кластера не критичен (например, всё в одной VPC с сетевыми политиками).
  • Случаев, когда наблюдаемость закрыта на уровне приложения через OpenTelemetry SDK.

Mesh — тяжёлая инфраструктура. Istio из коробки добавляет к каждому поду sidecar в 100–200 МБ памяти и удваивает количество сетевых хопов. Linkerd легче, но всё равно ресурсы.

Если ваш масштаб — 15 сервисов, 5 разработчиков, и вы не делаете canary-релизы каждый день, mesh будет стоить дороже, чем приносить.

Когда нужен только mesh

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

В этом случае gateway избыточен: внешнего трафика нет, аутентификация делается через service-to-service mTLS. Mesh обеспечивает всё остальное: маршрутизацию, наблюдаемость, надёжность.

Признаюсь, я видел такую конфигурацию один раз за двенадцать лет. Чаще всё-таки есть какая-то внешняя поверхность, и для неё нужен gateway.

Когда оба

Большинство зрелых систем приходят к комбинации. Gateway на границе, mesh внутри.

Конкретный сценарий — обработка запроса от пользователя:

  1. Запрос приходит в gateway. Тот проверяет JWT, делает rate limiting, направляет в нужный сервис.
  2. Между gateway и orders-service запрос идёт через sidecar mesh (gateway чаще всего тоже в mesh).
  3. Orders зовёт payments через свой sidecar. Mesh добавляет mTLS, проверяет authorization policy «orders может звать payments».
  4. Payments возвращает ответ через sidecar обратно.

В этой схеме gateway не знает, как orders ходит к payments, и не должен знать. Mesh не знает, что запрос пришёл от пользователя Васи, и тоже не должен.

Где проводить границу

Когда я разбираю существующую инфраструктуру, я смотрю на дублирование функций.

Retry/circuit breaker. Если оба настроены — выбирайте одно место. Лучше mesh, потому что он ближе к сервису и видит больше контекста. Gateway пусть только маршрутизирует.

Rate limiting. На уровне внешнего пользователя — gateway. На уровне сервис-к-сервису (защита от лавины внутренних вызовов) — mesh. Это разные задачи, и они не дублируются.

mTLS. Если у вас mesh, mTLS внутри — его работа. Gateway терминирует внешний TLS, общается с внутренним сервисом тоже через mTLS, который выписывает mesh.

Аутентификация. Внешняя — gateway. Внутренняя service-to-service — mesh. Никогда не дублируйте: внутренний сервис проверяет JWT, проверяет mTLS-идентичность, и ещё что-то — это нечитаемая мешанина.

Метрики. Mesh даёт метрики «бесплатно» на каждый коннект. Gateway — на каждый external endpoint. Не надо писать те же метрики в коде сервиса вручную.

Подводные камни

Несколько вещей, на которые я наступал.

Конфигурационная сложность. Istio из коробки — это десятки CRD: VirtualService, DestinationRule, AuthorizationPolicy, PeerAuthentication. У команды, которая поставила mesh «на всякий случай», конфигурация быстро превращается в YAML-болото. Решение — стандарты на конфигурацию: что-то типа внутренних шаблонов, через которые сервисы декларируют свои потребности.

Latency overhead. Каждый sidecar добавляет 1–5 мс на коннект. Для большинства сервисов несущественно, для high-throughput внутреннего API может быть критично. Замеряйте до и после, не верьте маркетинговым материалам.

Сетевая отладка. Когда между двумя сервисами стоят два sidecar, gateway и сетевой балансер, найти, где именно теряется запрос — занятие на час. Логи и трассировка должны покрывать каждый хоп.

Вендор-локин. Istio-конфигурация не переезжает на Linkerd за день. Перед выбором mesh оцените, насколько вы готовы к тому, что выбор будет «навсегда». То же про gateway: API Gateway от AWS — это не Kong с другой кнопкой.

«Mesh решит все проблемы». Не решит. Если у вас в коде сервиса retry на каждый внешний вызов, mesh его не уберёт. Если вы шифруете JSON-телом — mesh не расшифрует. Mesh — это инфраструктурный слой, он не заменит правильно написанный сервис.

Альтернативы и эволюция

Не всем нужен sidecar-mesh. Появляются альтернативные модели:

  • Sidecar-less mesh. Cilium Service Mesh использует eBPF вместо sidecar. Меньше overhead, но сложнее в установке и привязка к ядру Linux.
  • Ambient mesh. Istio Ambient — без sidecar для базовых функций, опционально с sidecar для продвинутых. Снижает накладные расходы.
  • Library mesh. gRPC + xDS API даёт часть mesh-функций без отдельного процесса. Подходит для команд, готовых работать с этим в коде.

Если будете запускать mesh с нуля в 2026 — посмотрите Linkerd (самый простой) и Istio Ambient. Sidecar-only Istio уже не дефолтный выбор.

Что запомнить

Gateway — для внешнего периметра, mesh — для внутреннего. Они не взаимоисключают, но решают разные задачи. Если у вас 5 сервисов и публичный API — нужен только gateway. Если 50 сервисов с активной интеграцией — оба, с чёткой границей ответственности.

Главное — не дублировать функции. Каждая задача (rate limiting, mTLS, retry) живёт в одном слое, и каждый слой знает только свою зону. Когда оба знают про всё — это не отказоустойчивость, это путаница, которую через год команда не понимает.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.