Service Mesh Patterns
Istio — Traffic Management
# VirtualService: weighted canary routing
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- match:
- headers:
x-canary:
exact: "true"
route:
- destination:
host: myapp
subset: canary
- route:
- destination:
host: myapp
subset: stable
weight: 90
- destination:
host: myapp
subset: canary
weight: 10
# DestinationRule: subsets + circuit breaker
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: myapp
spec:
host: myapp
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 1000
http2MaxRequests: 1000
outlierDetection:
consecutiveGatewayErrors: 5
interval: 10s
baseEjectionTime: 30s
maxEjectionPercent: 50
subsets:
- name: stable
labels:
version: stable
- name: canary
labels:
version: canary
Retry and Timeout
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- timeout: 5s
retries:
attempts: 3
perTryTimeout: 2s
retryOn: gateway-error,connect-failure,retriable-4xx
route:
- destination:
host: myapp
mTLS (PeerAuthentication)
# Enforce mTLS for all services in namespace
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: prod
spec:
mtls:
mode: STRICT
# Allow unauthenticated health check port only
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: myapp
namespace: prod
spec:
selector:
matchLabels:
app: myapp
mtls:
mode: STRICT
portLevelMtls:
8080:
mode: PERMISSIVE # health checks from external
Authorization Policy
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: myapp
namespace: prod
spec:
selector:
matchLabels:
app: myapp
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/prod/sa/api-gateway
- cluster.local/ns/prod/sa/frontend
to:
- operation:
methods: [GET, POST]
paths: [/api/*]
Linkerd (simpler alternative)
# Annotate namespace to auto-inject proxy
kubectl annotate namespace prod \
linkerd.io/inject=enabled
# Traffic split (canary)
kubectl apply -f - <<EOF
apiVersion: split.smi-spec.io/v1alpha1
kind: TrafficSplit
metadata:
name: myapp
spec:
service: myapp
backends:
- service: myapp-stable
weight: 900m
- service: myapp-canary
weight: 100m
EOF
# Observe live traffic
linkerd viz stat deploy -n prod
linkerd viz top deploy/myapp -n prod
Observability from Mesh
# Istio: per-service metrics auto-generated
istio_requests_total{source_app, destination_app, response_code}
istio_request_duration_milliseconds_bucket{...}
# Kiali dashboard (Istio)
kubectl port-forward svc/kiali 20001:20001 -n istio-system
# Jaeger distributed tracing
kubectl port-forward svc/tracing 16686:80 -n istio-system
Key Rules
- Start with
PERMISSIVE mTLS mode, migrate to STRICT after verifying all services have sidecars
- Service mesh adds ~2-5ms latency per hop — profile before assuming it's the mesh
- Use Linkerd for simplicity; Istio for advanced traffic management (header-based routing, WASM filters)
- Inject proxies via namespace annotation, not per-pod (easier to manage at scale)
- Circuit breaker
outlierDetection prevents cascading failures — always configure for dependencies