Service Mesh: Istio vs Linkerd, mTLS i zarządzanie ruchem
W architekturze mikrousług na Kubernetesie każda usługa komunikuje się z dziesiątkami innych. Kto gwarantuje, że ta komunikacja jest szyfrowana? Kto zarządza automatyczną ponowną próbą, kiedy usługa jest chwilowo nieosiągalna? Kto dostarcza metryki opóźnień i szybkości błędu dla każdej pary źródło-miejsce docelowe? Bez siatki usług odpowiedz na te pytania pytania wymagają niestandardowego kodu w każdej usłudze.
Un siatka serwisowa rozwiązuje te problemy na poziomie infrastruktury, przejrzysty w zastosowaniu. Dwóch dominujących graczy w środowisku Kubernetes to Istio, najbardziej bogaty w funkcje i Linkerda, zaprojektowany z myślą o prostocie i minimalnych kosztach ogólnych. W tym artykule pokazano, jak zainstalować w obu przypadkach skonfiguruj automatyczny mTLS, zarządzaj ruchem dzięki wdrożeniu Canary i przerwanie obwodu i kiedy wybrać jedno lub drugie.
Czego się nauczysz
- Jak działa siatka usług: płaszczyzna danych (wózek boczny) i płaszczyzna sterowania
- Automatyczny mTLS: co to znaczy, jak to sprawdzić, jak obsługiwać wyjątki
- Istio: instalacja, VirtualService, DestinationRule, kanarek i niebieski/zielony
- Linkerd: lekka instalacja, SMI TrafficSplit, rozszerzenia
- Przerywanie obwodu za pomocą Istio OutlierDetection
- Ponów próbę i przekrocz limit czasu na poziomie infrastruktury
- Obserwowalność: metryki złotych sygnałów z siatki usług
- Istio vs Linkerd: kiedy wybrać który
Jak działa siatka usług
Siatka serwisowa opiera się na automatycznym wstrzykiwaniu m.in poboczny serwer proxy (Wysłannik dla Istio, Linkerd2-proxy dla Linkerd) w każdym Pod. Wózek boczny przechwytuje wszystko ruch do i z kontenera aplikacji, bez konieczności wprowadzania zmian do kodu.
Il płaszczyzna danych oraz zestaw wszystkich wózków proxy proxy, które obsługują ruch skuteczny. The płaszczyzna sterująca (Istiod dla Istio, płaszczyzna kontrolna linkerda dla Linkerda) dystrybuuje konfigurację do serwerów proxy, zarządza certyfikatami dla mTLS i zbiera dane telemetryczne.
Porównanie Istio i Linkerda
| Charakterystyczny | Istio | Linkerda |
|---|---|---|
| Serwer proxy bocznego | Wysłannik (C++, 50-100 MB) | linkerd2-proxy (Rdza, 10-20 MB) |
| Narzut pamięci dla Poda | 100-200 MB | 20-30MB |
| Narzut opóźnienia P99 | 2-5 ms | 0,5-1 ms |
| Automatyczny mTLS | Tak (menedżer certyfikatów lub wbudowany) | Tak (automatyczna rotacja 24h) |
| Zarządzanie ruchem | Pełna (usługa wirtualna, DR) | Podstawowy (HTTPRoute, TrafficSplit) |
| Polityka L7 | HTTP, gRPC, TCP | HTTP, gRPC |
| Wejście | Brama API + Brama Istio | Brama API |
| Krzywa uczenia się | Stromy | Umiarkowany |
| Dojrzałość produkcyjna | Wysoki (Google, Airbnb) | Wysoka (Shopify, Microsoft) |
Istio: Podstawowa instalacja i konfiguracja
Instalacja za pomocą istioctl
# Scarica e installa istioctl
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.22.0 sh -
export PATH=$PWD/istio-1.22.0/bin:$PATH
# Installa Istio con profilo di produzione
istioctl install --set profile=production -y
# Il profilo production abilita:
# - HA con multiple repliche del control plane
# - Affinity rules per distribuire su nodi diversi
# - Risorse CPU/memoria adeguate
# - Solo le feature necessarie (no addon come Kiali, Jaeger)
# Abilita l'iniezione automatica del sidecar nel namespace
kubectl label namespace production istio-injection=enabled
# Verifica lo stato del mesh
istioctl proxy-status
# Analizza la configurazione per possibili problemi
istioctl analyze --namespace production
mTLS z Istio: PeerAuthentication i DestinationRule
Istio wdraża automatyczny mTLS pomiędzy wszystkimi wstrzykiwanymi kapsułami bocznymi. Z PeerAuthentication można wykonać za pośrednictwem mTLS ŚCISŁY (wymagane) przestrzeń nazw lub cały poziom siatki:
# mtls-strict.yaml
# Abilita mTLS STRICT per tutto il namespace production
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default-mtls
namespace: production
spec:
mtls:
mode: STRICT # DISABLE, PERMISSIVE, STRICT
---
# Eccezione: un servizio legacy che non ha sidecar
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: legacy-service-exception
namespace: production
spec:
selector:
matchLabels:
app: legacy-service
mtls:
mode: PERMISSIVE # accetta anche connessioni plain-text
# Verifica mTLS
kubectl exec -n production frontend-pod -c istio-proxy -- \
pilot-agent request GET /config_dump | grep -A5 "tls_context"
# Visualizza lo stato mTLS con istioctl
istioctl x describe pod frontend-pod.production
Usługa wirtualna: routing i podział ruchu
Usługa wirtualna definiuje sposób kierowania ruchu do usługi, z regułami opartymi na nagłówkach HTTP, wagach, dopasowywaniu ścieżek:
# virtual-service-canary.yaml
# Canary deployment: 90% traffico a v1, 10% a v2
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: api-service-vs
namespace: production
spec:
hosts:
- api-service # nome del Kubernetes Service
http:
# Routing per header: dev e QA ricevono sempre v2
- match:
- headers:
x-user-group:
exact: "beta-testers"
route:
- destination:
host: api-service
subset: v2
# Traffico generale: 90/10 split
- route:
- destination:
host: api-service
subset: v1
weight: 90
- destination:
host: api-service
subset: v2
weight: 10
# Timeout e retry a livello di infrastruttura
timeout: 5s
retries:
attempts: 3
perTryTimeout: 2s
retryOn: "5xx,reset,connect-failure,retriable-4xx"
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: api-service-dr
namespace: production
spec:
host: api-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http2MaxRequests: 1000
maxRequestsPerConnection: 10
loadBalancer:
simple: LEAST_CONN # ROUND_ROBIN, RANDOM, LEAST_CONN
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
Wyłącznik automatyczny z funkcją wykrywania wartości odstających
Wyłącznik automatyczny tymczasowo usuwa „niezdrowe” hosty z równoważenia obciążenia pulę, gdy przekroczą zdefiniowane progi błędów:
# destination-rule-circuit-breaker.yaml
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: payment-service-circuit-breaker
namespace: production
spec:
host: payment-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 50
connectTimeout: 3s
http:
http1MaxPendingRequests: 100
http2MaxRequests: 500
maxRetries: 3
outlierDetection:
# Rimuovi un host se in 10 secondi riceve 5 errori 5xx
consecutiveGatewayErrors: 5
consecutive5xxErrors: 5
interval: 10s
# Tienilo fuori per 30 secondi
baseEjectionTime: 30s
# Massimo 50% degli host puo essere rimosso
maxEjectionPercent: 50
# Analizza solo richieste con 100ms o piu di latenza
minHealthPercent: 50
Brama Istio dla ruchu przychodzącego
# istio-gateway.yaml
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: production-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: wildcard-tls-cert # Secret con cert TLS
hosts:
- "*.federicocalo.dev"
- port:
number: 80
name: http
protocol: HTTP
tls:
httpsRedirect: true # redirect tutto HTTP a HTTPS
hosts:
- "*.federicocalo.dev"
---
# Collega il Gateway al VirtualService
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: api-gateway-vs
namespace: production
spec:
hosts:
- "api.federicocalo.dev"
gateways:
- istio-system/production-gateway
- mesh # anche per traffico interno al mesh
http:
- route:
- destination:
host: api-service
port:
number: 8080
Polityka autoryzacji: Kontrola dostępu
# authorization-policy.yaml
# Solo il frontend puo chiamare il backend
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: backend-access-policy
namespace: production
spec:
selector:
matchLabels:
app: backend
action: ALLOW
rules:
- from:
- source:
principals:
- "cluster.local/ns/production/sa/frontend-service-account"
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/v1/*"]
---
# Blocca tutto il resto (default deny)
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: production
spec:
action: DENY
# Nessun selector = si applica a tutti i Pod nel namespace
# Nessuna rule = blocca tutto
Linkerd: Instalacja i konfiguracja
Linkerd preferuje prostotę obsługi i wydajność. Jego serwer proxy napisany w języku Rust Ma narzut wynoszący ~1 ms opóźnienia P99 i ~20 MB pamięci na kapsułę, co czyni go idealnym rozwiązaniem dla klastrów z wieloma mikrousługami lub ograniczeniami zasobów.
Instalacja Linkerda
# Installa Linkerd CLI
curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install | sh
export PATH=$HOME/.linkerd2/bin:$PATH
# Prerequisiti: verifica che il cluster sia compatibile
linkerd check --pre
# Installa il control plane
linkerd install --crds | kubectl apply -f -
linkerd install | kubectl apply -f -
# Verifica installazione
linkerd check
# Abilita injection sul namespace
kubectl annotate namespace production linkerd.io/inject=enabled
# Installa l'estensione Viz per osservabilita
linkerd viz install | kubectl apply -f -
linkerd viz check
linkerd viz dashboard &
Canary z Linkerdem i HTTPRoute (API bramy)
# linkerd-canary-httproute.yaml
# Linkerd usa la Gateway API per il traffic splitting
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-service-canary
namespace: production
spec:
parentRefs:
- name: api-service
kind: Service
group: core
port: 80
rules:
- backendRefs:
- name: api-service-v1
port: 80
weight: 90
- name: api-service-v2
port: 80
weight: 10
# Monitora il canary con linkerd viz
linkerd viz stat httproute/api-service-canary -n production
linkerd viz routes deploy/api-service-v2 -n production
Obserwowalne za pomocą Linkerda
# Visualizza metriche golden signals per tutti i deployment
linkerd viz stat deploy -n production
# Output tipico:
# NAME MESHED SUCCESS RPS LATENCY_P50 LATENCY_P99 TCP_CONN
# api-service 4/4 99.8% 245 1ms 12ms 42
# backend-service 3/3 98.2% 180 3ms 45ms 28
# payment-service 2/2 100.0% 65 8ms 89ms 12
# Visualizza il traffico per un singolo Pod
linkerd viz tap pod/api-service-xyz -n production
# Genera un report di osservabilita
linkerd viz check --proxy -n production
Telemetria Istio: metryki, śledzenie i rejestrowanie
Istio automatycznie wydaje plik złote sygnały (opóźnienie, ruch, błędy, nasycenie) dla każdej pary źródło-miejsce docelowe. Metryki są prezentowane w formacie Prometheus i widoczny w Grafanie z oficjalnymi pulpitami nawigacyjnymi Istio.
# telemetry-config.yaml
# Configura il sampling per il distributed tracing
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: mesh-tracing
namespace: istio-system
spec:
tracing:
- providers:
- name: tempo # o jaeger, zipkin
randomSamplingPercentage: 1.0 # campiona 1% del traffico in produzione
---
# Metriche custom per un servizio specifico
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: payment-service-metrics
namespace: production
spec:
selector:
matchLabels:
app: payment-service
metrics:
- providers:
- name: prometheus
overrides:
- match:
metric: REQUEST_COUNT
tagOverrides:
destination_version:
value: "request.headers['x-version'] | 'unknown'"
# Importa le dashboard Grafana ufficiali Istio
# Dashboard ID: 7639 (Mesh Overview), 11829 (Service), 12378 (Workload)
Service Mesh vs Cilium eBPF: kiedy ich używać
Wraz z pojawieniem się Cilium, które oferuje zasady mTLS i L7 bez przyczepek (poprzez eBPF w jądrze), wybór jest skomplikowany. Oto praktyczny przewodnik:
| Scenariusz | Zalecany wybór | Powód |
|---|---|---|
| Mikrousługi z zaawansowanym zarządzaniem ruchem (kanaryjski, routing oparty na nagłówkach) | Istio | VirtualService/DestinationRule niezastąpione |
| Bezpieczeństwo mTLS przy minimalnych kosztach ogólnych | Linkerd lub Cilium | Rust proxy lub minimalny eBPF |
| Klaster z setkami mikrousług i ograniczonymi zasobami | Linkerd lub Cilium mTLS | Narzut wózka bocznego pomnożony przez każdą kapsułę |
| Wiele klastrów lub wiele chmur | Istio | Wbudowana federacja siatki |
| Zespół nowy w obsłudze siatki | Linkerda | Znacznie niższa krzywa uczenia się |
Najlepsze praktyki dotyczące siatki usług
Lista kontrolna dotycząca siatki usług w produkcji
- Rozpocznij w trybie DOZWOLONYM: włącz mTLS w trybie PERMISSIVE, zanim ustawisz go na STRICT, aby zidentyfikować usługi, które nie mają jeszcze przyczepki
- Ustaw limit czasu dla wszystkich usług wirtualnych: bez limitu czasu powolna zależność blokuje cały łańcuch połączeń
- Wyłącznik automatyczny dla każdej zależności zewnętrznej: bazy danych, zewnętrzne API, usługi płatnicze
- Użyj ponownej próby tylko w przypadku błędów idempotentnych: nie wykonuj automatycznej ponownej próby POST bez klucza idempotencji, w przeciwnym razie utworzysz zduplikowane zamówienia
- Monitoruj poboczny procesor/pamięć: w klastrach z wieloma kapsułami łączny narzut wózka bocznego może być znaczny
- Testowanie przełączania awaryjnego: ręcznie wyłącz moduł i sprawdź, czy wyłącznik automatyczny oraz ponowne próby działają zgodnie z oczekiwaniami
- Aktualizuj siatkę: Wersje Istio i Linkerd mają krótki cykl życia (6-12 miesięcy); planuj regularne aktualizacje
Typowe anty-wzorce
- Nieskończone próby ze wzmocnieniem: jeśli A przywołuje B po 3 próbach, a B przywołuje C po 3 próbach, pojedynczy błąd generuje 9 prób w kierunku C (burza ponowień)
- Zbyt duże limity czasu: 60-sekundowy limit czasu w krytycznym interfejsie API oznacza, że podczas przestoju wszystkie wątki aplikacji/goroutines są blokowane na 60 sekund
- Ignorowanie nad głową płaszczyzny sterującej: Istiod zużywa znaczną ilość procesora/pamięci dla każdego podłączonego serwera proxy; w klastrach obejmujących ponad 1000 podów potrzebny jest dedykowany węzeł
- Wtrysk selektywny bez płaszczyzny: jeśli tylko niektóre kapsuły mają przyczepy boczne, komunikacja z kapsułami mTLS STRICT nie powiedzie się
Wnioski i dalsze kroki
Siatka usług przestała być „miło mieć” i stała się wymogiem jakąkolwiek poważną architekturę mikrousług. Automatyczny mTLS, szczegółowa obserwowalność, Przerywanie obwodów i deklaratywne zarządzanie ruchem rozwiązują bez nich rzeczywiste problemy siatka usług wymagałaby niestandardowego kodu w każdej usłudze.
Wybór pomiędzy Istio i Linkerd zależy od Twoich potrzeb: Istio dla złożonych scenariuszy zaawansowane i wieloklastrowe zarządzanie ruchem, Linkerd zapewnia prostotę operacyjną i koszty ogólne minimalne. W obu przypadkach początkowa inwestycja w naukę i konfigurację i opłaciło się poprzez zmniejszenie kodu infrastrukturalnego w aplikacjach i zmniejszenie widoczności bezprecedensowy wpływ na ruch wewnątrzklastrowy.
Nadchodzące artykuły z serii Kubernetes at Scale
Poprzednie artykuły
Powiązane serie
- Sieć Kubernetes: Cilium z eBPF — alternatywa dla usługi mesh dla mTLS
- Obserwowalność i OpenTelemetry — śledzenie rozproszone zintegrowane z Istio
- Inżynieria Platformy — siatka usług jako platforma wewnętrzna







