Service Mesh и политика трафика
1) Зачем нужен Service Mesh
Service Mesh — инфраструктурный слой для east-west трафика (межсервисные связи), дающий единообразные возможности без переписывания кода:- Безопасность по умолчанию: mTLS, автоматическая выдача/ротация сертификатов, идентичности сервисов.
- Политика трафика: маршрутизация L7, канареечные/AB-тесты, деградация и устойчивость.
- Наблюдаемость: метрики, логи, трассировки, золотые сигналы на каждом вызове.
- Операции: единые политики для всех языков/фреймворков.
Отличие от API-шлюза: шлюз — north-south периметр; mesh — east-west внутри кластера/организации. Часто работают вместе.
2) Архитектура: плоскости и паттерны
Data Plane: sidecar-прокси (Envoy/Linkerd-proxy/haproxy), перехватывающий трафик пода/ВМ.
Control Plane: распределяет конфигурации (маршруты, политики, сертификаты), хранит состояние, публикует сервис-дискoвери.
Identity: обычно SPIFFE ID и автоматические X.509-сертификаты (SPIRE/встроенный CA).
Точки входа/выхода: ingress/egress-gateway для контроля граничных потоков.
Режимы внедрения: sidecar на каждый под; пер-узловые/ambient-моды в новых реализациях.
3) Политика безопасности и zero-trust
1. mTLS by default: шифрование и взаимная аутентификация сервис↔сервис.
2. AuthN/AuthZ:- AuthN: доверяем только идентичностям, выданным CA mesh’а (SPIFFE).
- AuthZ: декларативные правила «кто может к кому и как» (RBAC/ABAC).
- Разрешенные домены/подсети; принудительный выход через egress-gateway.
- Блокировка прямых исходов из подов.
3. Изоляция и egress-контроль:
4. Ротация секретов: короткоживущие сертификаты, автоматическая переконфигурация прокси.
yaml apiVersion: security. istio. io/v1beta1 kind: PeerAuthentication metadata: { name: default, namespace: istio-system }
spec:
mtls: { mode: STRICT }
Istio (пример: разрешить только inventory→billing на gRPC):
yaml apiVersion: security. istio. io/v1beta1 kind: AuthorizationPolicy metadata: { name: billing-allow, namespace: prod }
spec:
selector: { matchLabels: { app: billing } }
rules:
- from:
- source: { principals: ["spiffe://corp. local/ns/prod/sa/inventory"] }
to:
- operation: { ports: ["8080"], methods: ["POST"], paths: ["/proto. Billing/"] }
4) Политика трафика: устойчивость и маршрутизация
4.1 Таймауты и ретраи
Timeouts: обязательно задаются на вызов (connect/read/overall).
Retries: только для идемпотентных операций; backoff+джиттер; лимиты per-try timeout.
yaml apiVersion: networking. istio. io/v1beta1 kind: VirtualService metadata: { name: orders }
spec:
hosts: ["orders"]
http:
- route:
- destination: { host: orders, subset: v1, port: { number: 8080 } }
timeout: 5s retries:
attempts: 2 perTryTimeout: 2s retryOn: "5xx,connect-failure,reset"
4.2 Circuit Breaker и outlier detection
CB: ограничивает одновременные запросы/подключения, защищая апстримы.
Outlier: выкидывает «плохие» инстансы по ошибкам/латентности.
yaml apiVersion: networking. istio. io/v1beta1 kind: DestinationRule metadata: { name: orders }
spec:
host: orders trafficPolicy:
connectionPool:
http: { http1MaxPendingRequests: 1024, maxRequestsPerConnection: 100 }
outlierDetection:
consecutive5xxErrors: 5 interval: 5s baseEjectionTime: 30s maxEjectionPercent: 50
4.3 Канареечные и по-условиям
Weighted: разделение трафика по весам v1/v2.
Header-based: флаги/куки/tenant → перекидывать в новую версию.
Session affinity: хэш по ключу (аккуратно с масштабированием).
yaml http:
- match: [{ headers: { "x-experiment": { exact: "new" } } }]
route: [{ destination: { host: orders, subset: v2 } }]
- route:
- destination: { host: orders, subset: v1, weight: 90 }
- destination: { host: orders, subset: v2, weight: 10 }
4.4 Fault Injection и деградация
Инъекция задержек/ошибок для теста устойчивости и SLO.
yaml fault:
delay: { fixedDelay: 300ms, percentage: { value: 10 } }
abort: { httpStatus: 503, percentage: { value: 1 } }
5) Сетевые границы: ingress/egress и внешние сервисы
Ingress-gateway: единственная точка входа для внешних клиентов в mesh; интеграция с WAF/OIDC/ratelimits.
Egress-gateway: центральный выход со списком разрешенных хостов, TLS-инспекция, запись телеметрии.
ServiceEntry: объявляет внешние SNI/host как часть mesh (политики и mTLS-origination применимы).
yaml apiVersion: networking. istio. io/v1beta1 kind: ServiceEntry metadata: { name: payments-external }
spec:
hosts: ["api. payments. com"]
ports: [{ number: 443, name: https, protocol: TLS }]
resolution: DNS location: MESH_EXTERNAL
6) Multi-cluster, multi-network и гибрид
Общая PKI/траст-домен: единые SPIFFE-идентичности между кластерами.
Endpoint discovery: шары сервисов между регионами; локальный приоритет и failover.
Зональная изоляция: пер-региональные политики, лимиты и приоритеты.
ВМ в mesh: подключение legacy/Stateful систем к прокси и тем же политикам.
7) Наблюдаемость, SLO и эксплуатация
Метрики: `requests_total`, `request_duration_ms{p50,p95,p99}`, `5xx_rate`, `retry_attempts`, `cb_state`, `mTLS_authz_denied`.
Логи доступа: структурные, с `traceparent`, `user/tenant`, `response_flags`.
Трейсинг: авто-инъекция заголовков (W3C Trace Context), сэмплирование, спаны на hop-уровне.
SLO: цели по p99/ошибкам на маршруте (service→service).
Алерты: всплеск `5xx`, рост `reset`, `outlier_ejections`, деградация mTLS (handshake failures).
8) Производительность и стоимость
Sidecar добавляет накладные (CPU/RAM/latency). Оптимизируем:- Зернистость: включать политику там, где нужна; не включать тяжелые фильтры везде.
- Пулы: разделить пути (критичные/фоновые) на разные маршруты и лимиты.
- Профилирование: p99 на «холодных» маршрутах, объем телеметрии (rate-limit логов/трейсов).
- Рассмотреть ambient/sidecarless режимы, если поддерживаются и подходят под требования.
9) Безопасность и комплаенс
Минимально необходимый доступ: явно разрешать направления и методы.
Политики по неймспейсам/тенантам: сетевые/авторизационные границы.
Ротация ключей/CA: плановая и аварийная; короткие TTL сертификатов.
PII/секреты: маскирование в логах/трейсах; шифрование на проводе/в покое.
Аудит: кто, когда и какую политику изменил; двухэтапные апрувы.
10) Интеграция с K8s-уровнем
Mesh-политики дополняют, а не заменяют NetworkPolicy.
В ingress/egress-gateway можно вешать PodSecurity/PSA уровнем ниже.
HPA/автоскейлинг: учитывайте ретраи/CB — они меняют нагрузку.
Планы релизов: канареечные веса через VirtualService + автоматическое продвижение по SLO.
11) Чек-лист внедрения
- Определены границы доверия и включен STRICT mTLS.
- Включены AuthZ-политики: кто к кому, на каких портах/методах.
- Настроены timeouts/retries и outlier detection, определены идемпотентные пути.
- Прописаны канареечные маршруты и rollback-план; fault-injection — только в не-прод.
- Вынесены внешние зависимости через egress-gateway и ServiceEntry.
- Настроены метрики, логи, трассы; дашборды и алерты на p99/5xx/CB.
- Предусмотрены квоты/лимиты per-tenant/namespace.
- Подготовлены runbooks: утечка сертификата, отказ CA, деградация апстрима, массовые 503/RESET.
- План multi-cluster (общая PKI, локальные приоритеты, DR-сценарии).
- Тест-дни (game days): падение control plane, стоп sidecar, разрыв сети, «ядовитый» апстрим.
12) Анти-паттерны
Mesh «везде и сразу» без инвентаризации маршрутов и SLO → дорогая сложность.
Ретраи по умолчанию для всех методов → дубли эффектов и лавина трафика.
Отключенный mTLS «временно» → остается навсегда.
Egress без шлюза → утечка данных/неучтенные зависимости.
Одна глобальная политика для всех сервисов → фальш-безопасность и ложные срабатывания.
Нулевой observability: включили mesh, но не собираем метрики/трейсы — теряем смысл.
13) Быстрые рецепты
Linkerd: включить mTLS и policy по серверу
yaml apiVersion: policy. linkerd. io/v1beta1 kind: Server metadata: { name: billing, namespace: prod }
spec:
podSelector: { matchLabels: { app: billing } }
port: 8080 apiVersion: policy. linkerd. io/v1beta1 kind: ServerAuthorization metadata: { name: billing-allow-inventory, namespace: prod }
spec:
server: { name: billing }
client:
meshTLS:
identities: ["inventory. prod. serviceaccount. identity. linkerd. cluster. local"]
Consul (L7 intent + splitter)
hcl
Kind = "service-router"
Name = "orders"
Routes = [{
Match { HTTP { PathPrefix = "/v1" } }
Destination { Service = "orders" }
}]
Kind = "service-splitter"
Name = "orders"
Splits = [
{ Weight = 90, ServiceSubset = "v1" },
{ Weight = 10, ServiceSubset = "v2" }
]
14) FAQ
Нужен ли mesh маленькой команде?
Если 3–5 сервисов — чаще нет. Начните с хорошего ingress и библиотек устойчивости. Подключайте mesh, когда появляется потребность в mTLS-по-умолчанию, единых политиках и трассировке без изменения кода.
Как контролировать стоимость?
Замерьте накладные (CPU/RAM/latency) на критичных путях, отключайте лишние фильтры, снижайте объем логов/трейсов, используйте режимы без sidecar там, где это безопасно.
Можно ли мешать mesh и вручную настроенные прокси?
Да, но избегайте двойной маршрутизации/дублирующих ретраев. Единое место истинны — control plane.
Что важнее: безопасность или производительность?
По умолчанию — безопасность (mTLS, AuthZ). Производительность достигается тюнингом connection pools, outlier detection, целевыми маршрутами.
15) Итоги
Service Mesh превращает сеть между сервисами в программируемый слой с едиными политиками: шифрование и идентичности, тонкая маршрутизация и устойчивость, телеметрия и квоты. Начинайте с критичных путей, включайте STRICT mTLS и явные AuthZ, задавайте таймауты/ретраи/CB, контролируйте egress, измеряйте p99 и 5xx, проводите game days. Тогда mesh станет усилителем надежности и скорости релизов, а не источником неожиданностей.