Перейти к содержанию

Service Mesh

Service Mesh - инфраструктурный слой, который берёт на себя общение сервис-сервис: маршрутизацию, retry, mTLS, метрики. Делает он это через прокси рядом с каждым сервисом, в коде сервиса этой логики нет.

Зачем: раньше retry, timeout, circuit breaker и discovery жили в библиотеках внутри сервиса (Netflix OSS: Hystrix, Ribbon, Eureka-клиент). Библиотека своя под каждый язык, и обновлять её надо в каждом сервисе. Mesh выносит эту логику из процесса в прокси, одинаковый для всех языков.


Как устроено

  • Data plane - прокси рядом с каждым сервисом, через него идёт весь входящий и исходящий трафик. Классически это sidecar-контейнер с Envoy в каждом поде. У Linkerd свой прокси на Rust
  • Control plane - раздаёт прокси политики, маршруты и сертификаты. В Istio это istiod, конфиг он отдаёт прокси по xDS API

Сервис думает, что зовёт http://orders, а на деле упирается в локальный прокси. Прокси и делает mTLS, retry, timeout и маршрутизацию.

          под orders                           под payments
   +----------------------+             +----------------------+
   |  app --> proxy       | -- mTLS --> |  proxy --> app       |
   |          (Envoy)     |             |  (Envoy)             |
   +----------------------+             +----------------------+
              ^                                    ^
              +---------- control plane -----------+
                 (политики, сертификаты, маршруты)

Mesh опирается на service discovery: control plane берёт список живых инстансов из registry (в Kubernetes - из EndpointSlice) и раздаёт его прокси. Discovery отвечает, где живёт сервис, mesh - как до него дойти.

Sidecar - общий паттерн вспомогательного контейнера рядом с основным (Burns и Oppenheimer, 2016). Прокси меша - лишь один его случай.

Без sidecar. Прокси на каждом поде стоит памяти и CPU, поэтому появились режимы без sidecar. В Istio ambient mode ztunnel на каждой ноде держит L4 и mTLS, а L7-политики обрабатывает отдельный waypoint-прокси. Cilium делает mesh на eBPF в ядре и одном Envoy на ноду для L7.

Команды:

kubectl get pods            # READY 2/2 - в поде app и sidecar-прокси
istioctl proxy-status       # получили ли прокси конфиг от control plane
linkerd viz stat deploy     # RPS, доля успешных запросов и латентность по сервисам, снятые прокси

Что даёт

  • mTLS между сервисами. Взаимная аутентификация по сертификатам, ротация без участия сервиса. Это identity, а не authz: mTLS доказывает, кто звонит, но не что ему можно (см. Безопасность).
  • Retry, timeout, circuit breaking. Политикой в конфиге, а не библиотекой в каждом сервисе (см. Устойчивость).
  • Канареечные и weighted-маршруты. «5% трафика на v2» правится в конфиге меша (см. Деплой-стратегии).
  • Observability. Прокси видит весь трафик и отдаёт метрики и спаны по каждому хопу (см. Наблюдаемость).

Mesh ведёт трафик между сервисами (east-west). Вход снаружи (north-south) держит API Gateway, у Istio для этого есть свой ingress gateway.


Цена и когда окупается

  • Сложность. Control plane, инъекция sidecar, CRD политик - ещё одна большая система в эксплуатации.
  • Латентность. Каждый вызов проходит через два прокси. Обычно это единицы миллисекунд, но они есть.
  • Ресурсы. Sidecar на каждый под, память и CPU умножаются на число подов.

Mesh окупается на десятках сервисов, когда нужен mTLS везде и единые политики retry и timeout без правки кода. На трёх сервисах накладные расходы не окупятся: те же retry и timeout дешевле прописать библиотекой.


Технологии

Технология Как устроен Когда брать
Istio Envoy-sidecar или ambient mode, control plane istiod Нужны сложные политики трафика
Linkerd Свой лёгкий прокси на Rust Нужны в основном mTLS и метрики, важна простота
Consul service mesh Envoy-sidecar, registry и mesh в одном продукте Сервисы и в Kubernetes, и на виртуальных машинах
Cilium Service Mesh eBPF в ядре, без sidecar Cilium уже стоит сетевым плагином Kubernetes
Kuma Envoy-sidecar, проект CNCF от Kong Kubernetes и виртуальные машины, несколько кластеров