Service mesh internals deep dive across 3 layers (istio sidecar, ambient mesh, cilium-ebpf) with 4 scenarios: Istio mTLS auto, canary 95/5 traffic shift, AuthorizationPolicy deny, sidecarless (ambient ztunnel+waypoint and Cilium eBPF kernel path).
Базовый paтtern service-mesh объясняет, зачем sidecar нужен. Этот гайд — про что внутри: как Istiod пушит конфиг в Envoy через xDS, как iptables ловит трафик в pod, чем Cilium eBPF радикально отличается от sidecar-подхода, и как мигрировать с raw k8s на mesh без big-bang. Цель — понимать, что показывает istioctl proxy-config listener, откуда взялся 503 в логах sidecar и стоит ли терпеть +50MB RAM × N pod ради «бесплатного» mTLS.
Service mesh = data plane (Envoy/eBPF на каждом hop) + control plane (Istiod/cilium-operator), синхронизированные через xDS (gRPC push) или eBPF maps (kernel state). Истинная цена — operational complexity. Истинная награда — observability + mTLS + traffic policy без касания app-кода.
Три архитектурных воплощения mental model на диаграмме:
istio — классический sidecar: один Envoy в каждом pod, RAM/latency tax × N.ambient — split data plane: ztunnel (L4 mTLS, per-node) + waypoint (L7, opt-in). Sidecar убран.cilium-ebpf — sidecar-less, mTLS/policy в kernel через eBPF maps. Самый быстрый, но L7-беднее.Три слоя, переключаемых layer-pills:
istio — Istiod (Pilot+Citadel+Galley в одном бинаре с 1.5) пушит xDS gRPC во все sidecar'ы. Каждый pod = app + envoy sidecar, связанные через localhost после iptables-redirect. Между sidecar'ами — mTLS с SPIFFE-identity (spiffe://cluster/ns/X/sa/Y). Видны canary v1/v2 с 95/5 weight, unauthorized external-client без сертификата и observability stack (Prometheus + Jaeger + Kiali).
ambient — тот же Istiod, но в pod'ах нет sidecar. ztunnel (по одному на ноду) делает L4 mTLS через HBONE (HTTP-Based Overlay Network Encapsulation). L7-политики (header routing, JWT-validate) — через отдельный waypoint proxy, который подключается только там, где нужен.
cilium-ebpf — cilium-operator конфигурирует cilium-agent (DaemonSet). eBPF programs в kernel перехватывают connect/sendmsg/recvmsg syscalls на уровне socket, mTLS и policy лежат в eBPF maps. User-space proxy в горячем пути отсутствует.
Классический happy path. App шлёт plain HTTP на localhost:8080, iptables редиректит на Envoy:15001, Envoy уже имеет cached route+cluster+cert от Istiod (push-on-change), делает mTLS-handshake с peer-sidecar по SPIFFE-identity. Backend-app видит чистый localhost и про mesh ничего не знает. Это и есть «бесплатный» mTLS — цена скрыта в RAM/latency sidecar'a.
VirtualService с weight: 95 / 5 — Istiod hot-reload'ит RDS в frontend-envoy без рестарта пода. 19 запросов из 20 хэшируются в v1, один — в v2. Прометей собирает метрики v2 независимо (sidecar добавляет destination_version label автоматически); если error_rate < 0.1% — поднимаем до 50/50, затем 100. Никакого app deploy'а, только CRD-патч.
Zero-trust в действии. external-client без sidecar (значит без SPIFFE-cert) дёргает backend-v1. Sidecar backend'а проверяет AuthorizationPolicy, не находит principal в whitelist, возвращает 403. Тот же endpoint от frontend-app (с sidecar и валидной identity) — пропускается. App-код одинаков; разница только в iptables-захвате и mTLS-handshake'е.
Сравнение ambient vs eBPF на одном fly-through. Ambient: frontend → ztunnel-1 → waypoint (L7) → ztunnel-2 → backend через HBONE. RAM-экономия очевидна — нет per-pod Envoy. Cilium: frontend → cilium-agent-1 → cilium-agent-2 → backend через socket-hook в kernel, ~0.5ms против ~3ms у Envoy hop. Но Cilium L7 ограничен, для сложного routing он сам деплоит per-node Envoy.
Context. Команда: ~25 микросервисов на 3 языках (Go/Node/Python) в одном k8s-кластере, требование compliance (PCI/SOC2) на mTLS + audit, нет dedicated platform engineer пока, но в найме.
Альтернатива A — Istio sidecar. Зрелое, rich features, comprehensive observability. Цена: +50-100MB RAM × N pod (для 5000 pod = +500GB RAM), +1-3ms per hop, ops complexity (CRD upgrades, istioctl debug skills).
Альтернатива B — Istio ambient. Те же CRDs, тот же контрол плейн, но без per-pod sidecar. L4 mTLS «бесплатно» через ztunnel (один на ноду), L7 — только через waypoint в нужных namespace. RAM-overhead падает на порядок. Цена: моложе (GA в 1.22), debug сложнее (нет sidecar-логов в каждом pod), L7 features ограничены тем, что поддерживает waypoint.
Альтернатива C — Cilium eBPF mesh. Sidecar-less by design, ядро делает всю работу. ~2× ниже latency, ~50-70% меньше memory. Цена: kernel ≥ 5.10, L7 ограничен (для rich HTTP-routing Cilium сам ставит Envoy на ноде), debugging через bpftool и trace points, community меньше.
Альтернатива D — in-process library (gRPC interceptors для retry/CB, OTel SDK для traces, JWT для service-to-service). Zero infra overhead, debug в profiler как обычный код. Цена: дублирование на 3 языках (Python ecosystem отстаёт), retry/CB semantics дрейфуют между сервисами, mTLS-rotation = передеплой всех клиентов, central kill-switch отсутствует.
Decision matrix:
| Сигнал | Lean A (sidecar) | Lean B (ambient) | Lean C (cilium) | Lean D (library) |
|---|---|---|---|---|
| < 10 сервисов, 1 язык | YES | |||
| Compliance: PCI / HIPAA / GDPR | YES | YES | YES | |
| 3+ языка, разные ecosystem'ы | YES | YES | YES | |
| Hot-path latency budget < 1ms (HFT, ad bidding) | YES | YES | ||
| Нет dedicated platform engineer | YES | |||
| Pod budget > 1000 (RAM cost критичен) | YES | YES | ||
| Canary/traffic shift без redeploy | YES | YES | YES | |
| L7 routing + JWT + header-based policies | YES | YES | ||
| Multi-cluster federation на горизонте | YES | YES | ||
| Kernel ≥ 5.10 везде | - | - | YES | - |
Decision. Для описанного кейса — Istio ambient. Compliance закрывается ztunnel-L4-mTLS, RAM-overhead снят (главный аргумент против sidecar), L7-policies подключаются только в namespace, где реально нужны header-based routing. Если бы было ≤ 10 сервисов на одном языке без compliance — выбор был бы D (library-only).
Triggers пересмотра:
proxy.resources.limits.Источники: