Service Mesh обычно всплывает в разговорах, когда микросервисов уже много, всё крутится в Kubernetes, и сетевой хаос начинает доставать. По сути, это дополнительный сетевой слой внутри кластера, который берет на себя все сложные штуки вокруг общения сервисов: кто с кем говорит, по какому протоколу, как шифруется, что логируется и что делать при сбоях. Делается это через отдельный прокси-слой, а не через правки кода во всех приложениях.
Идея простая: вместо того чтобы в каждый сервис встраивать поддержку ретраев, таймаутов, mTLS, логирования и прочих «сетевых особенностей», мы вешаем это на платформу. Разработчики занимаются бизнес-логикой, а mesh уже сам занимается маршрутизацией, авторизацией, шифрованием и телеметрией.
Как примерно устроен Service Mesh #
На практике всё крутится вокруг sidecar-прокси. В каждый pod прилетает дополнительный контейнер (часто это Envoy), который перехватывает весь входящий и исходящий трафик. Приложение считает, что общается по сети напрямую, но на самом деле говорит с локальным прокси, а тот уже решает, куда реально отправить запрос и с какими правилами.
Над этим всем сидит control plane, который заливает в прокси конфигурацию: маршруты, политики безопасности, параметры телеметрии и так далее. В итоге архитектура обычно делится на два слоя:
- Data Plane — это как раз армия sidecar-прокси, через которые идет весь реальный трафик;
- Control Plane — отдельные компоненты, которые хранят и раздают конфиг, следят за сертификатами, политиками и всеми апдейтами.
Что mesh умеет делать #
- Маршрутизация и поиск сервисов — можно рулить трафиком по версиям, заголовкам, тегам, делать умные маршруты;
- Шифрование (mTLS) — шифрование трафика «из коробки», сертификаты и взаимная аутентификация между сервисами;
- Управление доступом — политики, RBAC, ограничения по SNI, CIDR и прочим признакам;
- Тонкая настройка сетевого поведения — таймауты, ретраи, circuit breaker, rate limiting, всё на уровне прокси;
- Наблюдаемость — метрики, трассировка, логи; обычный стек — Prometheus, Grafana, Jaeger, Zipkin и им подобные;
- Canary и A/B — трафик-сплит по версиям без перекраивания приложения;
- Zero Trust-модель — каждый сервис явно аутентифицируется и авторизуется, внутренней сети «просто так» не верим.
Что за решения бывают #
Самые часто встречающиеся варианты:
- Istio — тяжеловесный, но очень гибкий; строится вокруг Envoy и собственного control plane;
- Linkerd — полегче и попроще, со своим прокси на Rust;
- Consul Connect — меш, который вырос из service discovery в Consul;
- Kuma — тоже вокруг Envoy, делает упор на multi-mesh и управление через CRD;
- Open Service Mesh (OSM) — лёгкий вариант с Envoy и поддержкой SMI.
Где mesh реально выручает #
- Kubernetes-кластеры с кучей микросервисов, где уже не получается «договориться на словах» о сетевых правилах;
- Мультикластер и мультиоблако — когда сервисы раскиданы по разным кластерам и провайдерам;
- Финтех, медицина и прочие домены, где к шифрованию и аудиту трафика есть формальные требования;
- DevSecOps и Zero Trust-архитектуры, где внутренняя сеть не считается безопасной по определению;
- Сложные CI/CD-пайплайны, где нужно тестировать версии и управлять rollout’ами на уровне сети.
Зачем всё это вообще городить #
- Снять с разработчиков сетевую «обвязку»: таймауты, mTLS, ретраи, авторизацию между сервисами и т.п.;
- Хранить и применять политики безопасности централизованно, а не по файлам конфигов в каждом сервисе;
- Повысить устойчивость микросервисов к сетевым проблемам и странным сценариям в проде;
- Втащить нормальный observability-стек без того, чтобы лезть в код каждого сервиса и расставлять там клиенты метрик/трейсов.
Если по сути, Service Mesh — это слой, который становится почти обязательным, когда микросервисная история и Kubernetes уже переросли уровень «поиграться». Это вопрос не моды, а контроля: шифрование, стабильность, понятный трафик и управляемые rollout’ы.
Istio: как это выглядит на схеме #
┌────────────────────────────┐
│ Istio Control Plane │
│ ┌────────┐ ┌───────────┐ │
│ │ Pilot │ │ Citadel │ │
│ └────────┘ └───────────┘ │
└────────┬────────┬──────────┘
│ │
┌──────────────┐ mTLS ▼ ▼ mTLS ┌──────────────┐
│ Service A │◄────────► Envoy ◄─► Envoy ◄──────►│ Service B │
└──────────────┘ Sidecar Sidecar └──────────────┘
- Envoy — тот самый sidecar, который кладут почти в каждый pod;
- Pilot — часть control plane, которая отвечает за маршрутизацию и раздачу конфигов;
- Citadel — старый компонент для управления сертификатами и mTLS (в новых версиях эта роль переехала в Istiod);
- Galley / Telemetry / Mixer — исторические компоненты для политики и телеметрии, которые в актуальных релизах уже упрощены и переработаны.
Пример: включаем mTLS между сервисами #
1. Жёсткий mTLS на namespace #
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: production
spec:
mtls:
mode: STRICT
2. Правило: кто имеет право говорить с backend #
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
selector:
matchLabels:
app: backend
rules:
- from:
- source:
principals: ["cluster.local/ns/production/sa/frontend"]
Эта политика говорит: к подам с меткой app=backend можно ходить только от сервис-аккаунта frontend в namespace production.
Canary rollout на Istio через VirtualService #
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: web-app
spec:
hosts:
- web.example.com
http:
- route:
- destination:
host: web-app
subset: v1
weight: 90
- destination:
host: web-app
subset: v2
weight: 10
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: web-app
spec:
host: web-app
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
Дальше уже дело за Deployment’ами: поды web-app должны быть размечены метками version: v1 и version: v2, чтобы mesh понимал, куда какой трафик слать.
Istio vs Linkerd — в чем разница по ощущениям #
- Прокси: Istio опирается на Envoy (C++), Linkerd использует собственный лёгкий прокси на Rust;
- Установка: у Istio больше CRD и настроек, порог входа выше; Linkerd ставится быстрее и проще;
- mTLS: в обоих есть, в Linkerd он всегда включен по умолчанию, в современных Istio тоже можно настроить как default;
- Traffic splitting: и там, и там есть, только в Istio через VirtualService, а в Linkerd — через SMI или ServiceProfile;
- Наблюдаемость: Istio обычно дружит с Prometheus, Jaeger, Kiali; Linkerd — с Prometheus, Grafana и своим Tap;
- Производительность: Istio даёт больше overhead, Linkerd заметно легче;
- Расширяемость: Istio очень гибкий, есть плагины, WASM, WAF; Linkerd — проще и более ограничен по фичам;
- Продакшен: оба реально используются, Istio часто в тяжёлых платформах, Linkerd — там, где важна простота и низкий overhead.
Дальше вокруг этого можно наращивать конкретику: архитектуру Istio, примеры mTLS, манифесты для трафик-сплита — всё это уже чисто практические вещи для конкретных Kubernetes-кластеров.
