
Implementing Service Mesh
- 42 installs
- 426 repo stars
- Updated December 11, 2025
- ancoleman/ai-design-components
implementing-service-mesh is a Claude Code skill that deploys production service meshes with Istio, Linkerd, or Cilium, configuring mTLS, authorization, traffic routing, and progressive delivery.
About
This skill deploys and configures service mesh infrastructure for Kubernetes using Istio, Linkerd, or Cilium. It enables mutual TLS between services, authorization policies, traffic routing, and progressive delivery patterns like canary deployments. Developers use it when setting up service-to-service communication, implementing zero-trust security, or enabling traffic splitting between versions.
- Production service mesh deployment with Istio, Linkerd, or Cilium
- Configures mTLS, authorization policies, and traffic routing for microservices
- Covers progressive delivery, canary deployments, and zero-trust security
Implementing Service Mesh by the numbers
- 42 all-time installs (skills.sh)
- Ranked #748 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
implementing-service-mesh capabilities & compatibility
- Capabilities
- mtls setup · traffic routing · authorization policy · canary deployment
- Works with
- kubernetes
- Use cases
- devops · security audit
- Pricing
- Free
What implementing-service-mesh says it does
Implement production-ready service mesh deployments with Istio, Linkerd, or Cilium.
8% latency overhead with mTLS (vs 166% sidecar mode)
npx skills add https://github.com/ancoleman/ai-design-components --skill implementing-service-meshAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 42 |
|---|---|
| repo stars | ★ 426 |
| Last updated | December 11, 2025 |
| Repository | ancoleman/ai-design-components ↗ |
What it does
Deploying Istio, Linkerd, or Cilium service meshes with mTLS, traffic routing, and authorization for microservices.
Who is it for?
Kubernetes microservices needing mTLS, zero-trust authorization, and canary traffic control.
Skip if: Monoliths or small architectures with fewer than a handful of services.
When should I use this skill?
You are setting up service-to-service communication, zero-trust security, or canary deployments on Kubernetes.
What you get
A configured service mesh providing automatic mTLS, identity-based authorization, and progressive delivery.
- Istio/Linkerd/Cilium configuration
- mTLS PeerAuthentication policies
- Traffic routing VirtualServices
By the numbers
- Istio Ambient 8% latency overhead with mTLS
- Linkerd 33% latency overhead (lowest sidecar)
Files
Service Mesh Implementation
Purpose
Configure and deploy service mesh infrastructure for Kubernetes environments. Enable secure service-to-service communication with mutual TLS, implement traffic management policies, configure authorization controls, and set up progressive delivery strategies. Abstracts network complexity while providing observability, security, and resilience for microservices.
When to Use
Invoke this skill when:
- "Set up service mesh with mTLS"
- "Configure Istio traffic routing"
- "Implement canary deployments"
- "Secure microservices communication"
- "Add authorization policies to services"
- "Traffic splitting between versions"
- "Multi-cluster service mesh setup"
- "Configure ambient mode vs sidecar"
- "Set up circuit breaker configuration"
- "Enable distributed tracing"
Service Mesh Selection
Choose based on requirements and constraints.
Istio Ambient (Recommended for most):
- 8% latency overhead with mTLS (vs 166% sidecar mode)
- Enterprise features, multi-cloud, advanced L7 routing
- Sidecar-less L4 (ztunnel) + optional L7 (waypoint)
Linkerd (Simplicity priority):
- 33% latency overhead (lowest sidecar)
- Rust-based micro-proxy, automatic mTLS
- Best for small-medium teams, easy adoption
Cilium (eBPF-native):
- 99% latency overhead, kernel-level enforcement
- Advanced networking, sidecar-less by design
- Best for eBPF infrastructure, future-proof
For detailed comparison matrix and architecture trade-offs, see references/decision-tree.md.
Core Concepts
Data Plane Architectures
Sidecar: Proxy per pod, fine-grained L7 control, higher overhead Sidecar-less: Shared node proxies (Istio Ambient) or eBPF (Cilium), lower overhead
Istio Ambient Components:
- ztunnel: Per-node L4 proxy for mTLS
- waypoint: Optional per-namespace L7 proxy for HTTP routing
Traffic Management
Routing: Path, header, weight-based traffic distribution Resilience: Retries, timeouts, circuit breakers, fault injection Load Balancing: Round robin, least connections, consistent hash
Security Model
mTLS: Automatic encryption, certificate rotation, zero app changes Modes: STRICT (reject plaintext), PERMISSIVE (accept both) Authorization: Default-deny, identity-based (not IP), L7 policies
Istio Configuration
Istio uses Custom Resource Definitions for traffic management and security.
VirtualService (Routing)
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend-canary
spec:
hosts:
- backend
http:
- route:
- destination:
host: backend
subset: v1
weight: 90
- destination:
host: backend
subset: v2
weight: 10DestinationRule (Traffic Policy)
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: backend-circuit-breaker
spec:
host: backend
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 10
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30sPeerAuthentication (mTLS)
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICTAuthorizationPolicy (Access Control)
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: allow-frontend
namespace: production
spec:
selector:
matchLabels:
app: backend
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/production/sa/frontend
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/*"]For advanced patterns (fault injection, mirroring, gateways), see references/istio-patterns.md.
Linkerd Configuration
Linkerd emphasizes simplicity with automatic mTLS.
HTTPRoute (Traffic Splitting)
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: backend-canary
spec:
parentRefs:
- name: backend
kind: Service
rules:
- backendRefs:
- name: backend-v1
port: 8080
weight: 90
- name: backend-v2
port: 8080
weight: 10ServiceProfile (Retries/Timeouts)
apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
name: backend.production.svc.cluster.local
spec:
routes:
- name: GET /api/data
condition:
method: GET
pathRegex: /api/data
timeout: 3s
retryBudget:
retryRatio: 0.2
minRetriesPerSecond: 10AuthorizationPolicy
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: allow-frontend
spec:
targetRef:
kind: Server
name: backend-api
requiredAuthenticationRefs:
- name: frontend-identity
kind: MeshTLSAuthenticationFor complete patterns and mTLS verification, see references/linkerd-patterns.md.
Cilium Configuration
Cilium uses eBPF for kernel-level enforcement.
CiliumNetworkPolicy (L3/L4/L7)
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: backend-access
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
rules:
http:
- method: GET
path: "/api/.*"DNS-Based Egress
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: external-api-access
spec:
endpointSelector:
matchLabels:
app: backend
egress:
- toFQDNs:
- matchName: "api.github.com"
toPorts:
- ports:
- port: "443"For mTLS with SPIRE and eBPF patterns, see references/cilium-patterns.md.
Security Implementation
Zero-Trust Architecture
1. Enable strict mTLS (encrypt all traffic) 2. Default-deny authorization policies 3. Explicit allow rules (least privilege) 4. Identity-based access control 5. Audit logging
Example (Istio):
# Strict mTLS
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: strict-mtls
namespace: production
spec:
mtls:
mode: STRICT
---
# Deny all by default
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: production
spec: {}Certificate Management
- Automatic rotation (24h TTL default)
- Zero-downtime updates
- External CA integration (cert-manager)
- SPIFFE/SPIRE for workload identity
For JWT authentication and external authorization (OPA), see references/security-patterns.md.
Progressive Delivery
Canary Deployment
Gradually shift traffic with monitoring.
Stages: 1. Deploy v2 with 0% traffic 2. Route 10% to v2, monitor metrics 3. Increase: 25% → 50% → 75% → 100% 4. Cleanup v1 deployment
Monitor: Error rate, latency (P95/P99), throughput
Blue/Green Deployment
Instant cutover with quick rollback.
Process: 1. Deploy green alongside blue 2. Test green with header routing 3. Instant cutover to green 4. Rollback to blue if needed
Automated Rollback (Flagger)
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: backend
spec:
targetRef:
kind: Deployment
name: backend
service:
port: 8080
analysis:
interval: 1m
threshold: 5
maxWeight: 50
stepWeight: 10
metrics:
- name: request-success-rate
thresholdRange:
min: 99For A/B testing and detailed patterns, see references/progressive-delivery.md.
Multi-Cluster Mesh
Extend mesh across Kubernetes clusters.
Use Cases: HA, geo-distribution, compliance, DR
Istio Multi-Primary:
# Install on cluster 1
istioctl install --set values.global.meshID=mesh1 \
--set values.global.multiCluster.clusterName=cluster1
# Exchange secrets for service discovery
istioctl x create-remote-secret --context=cluster2 | \
kubectl apply -f - --context=cluster1Linkerd Multi-Cluster:
# Link clusters
linkerd multicluster link --cluster-name cluster2 | \
kubectl apply -f -
# Export service
kubectl label svc/backend mirror.linkerd.io/exported=trueFor complete setup and cross-cluster patterns, see references/multi-cluster.md.
Installation
Istio Ambient Mode
curl -L https://istio.io/downloadIstio | sh -
istioctl install --set profile=ambient -y
kubectl label namespace production istio.io/dataplane-mode=ambientLinkerd
curl -sL https://run.linkerd.io/install-edge | sh
linkerd install --crds | kubectl apply -f -
linkerd install | kubectl apply -f -
kubectl annotate namespace production linkerd.io/inject=enabledCilium
helm install cilium cilium/cilium \
--namespace kube-system \
--set meshMode=enabled \
--set authentication.mutual.spire.enabled=trueTroubleshooting
mTLS Issues
# Istio: Check mTLS status
istioctl authn tls-check frontend.production.svc.cluster.local
# Linkerd: Check edges
linkerd edges deployment/frontend -n production
# Cilium: Check auth
cilium bpf auth listTraffic Routing Issues
# Istio: Analyze config
istioctl analyze -n production
# Linkerd: Tap traffic
linkerd tap deployment/backend -n production
# Cilium: Observe flows
hubble observe --namespace productionFor complete debugging guide and solutions, see references/troubleshooting.md.
Integration with Other Skills
kubernetes-operations: Cluster setup, namespaces, RBAC security-hardening: Container security, secret management infrastructure-as-code: Terraform/Helm for mesh deployment building-ci-pipelines: Automated canary, integration tests performance-engineering: Latency benchmarking, optimization
Reference Files
references/decision-tree.md- Service mesh selection and comparisonreferences/istio-patterns.md- Istio configuration examplesreferences/linkerd-patterns.md- Linkerd patterns and best practicesreferences/cilium-patterns.md- Cilium eBPF policies and mTLSreferences/security-patterns.md- Zero-trust and authorizationreferences/progressive-delivery.md- Canary, blue/green, A/B testingreferences/multi-cluster.md- Multi-cluster setup and federationreferences/troubleshooting.md- Common issues and debugging
# Cilium Network Policy Example
#
# Demonstrates: L3/L4/L7 network policies with eBPF enforcement
#
# Dependencies:
# Cilium installed with service mesh enabled
#
# Usage:
# kubectl apply -f network-policy.yaml
---
# Frontend deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: production
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: frontend:latest
ports:
- containerPort: 3000
---
# Backend deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: backend:latest
ports:
- containerPort: 8080
---
# Backend service
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: production
spec:
selector:
app: backend
ports:
- port: 8080
---
# L3/L4 Policy: Allow frontend to access backend on port 8080
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
description: "Allow frontend pods to access backend on port 8080"
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
---
# L7 HTTP Policy: Restrict HTTP methods and paths
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: backend-http-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: GET
path: "/api/users"
- method: GET
path: "/api/users/.*"
- method: POST
path: "/api/users"
---
# Egress policy: Allow backend to access external API
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: backend-egress
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
egress:
# Allow to external API
- toFQDNs:
- matchName: "api.github.com"
toPorts:
- ports:
- port: "443"
protocol: TCP
# Allow DNS queries
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchPattern: "*"
---
# Cluster-wide default deny policy
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: default-deny
spec:
description: "Default deny all traffic"
endpointSelector: {}
ingress:
- {}
egress:
# Allow DNS for all pods
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
# Istio Canary Deployment Example
#
# Demonstrates: Progressive traffic splitting from v1 to v2
#
# Usage:
# kubectl apply -f canary-deployment.yaml
# # Gradually update VirtualService weights: 90/10 → 75/25 → 50/50 → 100/0
---
# Backend v1 deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-v1
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: backend
version: v1
template:
metadata:
labels:
app: backend
version: v1
spec:
containers:
- name: backend
image: backend:v1
ports:
- containerPort: 8080
env:
- name: VERSION
value: "v1"
---
# Backend v2 deployment (canary)
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-v2
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: backend
version: v2
template:
metadata:
labels:
app: backend
version: v2
spec:
containers:
- name: backend
image: backend:v2
ports:
- containerPort: 8080
env:
- name: VERSION
value: "v2"
---
# Service (points to all backend pods)
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: production
spec:
selector:
app: backend
ports:
- port: 8080
targetPort: 8080
---
# DestinationRule: Define subsets for v1 and v2
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: backend
namespace: production
spec:
host: backend
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 10
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30s
---
# VirtualService: 90% v1, 10% v2 (initial canary)
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend-canary
namespace: production
spec:
hosts:
- backend
http:
# Internal testers always see v2
- match:
- headers:
x-canary-user:
exact: "true"
route:
- destination:
host: backend
subset: v2
# Production traffic: 90/10 split
- route:
- destination:
host: backend
subset: v1
weight: 90
- destination:
host: backend
subset: v2
weight: 10
# Istio mTLS and Authorization Example
#
# Demonstrates: Zero-trust security with strict mTLS and authorization policies
#
# Usage:
# kubectl apply -f mtls-authorization.yaml
---
# Enable strict mTLS for entire namespace
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default-strict-mtls
namespace: production
spec:
mtls:
mode: STRICT
---
# Default deny all traffic (zero-trust)
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: production
spec: {}
---
# Allow frontend to call backend (specific methods and paths)
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
selector:
matchLabels:
app: backend
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/production/sa/frontend
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/*"]
---
# Allow gateway to call all services
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: allow-gateway
namespace: production
spec:
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account
---
# Deny DELETE operations on database service
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-database-delete
namespace: production
spec:
selector:
matchLabels:
app: database
action: DENY
rules:
- to:
- operation:
methods: ["DELETE"]
# Linkerd Traffic Split Example
#
# Demonstrates: HTTPRoute-based traffic splitting for canary deployment
#
# Dependencies:
# kubectl annotate namespace production linkerd.io/inject=enabled
#
# Usage:
# kubectl apply -f traffic-split.yaml
---
# Backend v1 deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-v1
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: backend
version: v1
template:
metadata:
labels:
app: backend
version: v1
spec:
containers:
- name: backend
image: backend:v1
ports:
- containerPort: 8080
---
# Backend v2 deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-v2
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: backend
version: v2
template:
metadata:
labels:
app: backend
version: v2
spec:
containers:
- name: backend
image: backend:v2
ports:
- containerPort: 8080
---
# Service for v1
apiVersion: v1
kind: Service
metadata:
name: backend-v1
namespace: production
spec:
selector:
app: backend
version: v1
ports:
- port: 8080
---
# Service for v2
apiVersion: v1
kind: Service
metadata:
name: backend-v2
namespace: production
spec:
selector:
app: backend
version: v2
ports:
- port: 8080
---
# Main backend service
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: production
spec:
selector:
app: backend
ports:
- port: 8080
---
# HTTPRoute: 90% to v1, 10% to v2
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: backend-canary
namespace: production
spec:
parentRefs:
- name: backend
kind: Service
group: core
port: 8080
rules:
- backendRefs:
- name: backend-v1
port: 8080
weight: 90
- name: backend-v2
port: 8080
weight: 10
---
# ServiceProfile: Configure retries and timeouts
apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
name: backend.production.svc.cluster.local
namespace: production
spec:
routes:
- name: GET /api/users
condition:
method: GET
pathRegex: /api/users
timeout: 3s
retryBudget:
retryRatio: 0.2
minRetriesPerSecond: 10
ttl: 10s
- name: POST /api/users
condition:
method: POST
pathRegex: /api/users
timeout: 5s
isRetryable: false
skill: "implementing-service-mesh"
version: "1.0"
domain: "infrastructure"
base_outputs:
- path: "mesh/README.md"
must_contain: ["Service Mesh", "mTLS", "traffic management"]
description: "Service mesh documentation and architecture overview"
- path: "mesh/config/namespace-config.yaml"
must_contain: ["namespace", "labels"]
description: "Namespace configuration for mesh injection"
- path: "docs/mesh-decision.md"
must_contain: ["Istio", "Linkerd", "Cilium", "comparison"]
description: "Service mesh selection rationale"
conditional_outputs:
maturity:
starter:
- path: "mesh/config/mtls-config.yaml"
must_contain: ["PeerAuthentication", "PERMISSIVE"]
description: "Basic mTLS configuration in permissive mode"
- path: "mesh/traffic/basic-routing.yaml"
must_contain: ["VirtualService", "route"]
description: "Simple traffic routing configuration"
- path: "docs/getting-started.md"
must_contain: ["installation", "verification"]
description: "Getting started guide"
intermediate:
- path: "mesh/config/mtls-config.yaml"
must_contain: ["PeerAuthentication", "STRICT"]
description: "Strict mTLS enforcement"
- path: "mesh/security/authorization-policies.yaml"
must_contain: ["AuthorizationPolicy", "principals"]
description: "Identity-based authorization policies"
- path: "mesh/traffic/canary-deployment.yaml"
must_contain: ["weight", "subset"]
description: "Canary deployment configuration"
- path: "mesh/resilience/circuit-breaker.yaml"
must_contain: ["DestinationRule", "connectionPool", "outlierDetection"]
description: "Circuit breaker and connection pool settings"
- path: "mesh/observability/telemetry-config.yaml"
must_contain: ["metrics", "traces"]
description: "Observability configuration"
advanced:
- path: "mesh/multi-cluster/remote-secrets.yaml"
must_contain: ["secret", "cluster"]
description: "Multi-cluster service mesh secrets"
- path: "mesh/progressive-delivery/flagger-canary.yaml"
must_contain: ["Canary", "analysis", "metrics"]
description: "Automated progressive delivery with Flagger"
- path: "mesh/security/external-authorization.yaml"
must_contain: ["extensionProvider", "opa"]
description: "External authorization (OPA/custom)"
- path: "mesh/traffic/fault-injection.yaml"
must_contain: ["fault", "delay", "abort"]
description: "Chaos engineering with fault injection"
- path: "mesh/gateway/mesh-gateway.yaml"
must_contain: ["Gateway", "hosts", "servers"]
description: "Ingress/egress gateway configuration"
- path: "monitoring/mesh-dashboards.yaml"
must_contain: ["dashboard", "service mesh"]
description: "Grafana dashboards for mesh metrics"
- path: "monitoring/mesh-alerts.yaml"
must_contain: ["alert", "mtls", "traffic"]
description: "Alerting rules for mesh health"
service_mesh:
istio:
- path: "mesh/istio/install-config.yaml"
must_contain: ["IstioOperator", "profile"]
description: "Istio installation configuration"
- path: "mesh/istio/peer-authentication.yaml"
must_contain: ["apiVersion: security.istio.io/v1", "PeerAuthentication"]
description: "Istio mTLS peer authentication"
- path: "mesh/istio/virtual-service.yaml"
must_contain: ["apiVersion: networking.istio.io/v1", "VirtualService"]
description: "Istio traffic routing"
- path: "mesh/istio/destination-rule.yaml"
must_contain: ["apiVersion: networking.istio.io/v1", "DestinationRule"]
description: "Istio traffic policies and subsets"
- path: "mesh/istio/authorization-policy.yaml"
must_contain: ["apiVersion: security.istio.io/v1", "AuthorizationPolicy"]
description: "Istio authorization policies"
- path: "scripts/istio-install.sh"
must_contain: ["istioctl", "install"]
description: "Istio installation script"
linkerd:
- path: "mesh/linkerd/install-config.yaml"
must_contain: ["linkerd", "config"]
description: "Linkerd installation configuration"
- path: "mesh/linkerd/http-route.yaml"
must_contain: ["apiVersion: policy.linkerd.io/v1beta2", "HTTPRoute"]
description: "Linkerd traffic splitting"
- path: "mesh/linkerd/service-profile.yaml"
must_contain: ["apiVersion: linkerd.io/v1alpha2", "ServiceProfile"]
description: "Linkerd retries and timeouts"
- path: "mesh/linkerd/authorization-policy.yaml"
must_contain: ["apiVersion: policy.linkerd.io/v1alpha1", "AuthorizationPolicy"]
description: "Linkerd authorization"
- path: "scripts/linkerd-install.sh"
must_contain: ["linkerd", "install"]
description: "Linkerd installation script"
cilium:
- path: "mesh/cilium/helm-values.yaml"
must_contain: ["meshMode: enabled", "authentication"]
description: "Cilium service mesh Helm values"
- path: "mesh/cilium/network-policy.yaml"
must_contain: ["apiVersion: cilium.io/v2", "CiliumNetworkPolicy"]
description: "Cilium L3/L4/L7 network policies"
- path: "mesh/cilium/egress-policy.yaml"
must_contain: ["toFQDNs", "matchName"]
description: "Cilium DNS-based egress control"
- path: "mesh/cilium/spire-config.yaml"
must_contain: ["spire", "authentication"]
description: "Cilium with SPIRE integration"
- path: "scripts/cilium-install.sh"
must_contain: ["helm install cilium", "meshMode"]
description: "Cilium installation script"
istio-ambient:
- path: "mesh/istio/ambient-install.yaml"
must_contain: ["profile=ambient", "dataplane-mode=ambient"]
description: "Istio Ambient mode installation"
- path: "mesh/istio/waypoint-proxy.yaml"
must_contain: ["Gateway", "waypoint"]
description: "Istio Ambient L7 waypoint proxy"
- path: "mesh/istio/ztunnel-config.yaml"
must_contain: ["ztunnel"]
description: "Istio Ambient L4 ztunnel configuration"
observability:
prometheus:
- path: "monitoring/servicemonitor.yaml"
must_contain: ["ServiceMonitor", "endpoints"]
description: "Prometheus ServiceMonitor for mesh metrics"
- path: "monitoring/prometheus-rules.yaml"
must_contain: ["PrometheusRule", "groups"]
description: "Prometheus alerting rules"
jaeger:
- path: "mesh/tracing/jaeger-deployment.yaml"
must_contain: ["Jaeger", "collector"]
description: "Jaeger distributed tracing deployment"
- path: "mesh/tracing/telemetry-config.yaml"
must_contain: ["Telemetry", "providers", "zipkin"]
description: "Mesh tracing configuration"
grafana:
- path: "monitoring/grafana-dashboards/mesh-overview.json"
must_contain: ["dashboard", "panels"]
description: "Service mesh overview dashboard"
- path: "monitoring/grafana-dashboards/service-metrics.json"
must_contain: ["request_rate", "latency"]
description: "Per-service metrics dashboard"
scaffolding:
- path: "mesh/"
type: "directory"
description: "Root directory for service mesh configurations"
- path: "mesh/config/"
type: "directory"
description: "Core mesh configuration (mTLS, namespaces)"
- path: "mesh/security/"
type: "directory"
description: "Authorization policies and security configs"
- path: "mesh/traffic/"
type: "directory"
description: "Traffic management (routing, canary, blue/green)"
- path: "mesh/resilience/"
type: "directory"
description: "Resilience patterns (circuit breakers, retries)"
- path: "mesh/gateway/"
type: "directory"
description: "Ingress and egress gateway configurations"
- path: "mesh/multi-cluster/"
type: "directory"
description: "Multi-cluster mesh federation"
- path: "mesh/progressive-delivery/"
type: "directory"
description: "Automated canary and progressive delivery"
- path: "mesh/observability/"
type: "directory"
description: "Telemetry and observability configuration"
- path: "scripts/"
type: "directory"
description: "Installation and management scripts"
- path: "monitoring/"
type: "directory"
description: "Monitoring dashboards and alerts"
- path: "mesh/README.md"
type: "file"
template: |
# Service Mesh Configuration
This project uses [Istio/Linkerd/Cilium] for service mesh capabilities.
## Architecture
**Data Plane:** [Sidecar / Ambient / eBPF]
**mTLS Mode:** [STRICT / PERMISSIVE]
**Authorization:** [Default-deny / Allow-list]
## Quick Start
### Installation
```bash
# Install service mesh
./scripts/[istio/linkerd/cilium]-install.sh
# Verify installation
kubectl get pods -n [istio-system/linkerd/kube-system]
```
### Enable for Namespace
```bash
# Label namespace for mesh injection
kubectl label namespace production istio.io/dataplane-mode=ambient
# OR for Linkerd:
kubectl annotate namespace production linkerd.io/inject=enabled
```
### Verify mTLS
```bash
# Istio
istioctl authn tls-check frontend.production.svc.cluster.local
# Linkerd
linkerd edges deployment/frontend -n production
# Cilium
cilium bpf auth list
```
## Configuration
### mTLS Enforcement
- **Location:** `mesh/config/mtls-config.yaml`
- **Mode:** STRICT (reject plaintext connections)
- **Scope:** Namespace-wide
### Authorization Policies
- **Location:** `mesh/security/authorization-policies.yaml`
- **Default:** Deny all traffic
- **Explicit Allow:** Identity-based rules
### Traffic Management
- **Canary Deployments:** `mesh/traffic/canary-deployment.yaml`
- **Circuit Breakers:** `mesh/resilience/circuit-breaker.yaml`
- **Fault Injection:** `mesh/traffic/fault-injection.yaml`
## Progressive Delivery
Deploy new versions with automated canary analysis:
1. Deploy v2 with 0% traffic
2. Gradually increase: 10% → 25% → 50% → 100%
3. Monitor error rate, latency, throughput
4. Auto-rollback if metrics degrade
See `mesh/progressive-delivery/` for Flagger configurations.
## Multi-Cluster Setup
For multi-cluster service mesh:
1. Install mesh in each cluster
2. Exchange cluster secrets (see `mesh/multi-cluster/`)
3. Enable cross-cluster service discovery
4. Configure gateway for east-west traffic
## Troubleshooting
### mTLS Issues
```bash
# Check mTLS status
[istioctl authn tls-check / linkerd edges / cilium bpf auth list]
# Check certificates
[istioctl proxy-config secret / linkerd diagnostics proxy-metrics]
```
### Traffic Not Routing
```bash
# Analyze configuration
istioctl analyze -n production
# Tap traffic (Linkerd)
linkerd tap deployment/backend -n production
# Observe flows (Cilium)
hubble observe --namespace production
```
### Performance Issues
- Check proxy resource limits
- Review connection pool settings
- Analyze trace data in Jaeger
- Monitor mesh control plane health
## Security Best Practices
1. **Strict mTLS** - Reject plaintext connections
2. **Default Deny** - Explicit allow rules only
3. **Least Privilege** - Minimal service-to-service permissions
4. **Identity-Based** - Use workload identity, not IPs
5. **Audit Logging** - Enable for all authorization decisions
## Observability
- **Metrics:** Prometheus + Grafana dashboards
- **Traces:** Jaeger distributed tracing
- **Logs:** Aggregated control plane logs
- **Topology:** Service graph visualization
Dashboards: `monitoring/grafana-dashboards/`
## References
- Service Mesh Selection: `docs/mesh-decision.md`
- Installation Guide: `scripts/[mesh]-install.sh`
- Traffic Patterns: `references/[mesh]-patterns.md`
- Security Patterns: `references/security-patterns.md`
- Troubleshooting: `references/troubleshooting.md`
- path: "docs/mesh-decision.md"
type: "file"
template: |
# Service Mesh Selection
## Decision: [Istio Ambient / Linkerd / Cilium]
### Requirements
- [ ] Mutual TLS for all traffic
- [ ] L7 traffic routing
- [ ] Authorization policies
- [ ] Multi-cluster support
- [ ] Low latency overhead
- [ ] Easy operations
### Comparison
| Feature | Istio Ambient | Linkerd | Cilium |
|---------|---------------|---------|---------|
| Latency overhead | 8% (L4) | 33% | 99% |
| Architecture | Sidecar-less | Sidecar | eBPF |
| mTLS | Automatic | Automatic | With SPIRE |
| L7 routing | Optional waypoint | Built-in | Built-in |
| Multi-cluster | Strong | Good | Emerging |
| Complexity | Medium | Low | High |
| Maturity | New (2024) | Mature | Mature (network) |
### Rationale
**Chose [MESH] because:**
1. [Reason 1]
2. [Reason 2]
3. [Reason 3]
### Trade-offs
**Accepted:**
- [Trade-off 1]
- [Trade-off 2]
**Mitigated:**
- [How we addressed concern X]
### References
- Istio Ambient: https://istio.io/latest/docs/ambient/
- Linkerd: https://linkerd.io/
- Cilium Service Mesh: https://docs.cilium.io/en/stable/network/servicemesh/
metadata:
primary_blueprints: ["k8s", "security"]
contributes_to:
- "Service mesh deployment"
- "mTLS implementation"
- "Zero-trust security"
- "Traffic management"
- "Progressive delivery"
- "Multi-cluster networking"
integrates_with:
- "deploying-kubernetes" # Cluster setup, namespaces
- "security-hardening" # Container security, RBAC
- "infrastructure-as-code" # Terraform/Helm for mesh
- "building-ci-pipelines" # Automated canary deployments
- "performance-engineering" # Latency optimization
- "observability" # Metrics, traces, logs
common_patterns:
- name: "Istio Ambient with Flagger"
description: "Sidecar-less mesh with automated progressive delivery"
files: ["mesh/istio/ambient-install.yaml", "mesh/progressive-delivery/flagger-canary.yaml"]
- name: "Linkerd with HTTPRoute"
description: "Lightweight sidecar mesh with Gateway API traffic splitting"
files: ["mesh/linkerd/http-route.yaml", "mesh/linkerd/service-profile.yaml"]
- name: "Cilium with SPIRE"
description: "eBPF-native mesh with SPIFFE workload identity"
files: ["mesh/cilium/helm-values.yaml", "mesh/cilium/spire-config.yaml"]
- name: "Zero-Trust Security"
description: "Strict mTLS with default-deny authorization"
files: ["mesh/config/mtls-config.yaml", "mesh/security/authorization-policies.yaml"]
- name: "Multi-Cluster Mesh"
description: "Federated mesh across Kubernetes clusters"
files: ["mesh/multi-cluster/remote-secrets.yaml", "mesh/gateway/mesh-gateway.yaml"]
anti_patterns:
- name: "Permissive mTLS in production"
avoid: "Allows plaintext connections, defeats purpose"
use: "STRICT mode, reject all non-mTLS traffic"
- name: "No authorization policies"
avoid: "mTLS encrypts but doesn't authorize"
use: "Default-deny AuthorizationPolicy with explicit allows"
- name: "IP-based access control"
avoid: "Brittle, doesn't work with pod churn"
use: "Identity-based policies (service account principals)"
- name: "Manual canary weight updates"
avoid: "Error-prone, requires monitoring vigilance"
use: "Automated progressive delivery (Flagger, Argo Rollouts)"
- name: "No circuit breakers"
avoid: "Cascading failures across services"
use: "DestinationRule with outlierDetection and connectionPool"
- name: "Sidecar mode without resource limits"
avoid: "Proxy containers can starve application"
use: "Set CPU/memory limits, consider Ambient mode"
tools:
service_meshes:
- name: "Istio Ambient"
use_when: "Need enterprise features, low overhead, multi-cloud"
- name: "Linkerd"
use_when: "Simplicity priority, small-medium teams"
- name: "Cilium"
use_when: "eBPF infrastructure, future-proof, advanced networking"
progressive_delivery:
- name: "Flagger"
use_when: "Automated canary with Istio/Linkerd/App Mesh"
- name: "Argo Rollouts"
use_when: "GitOps workflow, advanced deployment strategies"
observability:
- name: "Kiali"
use_when: "Istio service graph visualization"
- name: "Linkerd Viz"
use_when: "Built-in Linkerd observability"
- name: "Hubble"
use_when: "Cilium network flow observability"
multi_cluster:
- name: "Istio Multi-Primary"
use_when: "Active-active, shared control plane"
- name: "Linkerd Multi-Cluster"
use_when: "Simple cross-cluster service mirroring"
validation_checks:
- "mTLS enforced (STRICT mode, no PERMISSIVE)"
- "Default-deny authorization policy exists"
- "Service-to-service policies use principals (not IPs)"
- "Circuit breakers configured for external dependencies"
- "Resource limits set for sidecar proxies (if using sidecar)"
- "Telemetry enabled (metrics, traces, logs)"
- "Gateway configured for external traffic"
- "Multi-cluster secrets properly scoped (if multi-cluster)"
- "Automated canary rollback configured"
- "Mesh control plane health monitored"
- "Certificate rotation tested"
- "Troubleshooting runbooks documented"
deployment_stages:
- stage: "starter"
description: "Basic mTLS and traffic routing"
files: ["mesh/config/mtls-config.yaml", "mesh/traffic/basic-routing.yaml"]
- stage: "intermediate"
description: "Zero-trust security and canary deployments"
files: ["mesh/security/authorization-policies.yaml", "mesh/traffic/canary-deployment.yaml"]
- stage: "advanced"
description: "Multi-cluster, automated progressive delivery, external authz"
files: ["mesh/multi-cluster/", "mesh/progressive-delivery/", "mesh/security/external-authorization.yaml"]
architecture_decisions:
- decision: "Data plane architecture"
options: ["Sidecar (per-pod proxy)", "Ambient (shared node proxy)", "eBPF (kernel-level)"]
considerations: ["Latency overhead", "Resource usage", "L7 features", "Operational complexity"]
- decision: "mTLS mode"
options: ["PERMISSIVE (migration)", "STRICT (production)"]
considerations: ["Security posture", "Legacy service compatibility", "Migration timeline"]
- decision: "Authorization model"
options: ["Default-allow", "Default-deny (zero-trust)"]
considerations: ["Security requirements", "Team velocity", "Audit compliance"]
- decision: "Progressive delivery automation"
options: ["Manual weight updates", "Flagger", "Argo Rollouts"]
considerations: ["Deployment frequency", "Team size", "Risk tolerance"]
- decision: "Multi-cluster topology"
options: ["Single cluster", "Multi-primary", "Primary-remote"]
considerations: ["HA requirements", "Geo-distribution", "Compliance boundaries"]
Cilium eBPF Service Mesh Patterns
Table of Contents
- CiliumNetworkPolicy Patterns
- L7 HTTP Policies
- DNS-Based Policies
- mTLS with SPIRE
- Observability with Hubble
CiliumNetworkPolicy Patterns
Cilium enforces network policies at kernel level using eBPF.
L3/L4 Policy (Basic)
Allow specific pods to communicate on specific ports.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
description: "Allow frontend pods to access backend on port 8080"
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCPNamespace-Level Policy
Allow all pods in one namespace to access another.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-from-frontend-namespace
namespace: backend
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCPEgress Policy
Control outbound traffic from pods.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: backend-egress
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
egress:
# Allow to database
- toEndpoints:
- matchLabels:
app: postgres
toPorts:
- ports:
- port: "5432"
protocol: TCP
# Allow to external API (requires DNS, see below)
- toFQDNs:
- matchName: "api.external.com"
toPorts:
- ports:
- port: "443"
protocol: TCP
# Allow DNS queries
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchPattern: "*"Deny-All Policy
Default deny for zero-trust security.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: deny-all-ingress
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- {} # Empty rule denies all ingressLabel-Based Selection
Select endpoints using Kubernetes labels.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: label-based-policy
spec:
endpointSelector:
matchLabels:
app: backend
env: production
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
env: production
- matchLabels:
app: gateway
tier: public
toPorts:
- ports:
- port: "8080"L7 HTTP Policies
Cilium supports L7 (HTTP) policy enforcement.
HTTP Method and Path
Allow specific HTTP methods and paths.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: http-api-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: GET
path: "/api/users"
- method: GET
path: "/api/users/.*"
- method: POST
path: "/api/users"HTTP Header Matching
Match on HTTP headers.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: http-header-policy
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
rules:
http:
- method: GET
path: "/api/admin/.*"
headers:
- "X-Admin-Token: secret-value"HTTP Host Header
Route based on Host header.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: http-host-policy
spec:
endpointSelector:
matchLabels:
app: ingress
ingress:
- fromEndpoints:
- matchLabels:
reserved:world
toPorts:
- ports:
- port: "80"
rules:
http:
- method: GET
host: "api.example.com"
path: "/.*"gRPC Policy
Control gRPC services and methods.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: grpc-policy
spec:
endpointSelector:
matchLabels:
app: grpc-backend
ingress:
- fromEndpoints:
- matchLabels:
app: grpc-client
toPorts:
- ports:
- port: "9090"
rules:
http:
- method: POST
path: "/user.UserService/GetUser"
- method: POST
path: "/user.UserService/ListUsers"DNS-Based Policies
Control egress to external services by DNS name.
Basic FQDN Matching
Allow egress to specific domain.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-github-api
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
egress:
- toFQDNs:
- matchName: "api.github.com"
toPorts:
- ports:
- port: "443"
protocol: TCP
# Allow DNS
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchPattern: "*"Wildcard FQDN
Allow egress to domain and subdomains.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-aws-services
spec:
endpointSelector:
matchLabels:
app: backend
egress:
- toFQDNs:
- matchPattern: "*.amazonaws.com"
toPorts:
- ports:
- port: "443"
protocol: TCPMultiple FQDNs
Allow multiple external services.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-external-apis
spec:
endpointSelector:
matchLabels:
app: backend
egress:
- toFQDNs:
- matchName: "api.github.com"
- matchName: "api.stripe.com"
- matchPattern: "*.slack.com"
toPorts:
- ports:
- port: "443"
protocol: TCP
# Allow DNS
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchPattern: "*"DNS Policy with TTL
Configure DNS TTL for policy updates.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: fqdn-with-ttl
spec:
endpointSelector:
matchLabels:
app: backend
egress:
- toFQDNs:
- matchName: "dynamic.example.com"
toPorts:
- ports:
- port: "443"
egressDeny:
- toFQDNs:
- matchPattern: "malicious.*"mTLS with SPIRE
Cilium integrates with SPIRE for mutual TLS.
Enable mTLS (Helm Values)
Install Cilium with SPIRE authentication.
# values.yaml for Cilium Helm chart
authentication:
mutual:
spire:
enabled: true
install:
enabled: true
server:
dataStorage:
size: 1Gi
agent:
image:
tag: 1.8.5Install Command
helm install cilium cilium/cilium \
--namespace kube-system \
--set authentication.mutual.spire.enabled=true \
--set authentication.mutual.spire.install.enabled=truemTLS Required Policy
Require mTLS for specific traffic.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: mtls-required
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
authentication:
mode: required # Require mTLS
toPorts:
- ports:
- port: "8080"Service Identity Verification
Verify SPIFFE identity in policy.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: identity-based-mtls
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
k8s:io.cilium.k8s.policy.serviceaccount: frontend-sa
authentication:
mode: required
toPorts:
- ports:
- port: "8080"Check mTLS Status
# List authenticated connections
cilium bpf auth list
# Check specific endpoint
cilium endpoint list
cilium endpoint get <endpoint-id>Cluster-Wide Policies
Apply policies across all namespaces.
CiliumClusterwideNetworkPolicy
Global default-deny policy.
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: default-deny-all
spec:
description: "Deny all traffic by default"
endpointSelector: {}
ingress:
- {}
egress:
# Allow DNS for all pods
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANYAllow Cluster Communication
Allow essential cluster traffic.
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: allow-cluster-essentials
spec:
endpointSelector: {}
egress:
# Allow to Kubernetes API server
- toEntities:
- kube-apiserver
# Allow DNS
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"Observability with Hubble
Hubble provides eBPF-based observability.
Enable Hubble
helm upgrade cilium cilium/cilium \
--namespace kube-system \
--reuse-values \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=trueObserve Traffic
# Watch all traffic in namespace
hubble observe --namespace production
# Filter by specific pod
hubble observe --pod backend-7d8f9c5b4-xyz12
# Filter by verdict (dropped, forwarded)
hubble observe --verdict DROPPED
# Filter by protocol
hubble observe --protocol http
# Show specific ports
hubble observe --port 8080
# Show DNS queries
hubble observe --type l7 --protocol dnsHubble Metrics
Export metrics to Prometheus.
# Enable Hubble metrics
hubble:
metrics:
enabled:
- dns
- drop
- tcp
- flow
- icmp
- httpUseful Metrics:
# HTTP request rate
rate(hubble_http_requests_total[5m])
# DNS query rate
rate(hubble_dns_queries_total[5m])
# Dropped packets
rate(hubble_drop_total[5m])
# TCP flags
rate(hubble_tcp_flags_total[5m])Hubble UI
Access visual service map.
# Port forward Hubble UI
kubectl port-forward -n kube-system svc/hubble-ui 12000:80
# Open browser
open http://localhost:12000Flow Filtering
Advanced flow filtering.
# Show flows between specific services
hubble observe --from-pod frontend --to-pod backend
# Show HTTP 500 errors
hubble observe --type l7 --http-status 500
# Show specific HTTP methods
hubble observe --type l7 --http-method POST
# Show specific paths
hubble observe --type l7 --http-path "/api/users"
# Export to JSON
hubble observe -o json --last 100 > flows.jsonCiliumEnvoyConfig (Advanced L7)
Use Envoy for advanced L7 routing.
Basic Envoy Configuration
Enable Envoy for specific service.
apiVersion: cilium.io/v2
kind: CiliumEnvoyConfig
metadata:
name: backend-envoy
namespace: production
spec:
services:
- name: backend
namespace: production
resources:
- "@type": type.googleapis.com/envoy.config.listener.v3.Listener
name: backend-listener
filterChains:
- filters:
- name: envoy.filters.network.http_connection_manager
typedConfig:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
statPrefix: backend
routeConfig:
name: backend_route
virtualHosts:
- name: backend
domains: ["*"]
routes:
- match:
prefix: "/v1"
route:
cluster: backend-v1
- match:
prefix: "/v2"
route:
cluster: backend-v2Multi-Cluster with Cilium
Cluster Mesh enables multi-cluster connectivity.
Enable Cluster Mesh
# Install Cilium on cluster 1
helm install cilium cilium/cilium \
--namespace kube-system \
--set cluster.name=cluster1 \
--set cluster.id=1
# Install Cilium on cluster 2
helm install cilium cilium/cilium \
--namespace kube-system \
--set cluster.name=cluster2 \
--set cluster.id=2
# Enable cluster mesh
cilium clustermesh enable
# Connect clusters
cilium clustermesh connect --context cluster1 --destination-context cluster2Cross-Cluster Policy
Allow traffic between clusters.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: cross-cluster-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
k8s:io.cilium.k8s.policy.cluster: cluster1
- matchLabels:
app: frontend
k8s:io.cilium.k8s.policy.cluster: cluster2Best Practices
Policy Design:
- Start with cluster-wide default-deny
- Use explicit allow rules for required traffic
- Prefer identity-based policies over IP-based
- Test policies in audit mode before enforcing
- Use labels consistently across applications
L7 Policies:
- Apply L7 rules only where necessary (performance impact)
- Combine with L3/L4 rules for defense in depth
- Use HTTP method and path restrictions
- Monitor L7 policy performance with Hubble
DNS Policies:
- Always allow DNS to kube-dns
- Use specific FQDNs over wildcards when possible
- Monitor DNS queries for anomalies
- Consider DNS TTL impact on policy updates
mTLS:
- Enable SPIRE for production workloads
- Require mTLS for sensitive services
- Monitor authentication failures
- Rotate SPIRE credentials regularly
Observability:
- Enable Hubble for all clusters
- Export metrics to Prometheus
- Use Hubble UI for visual debugging
- Set up alerts for dropped packets and policy violations
Multi-Cluster:
- Use consistent cluster IDs
- Test failover scenarios
- Monitor cross-cluster latency
- Implement circuit breakers for remote calls
Service Mesh Selection Decision Tree
Table of Contents
- Quick Decision Matrix
- Detailed Comparison Matrix
- Use Case Recommendations
- Sidecar vs Sidecar-less
- Performance Comparison
- Migration Paths
- Key Decision Factors
- Summary Recommendations
Quick Decision Matrix
START: Need service mesh for Kubernetes?
│
├─→ Priority: Simplicity + Low Overhead + Small Team
│ └─→ **LINKERD**
│ ✓ Lightweight Rust-based micro-proxy
│ ✓ Lowest latency overhead (33% with mTLS)
│ ✓ Automatic mTLS with zero config
│ ✓ Simple installation and operation
│ ✓ Best for: Small-medium teams, easy adoption
│
├─→ Priority: eBPF + Future-Proof + Advanced Networking
│ └─→ **CILIUM**
│ ✓ Sidecar-less by design (eBPF in kernel)
│ ✓ Advanced network policies (L3/L4/L7)
│ ✓ Integrated CNI (replaces kube-proxy)
│ ✓ Kernel-level observability (Hubble)
│ ✓ Best for: eBPF infrastructure, performance-critical
│
└─→ Priority: Enterprise Features + Multi-Cloud + Flexibility
└─→ **ISTIO**
├─→ Sidecar Mode (traditional)
│ ✓ Fine-grained L7 control per pod
│ ✓ Mature, battle-tested
│ ✗ 166% latency overhead with mTLS
│ ✓ Best for: Complex L7 requirements per service
│
└─→ Ambient Mode (modern, recommended)
✓ Sidecar-less L4 (ztunnel per-node)
✓ Optional L7 (waypoint per-namespace)
✓ Only 8% latency overhead with mTLS
✓ Lower resource consumption
✓ Best for: New deployments, enterprise scaleDetailed Comparison Matrix
| Criteria | Istio Sidecar | Istio Ambient | Linkerd | Cilium |
|---|---|---|---|---|
| Architecture | Sidecar (Envoy) | ztunnel + waypoint | Sidecar (linkerd2-proxy) | eBPF + optional Envoy |
| Latency Overhead (mTLS) | 166% | 8% ⭐ | 33% ⭐ | 99% |
| Resource Usage | High (per-pod) | Low (per-node) | Medium (lightweight proxy) | Low (kernel-level) |
| L7 Granularity | Per-pod | Per-namespace (waypoint) | Per-pod | Per-namespace or cluster |
| Installation Complexity | Medium | Medium | Low ⭐ | High (CNI integration) |
| Upgrade Complexity | High (pod restart) | Medium (node-level) | Medium (pod restart) | Low (kernel upgrade) |
| Multi-Cluster | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Advanced Routing | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| Security (mTLS) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Observability | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Community/Ecosystem | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Production Maturity | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
Use Case Recommendations
Enterprise Multi-Cloud
Recommended: Istio Ambient
- Multi-cluster federation (primary requirement)
- Advanced traffic management (weighted routing, mirroring)
- Enterprise compliance requirements
- Large engineering organization
- Lower overhead than sidecar mode
Alternative: Istio Sidecar
- Use if per-pod L7 policies are essential
- Trade higher overhead for fine-grained control
Startup or Small Team
Recommended: Linkerd
- Simplest to install and operate
- Lowest learning curve
- Automatic mTLS with zero configuration
- Best latency overhead for sidecar model
- Small resource footprint
Alternative: Istio Ambient
- Choose if expecting rapid growth
- Need for advanced features later
Performance-Critical Workloads
Recommended: Linkerd (sidecar)
- Lowest latency overhead (33%)
- Rust-based proxy (memory-safe, fast)
- Minimal resource consumption
- Simple troubleshooting
Alternative: Istio Ambient
- Second-best latency (8%)
- More features if needed
eBPF-Based Infrastructure
Recommended: Cilium
- Native eBPF enforcement at kernel level
- Integrated CNI (replaces kube-proxy)
- Advanced network policies
- Future-proof architecture
- Kernel-level observability
Note: Higher latency overhead (99%) vs other options, but unmatched networking features.
High-Compliance Environments
Recommended: Istio (Ambient or Sidecar)
- Comprehensive audit logging
- Advanced authorization policies
- External authorization (OPA, ext-authz)
- Proven in regulated industries
- Enterprise support available
Gradual Mesh Adoption
Recommended: Istio Ambient
- Start with L4 mTLS (ztunnel)
- Add L7 policies (waypoint) only where needed
- Namespace-level granularity
- No sidecar injection required
Alternative: Linkerd
- Simple namespace-level injection
- Gradual rollout with permissive mode
Sidecar vs Sidecar-less
Sidecar Architecture
How it Works:
- Proxy container injected into each pod
- Intercepts all network traffic (iptables or eBPF)
- Per-pod policy enforcement
- Independent proxy configuration
Advantages:
- Strong isolation (per-pod)
- Fine-grained L7 control
- Easy debugging (proxy per pod)
- Mature and battle-tested
Disadvantages:
- Higher resource usage (CPU/memory per pod)
- Higher latency overhead (extra hop)
- Complex upgrades (pod restarts)
- More moving parts
When to Use:
- Need per-pod L7 policies
- Strong isolation required
- Service-specific configurations
- Mature tooling priority
Sidecar-less Architecture
Istio Ambient:
- ztunnel (L4): Per-node shared proxy, mTLS enforcement
- waypoint (L7): Per-namespace optional proxy for HTTP routing
- Progressive adoption path
Cilium:
- eBPF programs in kernel
- No proxies for L3/L4
- Optional Envoy for L7
Advantages:
- Lower latency overhead
- Reduced resource consumption
- Simpler operations (fewer containers)
- Easier upgrades (node-level)
Disadvantages:
- Less mature (newer technology)
- Weaker isolation (shared components)
- Coarser granularity (namespace vs pod)
- Complex debugging (shared state)
When to Use:
- Lower overhead priority
- Simplified operations
- Namespace-level policies acceptable
- Modern infrastructure
Performance Comparison
Latency Overhead (with mTLS enabled)
Based on service mesh benchmarks (2025):
| Mesh | Mode | Latency Increase | Baseline (no mesh) |
|---|---|---|---|
| None | - | 0% | 1.0ms (reference) |
| Istio | Ambient | +8% | 1.08ms |
| Linkerd | Sidecar | +33% | 1.33ms |
| Cilium | eBPF | +99% | 1.99ms |
| Istio | Sidecar | +166% | 2.66ms |
Key Insight: Istio Ambient offers best balance of features and performance.
Resource Usage
Per-Pod Overhead (Sidecar):
- Istio Envoy: ~50MB memory, ~0.1 CPU cores
- Linkerd proxy: ~10MB memory, ~0.01 CPU cores ⭐
Per-Node Overhead (Sidecar-less):
- Istio ztunnel: ~100MB memory, ~0.2 CPU cores
- Cilium agent: ~150MB memory, ~0.3 CPU cores
Calculation Example (100 pods):
- Istio Sidecar: 5GB memory, 10 CPU cores
- Linkerd: 1GB memory, 1 CPU core
- Istio Ambient: 100MB memory (shared), 0.2 CPU cores
- Cilium: 150MB memory (shared), 0.3 CPU cores
Migration Paths
From No Mesh to Mesh
Recommended Order: 1. Install mesh control plane 2. Enable mTLS in PERMISSIVE mode (accept plaintext) 3. Inject mesh into non-critical namespaces first 4. Validate connectivity and observability 5. Switch to STRICT mTLS (reject plaintext) 6. Roll out to production namespaces
From Sidecar to Sidecar-less (Istio)
Migration to Ambient: 1. Install Istio with ambient profile 2. Keep existing sidecar namespaces running 3. New namespaces: label with istio.io/dataplane-mode=ambient 4. Test ambient mode in staging 5. Gradually migrate namespaces (remove sidecar injection, add ambient label) 6. Remove sidecar injection from all namespaces
Between Different Meshes
General Approach: 1. Install new mesh alongside existing 2. Run both meshes in parallel (different namespaces) 3. Migrate services namespace by namespace 4. Test thoroughly at each stage 5. Remove old mesh when migration complete
Complexity: High - Avoid if possible. Choose right mesh initially.
Key Decision Factors
Team Size and Expertise
- Small team (<10 engineers): Linkerd (simplicity)
- Medium team (10-50 engineers): Istio Ambient or Linkerd
- Large team (>50 engineers): Istio (features, scale)
Workload Characteristics
- Low latency critical: Linkerd (33% overhead)
- High throughput: Istio Ambient (8% overhead)
- eBPF-based networking: Cilium (kernel-level)
Operational Constraints
- Limited resources: Sidecar-less (Ambient, Cilium)
- Complex upgrades problematic: Sidecar-less preferred
- Need quick rollbacks: Sidecar (easier isolation)
Future Requirements
- Expecting growth: Istio (scales to enterprise)
- Multi-cloud planned: Istio (best multi-cluster)
- eBPF investment: Cilium (future-proof)
Summary Recommendations
2025 General Guidance:
1. Default choice: Istio Ambient (best balance of features and performance) 2. Simplicity priority: Linkerd (easiest to adopt) 3. eBPF future: Cilium (kernel-level networking) 4. Legacy compatibility: Istio Sidecar (mature, proven)
Anti-Patterns:
- ❌ Don't choose Istio Sidecar for new deployments (use Ambient instead)
- ❌ Don't choose Cilium if team lacks eBPF expertise
- ❌ Don't choose Linkerd if advanced L7 routing is critical
- ❌ Don't migrate between meshes unless absolutely necessary
Success Criteria:
- ✅ mTLS working across all services
- ✅ Authorization policies enforced
- ✅ Observability dashboards operational
- ✅ Canary deployments functioning
- ✅ Team can troubleshoot common issues
Istio Configuration Patterns
Table of Contents
- VirtualService Patterns
- DestinationRule Patterns
- Gateway Patterns
- ServiceEntry Patterns
- Combined Routing Examples
VirtualService Patterns
VirtualService defines routing rules for traffic within the mesh.
Path-Based Routing
Route traffic based on URL path.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: api-versioning
namespace: production
spec:
hosts:
- api.example.com
http:
- match:
- uri:
prefix: /v2/
route:
- destination:
host: api-v2.production.svc.cluster.local
port:
number: 8080
- match:
- uri:
prefix: /v1/
route:
- destination:
host: api-v1.production.svc.cluster.local
port:
number: 8080
- route:
- destination:
host: api-v1.production.svc.cluster.local
port:
number: 8080Header-Based Routing
Route based on HTTP headers (user-agent, custom headers, cookies).
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: header-routing
spec:
hosts:
- backend
http:
# Route mobile users to mobile-optimized backend
- match:
- headers:
user-agent:
regex: ".*(Mobile|Android|iPhone).*"
route:
- destination:
host: backend
subset: mobile
# Route beta testers to canary
- match:
- headers:
x-beta-user:
exact: "true"
route:
- destination:
host: backend
subset: canary
# Default route
- route:
- destination:
host: backend
subset: stableWeight-Based Traffic Splitting
Distribute traffic across multiple versions.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: canary-rollout
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 75
- destination:
host: reviews
subset: v2
weight: 25Fault Injection
Inject faults for chaos engineering and testing.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: fault-injection
spec:
hosts:
- backend
http:
- match:
- headers:
x-test-fault:
exact: "true"
fault:
delay:
percentage:
value: 10.0
fixedDelay: 5s
abort:
percentage:
value: 5.0
httpStatus: 503
route:
- destination:
host: backend
- route:
- destination:
host: backendTraffic Mirroring
Mirror traffic to a shadow deployment for testing.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: traffic-mirror
spec:
hosts:
- backend
http:
- route:
- destination:
host: backend
subset: v1
weight: 100
mirror:
host: backend
subset: v2-shadow
mirrorPercentage:
value: 10.0Retries and Timeouts
Configure resilience policies.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: resilient-routing
spec:
hosts:
- backend
http:
- route:
- destination:
host: backend
timeout: 3s
retries:
attempts: 3
perTryTimeout: 1s
retryOn: 5xx,reset,connect-failure,refused-streamURL Rewrite
Rewrite URLs before routing.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: url-rewrite
spec:
hosts:
- api.example.com
http:
- match:
- uri:
prefix: /legacy/
rewrite:
uri: /api/v1/
route:
- destination:
host: backendCORS Configuration
Configure Cross-Origin Resource Sharing.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: cors-enabled
spec:
hosts:
- api.example.com
http:
- corsPolicy:
allowOrigins:
- exact: https://example.com
- prefix: https://*.example.com
allowMethods:
- GET
- POST
- PUT
- DELETE
allowHeaders:
- Authorization
- Content-Type
maxAge: "24h"
allowCredentials: true
route:
- destination:
host: backendDestinationRule Patterns
DestinationRule configures traffic policies for destinations.
Circuit Breaker
Fail fast when backend is unhealthy.
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: circuit-breaker
spec:
host: backend.production.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 10
http2MaxRequests: 100
maxRequestsPerConnection: 2
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
minHealthPercent: 20Load Balancing Algorithms
Configure client-side load balancing.
Round Robin:
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: round-robin-lb
spec:
host: backend
trafficPolicy:
loadBalancer:
simple: ROUND_ROBINConsistent Hash (Sticky Sessions):
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: sticky-sessions
spec:
host: backend
trafficPolicy:
loadBalancer:
consistentHash:
httpHeaderName: x-user-idLeast Connections:
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: least-conn-lb
spec:
host: backend
trafficPolicy:
loadBalancer:
simple: LEAST_CONNSubset Configuration
Define subsets based on labels.
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: backend-subsets
spec:
host: backend
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: canary
labels:
version: v2
track: canaryTLS Configuration
Configure client-side TLS for upstream connections.
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: tls-origination
spec:
host: external-service.example.com
trafficPolicy:
tls:
mode: SIMPLE
sni: external-service.example.comMutual TLS to External Service:
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: mtls-origination
spec:
host: secure-external.example.com
trafficPolicy:
tls:
mode: MUTUAL
clientCertificate: /etc/certs/client-cert.pem
privateKey: /etc/certs/client-key.pem
caCertificates: /etc/certs/ca-cert.pemConnection Pool Settings
Control connection pooling behavior.
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: connection-pool
spec:
host: backend
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
connectTimeout: 30ms
tcpKeepalive:
time: 7200s
interval: 75s
http:
h2UpgradePolicy: UPGRADE
http1MaxPendingRequests: 10
http2MaxRequests: 100
maxRequestsPerConnection: 2
idleTimeout: 3600sGateway Patterns
Gateway manages ingress and egress traffic.
HTTPS Ingress Gateway
Terminate TLS at gateway.
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: https-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- api.example.com
- web.example.com
tls:
mode: SIMPLE
credentialName: example-com-cert
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: gateway-routing
spec:
hosts:
- api.example.com
gateways:
- istio-system/https-gateway
http:
- match:
- uri:
prefix: /api/
route:
- destination:
host: backend.production.svc.cluster.local
port:
number: 8080HTTP to HTTPS Redirect
Redirect all HTTP traffic to HTTPS.
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: http-redirect
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- api.example.com
tls:
httpsRedirect: true
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- api.example.com
tls:
mode: SIMPLE
credentialName: api-certMutual TLS at Gateway
Require client certificates at ingress.
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: mtls-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https-mtls
protocol: HTTPS
hosts:
- secure.example.com
tls:
mode: MUTUAL
credentialName: secure-example-com-cert
caCertificates: /etc/istio/ca-certificates/ca-cert.pemEgress Gateway
Route external traffic through egress gateway.
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: egress-gateway
namespace: istio-system
spec:
selector:
istio: egressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- api.external.com
tls:
mode: PASSTHROUGH
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: egress-routing
spec:
hosts:
- api.external.com
gateways:
- mesh
- istio-system/egress-gateway
http:
- match:
- gateways:
- mesh
port: 80
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
port:
number: 443
- match:
- gateways:
- istio-system/egress-gateway
port: 443
route:
- destination:
host: api.external.com
port:
number: 443ServiceEntry Patterns
ServiceEntry adds external services to mesh.
External HTTPS Service
Add external API to service registry.
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: external-api
spec:
hosts:
- api.github.com
ports:
- number: 443
name: https
protocol: HTTPS
location: MESH_EXTERNAL
resolution: DNSExternal Database
Add external database with static IPs.
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: external-postgres
spec:
hosts:
- postgres.example.com
addresses:
- 10.20.30.40
ports:
- number: 5432
name: postgres
protocol: TCP
location: MESH_EXTERNAL
resolution: STATIC
endpoints:
- address: 10.20.30.40
ports:
postgres: 5432Mesh Expansion (VM Integration)
Add VMs to service mesh.
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
name: vm-service
spec:
hosts:
- vm-backend.example.com
ports:
- number: 8080
name: http
protocol: HTTP
location: MESH_INTERNAL
resolution: STATIC
endpoints:
- address: 192.168.1.100
ports:
http: 8080
labels:
app: backend
version: v1Combined Routing Examples
Canary Deployment with Monitoring
Canary deployment with header-based routing and traffic split.
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: backend-subsets
spec:
host: backend
subsets:
- name: stable
labels:
version: v1
- name: canary
labels:
version: v2
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend-canary
spec:
hosts:
- backend
http:
# Internal testers always see canary
- match:
- headers:
x-canary-user:
exact: "true"
route:
- destination:
host: backend
subset: canary
# 10% of production traffic to canary
- route:
- destination:
host: backend
subset: stable
weight: 90
- destination:
host: backend
subset: canary
weight: 10Multi-Region Routing with Failover
Route to nearest region with failover.
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: multi-region
spec:
host: backend
trafficPolicy:
loadBalancer:
localityLbSetting:
enabled: true
distribute:
- from: us-east/*
to:
"us-east/*": 80
"us-west/*": 20
- from: us-west/*
to:
"us-west/*": 80
"us-east/*": 20
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30sA/B Testing
Route traffic based on user segments.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: ab-test
spec:
hosts:
- frontend
http:
# Variant A: Control group
- match:
- headers:
cookie:
regex: "^(.*?;)?(ab-test=a)(;.*)?$"
route:
- destination:
host: frontend
subset: variant-a
# Variant B: Treatment group
- match:
- headers:
cookie:
regex: "^(.*?;)?(ab-test=b)(;.*)?$"
route:
- destination:
host: frontend
subset: variant-b
# Default: 50/50 split with cookie injection
- route:
- destination:
host: frontend
subset: variant-a
weight: 50
- destination:
host: frontend
subset: variant-b
weight: 50Blue/Green Deployment
Instant cutover between versions.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: blue-green
spec:
hosts:
- backend
http:
# Route all traffic to green (or blue for rollback)
- route:
- destination:
host: backend
subset: green
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: backend-versions
spec:
host: backend
subsets:
- name: blue
labels:
version: blue
- name: green
labels:
version: greenBest Practices
VirtualService:
- Use specific host matches (avoid wildcards in production)
- Order match conditions from most to least specific
- Always include a default route (no match conditions)
- Set reasonable timeouts (avoid infinite waits)
- Use retries judiciously (avoid retry storms)
DestinationRule:
- Configure circuit breakers for external dependencies
- Use outlier detection to remove unhealthy endpoints
- Set connection pool limits to prevent resource exhaustion
- Choose load balancing algorithm based on workload characteristics
- Define subsets for all versions in use
Gateway:
- Use TLS for all ingress traffic (HTTPS only)
- Store certificates in Kubernetes secrets
- Configure HTTP to HTTPS redirects
- Use separate gateways for different security zones
- Rotate certificates before expiration
ServiceEntry:
- Use DNS resolution for cloud services
- Use STATIC resolution with specific IPs for legacy systems
- Set appropriate protocols (HTTP, HTTPS, TCP, gRPC)
- Configure timeouts and retries for external services
- Monitor external service health
Linkerd Configuration Patterns
Table of Contents
- HTTPRoute Patterns
- ServiceProfile Patterns
- Server and Policy Patterns
- Authorization Patterns
- Observability Integration
HTTPRoute Patterns
HTTPRoute uses Gateway API standard for traffic management.
Basic Traffic Splitting
Canary deployment with weight-based routing.
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: backend-canary
namespace: production
spec:
parentRefs:
- name: backend
kind: Service
group: core
port: 8080
rules:
- backendRefs:
- name: backend-v1
port: 8080
weight: 90
- name: backend-v2
port: 8080
weight: 10Path-Based Routing
Route based on URL path prefix.
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: api-versioning
spec:
parentRefs:
- name: api-gateway
kind: Service
rules:
- matches:
- path:
type: PathPrefix
value: /v1
backendRefs:
- name: api-v1
port: 8080
- matches:
- path:
type: PathPrefix
value: /v2
backendRefs:
- name: api-v2
port: 8080
- backendRefs:
- name: api-v1
port: 8080Header-Based Routing
Route based on HTTP headers.
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: header-routing
spec:
parentRefs:
- name: backend
rules:
- matches:
- headers:
- name: x-canary-user
value: "true"
backendRefs:
- name: backend-canary
port: 8080
- matches:
- headers:
- name: user-agent
value: "mobile"
type: Exact
backendRefs:
- name: backend-mobile
port: 8080
- backendRefs:
- name: backend-stable
port: 8080Request Header Modification
Add, set, or remove headers.
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: header-modification
spec:
parentRefs:
- name: backend
rules:
- filters:
- type: RequestHeaderModifier
requestHeaderModifier:
set:
- name: x-forwarded-by
value: linkerd-mesh
add:
- name: x-custom-header
value: custom-value
remove:
- x-internal-header
backendRefs:
- name: backend
port: 8080Cross-Namespace Routing
Route to services in different namespaces.
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: cross-namespace
namespace: frontend
spec:
parentRefs:
- name: frontend-service
namespace: frontend
rules:
- backendRefs:
- name: backend-service
namespace: backend
port: 8080ServiceProfile Patterns
ServiceProfile configures per-route metrics, retries, and timeouts.
Basic ServiceProfile
Define routes for better observability.
apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
name: backend.production.svc.cluster.local
namespace: production
spec:
routes:
- name: GET /api/users
condition:
method: GET
pathRegex: /api/users
- name: POST /api/users
condition:
method: POST
pathRegex: /api/users
- name: GET /api/users/[id]
condition:
method: GET
pathRegex: /api/users/[^/]+Retries Configuration
Configure automatic retries for idempotent requests.
apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
name: backend.production.svc.cluster.local
namespace: production
spec:
routes:
- name: GET /api/data
condition:
method: GET
pathRegex: /api/data
timeout: 3s
retryBudget:
retryRatio: 0.2
minRetriesPerSecond: 10
ttl: 10s
- name: POST /api/data
condition:
method: POST
pathRegex: /api/data
timeout: 5s
isRetryable: falseTimeout Configuration
Set per-route timeout values.
apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
name: slow-service.production.svc.cluster.local
spec:
routes:
- name: GET /slow-operation
condition:
method: GET
pathRegex: /slow-operation
timeout: 30s
- name: GET /fast-operation
condition:
method: GET
pathRegex: /fast-operation
timeout: 1sResponse Class Configuration
Define custom success criteria.
apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
name: backend.production.svc.cluster.local
spec:
routes:
- name: GET /api/users
condition:
method: GET
pathRegex: /api/users
responseClasses:
- condition:
status:
min: 200
max: 299
isFailure: false
- condition:
status:
min: 500
max: 599
isFailure: trueAuto-Generated ServiceProfiles
Generate ServiceProfile from live traffic.
# Generate from OpenAPI spec
linkerd profile --open-api swagger.json backend
# Generate from Protobuf
linkerd profile --proto api.proto backend
# Generate from live traffic observation
linkerd profile -n production backend --tap deploy/backend --tap-duration 60sServer and Policy Patterns
Server resource defines policy attachment points.
Basic Server Definition
Define a server for policy targeting.
apiVersion: policy.linkerd.io/v1beta3
kind: Server
metadata:
name: backend-api
namespace: production
spec:
podSelector:
matchLabels:
app: backend
port: 8080
proxyProtocol: HTTP/2Multiple Ports
Define servers for different ports.
apiVersion: policy.linkerd.io/v1beta3
kind: Server
metadata:
name: backend-http
namespace: production
spec:
podSelector:
matchLabels:
app: backend
port: 8080
proxyProtocol: HTTP/1
---
apiVersion: policy.linkerd.io/v1beta3
kind: Server
metadata:
name: backend-grpc
namespace: production
spec:
podSelector:
matchLabels:
app: backend
port: 9090
proxyProtocol: gRPCServer with HTTP Route
Combine Server with HTTPRoute for granular control.
apiVersion: policy.linkerd.io/v1beta3
kind: Server
metadata:
name: api-server
namespace: production
spec:
podSelector:
matchLabels:
app: api
port: 8080
---
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: api-routes
namespace: production
spec:
parentRefs:
- name: api-server
kind: Server
group: policy.linkerd.io
rules:
- matches:
- path:
value: /admin
backendRefs:
- name: admin-backend
port: 8080
- backendRefs:
- name: public-backend
port: 8080Authorization Patterns
Linkerd authorization uses identity-based access control.
Allow Specific Service
Allow one service to call another.
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: allow-frontend
namespace: production
spec:
targetRef:
group: policy.linkerd.io
kind: Server
name: backend-api
requiredAuthenticationRefs:
- name: frontend-identity
kind: MeshTLSAuthentication
---
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
name: frontend-identity
namespace: production
spec:
identities:
- "frontend.production.serviceaccount.identity.linkerd.cluster.local"Allow Multiple Services
Allow multiple services with one policy.
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
name: allowed-clients
namespace: production
spec:
identities:
- "frontend.production.serviceaccount.identity.linkerd.cluster.local"
- "gateway.production.serviceaccount.identity.linkerd.local"
- "*.staging.serviceaccount.identity.linkerd.cluster.local"
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: allow-clients
namespace: production
spec:
targetRef:
kind: Server
name: backend-api
requiredAuthenticationRefs:
- name: allowed-clients
kind: MeshTLSAuthenticationPer-Route Authorization
Apply different policies to different routes.
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: admin-routes
namespace: production
spec:
parentRefs:
- name: api-server
kind: Server
group: policy.linkerd.io
rules:
- matches:
- path:
value: /admin
backendRefs:
- name: admin-backend
port: 8080
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: admin-only
namespace: production
spec:
targetRef:
kind: HTTPRoute
name: admin-routes
requiredAuthenticationRefs:
- name: admin-identity
kind: MeshTLSAuthentication
---
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
name: admin-identity
namespace: production
spec:
identities:
- "admin-gateway.production.serviceaccount.identity.linkerd.cluster.local"Network-Based Authentication
Allow traffic from specific networks (use sparingly, prefer identity).
apiVersion: policy.linkerd.io/v1alpha1
kind: NetworkAuthentication
metadata:
name: internal-network
namespace: production
spec:
networks:
- cidr: 10.0.0.0/8
- cidr: 192.168.0.0/16
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: allow-internal
namespace: production
spec:
targetRef:
kind: Server
name: backend-api
requiredAuthenticationRefs:
- name: internal-network
kind: NetworkAuthenticationDefault Deny Policy
Deny all traffic by default (zero-trust).
apiVersion: policy.linkerd.io/v1beta3
kind: Server
metadata:
name: backend-locked
namespace: production
spec:
podSelector:
matchLabels:
app: backend
port: 8080
# No authorization policies = default denyObservability Integration
mTLS Verification
Check mTLS status between services.
# View service connections and mTLS status
linkerd edges deployment/frontend -n production
# Output shows:
# SRC DST SECURED MSG/SEC
# frontend backend √ 10.2Live Traffic Observation
Tap live traffic for debugging.
# Tap all traffic to backend
linkerd tap deployment/backend -n production
# Tap specific route
linkerd tap deployment/backend -n production --path /api/users
# Tap with filtering
linkerd tap deployment/backend -n production \
--method GET \
--path /api/users \
--authority backend.production.svc.cluster.localService Statistics
View service metrics.
# Per-service metrics
linkerd stat deployment/backend -n production
# Per-route metrics (requires ServiceProfile)
linkerd routes deployment/backend -n production
# Output shows success rate, RPS, latencies (P50, P95, P99)Dashboard Access
Access Linkerd dashboard.
# Launch dashboard
linkerd dashboard
# Access specific namespace
linkerd dashboard -n production
# View service graph
linkerd viz dashboardPrometheus Integration
Linkerd exports metrics to Prometheus automatically.
Useful Queries:
# Request rate
sum(rate(request_total[1m])) by (dst_service)
# Success rate
sum(rate(request_total{classification="success"}[1m])) by (dst_service)
/ sum(rate(request_total[1m])) by (dst_service)
# P95 latency
histogram_quantile(0.95,
sum(rate(response_latency_ms_bucket[1m])) by (le, dst_service)
)Multi-Cluster Patterns
Multi-Cluster Setup
Link multiple clusters.
# Install Linkerd on cluster 1
linkerd install --cluster-domain cluster1.local | kubectl apply -f -
# Install Linkerd on cluster 2
linkerd install --cluster-domain cluster2.local | kubectl apply -f -
# Link clusters (from cluster 1)
linkerd multicluster link --cluster-name cluster2 | \
kubectl --context=cluster1 apply -f -
# Export service from cluster 2
kubectl --context=cluster2 label svc/backend \
mirror.linkerd.io/exported=true -n productionCross-Cluster Traffic Routing
Route traffic to services in remote clusters.
# Service is automatically mirrored with suffix
# backend-cluster2.production.svc.cluster1.local
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: multi-cluster-routing
namespace: production
spec:
parentRefs:
- name: frontend
rules:
# 80% local, 20% remote
- backendRefs:
- name: backend
port: 8080
weight: 80
- name: backend-cluster2
port: 8080
weight: 20Best Practices
HTTPRoute:
- Use Gateway API standard resources (future-proof)
- Leverage header modification for observability
- Keep route matching simple and explicit
- Use cross-namespace routing sparingly
ServiceProfile:
- Auto-generate from OpenAPI/Protobuf when possible
- Set timeouts based on actual performance
- Use retry budgets to prevent retry storms
- Mark mutations (POST, PUT, DELETE) as non-retryable
Authorization:
- Prefer identity-based over network-based policies
- Start with default-deny, add explicit allows
- Use Server resources for fine-grained control
- Apply policies at route level for sensitive operations
Observability:
- Use tap for real-time debugging (not production monitoring)
- Create ServiceProfiles for per-route metrics
- Integrate with Prometheus for alerting
- Monitor edges for mTLS status
Multi-Cluster:
- Use consistent naming across clusters
- Monitor cross-cluster latency
- Implement circuit breakers for remote calls
- Test failover scenarios regularly
Multi-Cluster Service Mesh
Table of Contents
Istio Multi-Cluster
Connect multiple Kubernetes clusters in a single mesh.
Architecture Models
Primary-Remote (Single Control Plane):
- One cluster hosts Istiod
- Remote clusters use primary's control plane
- Best for: Small deployments, cost optimization
Multi-Primary (Multiple Control Planes):
- Each cluster has its own Istiod
- Meshes communicate peer-to-peer
- Best for: High availability, isolation
Single Network Multi-Primary
Clusters share same network (pod IPs routable).
Install on Cluster 1:
# Set context
export CTX_CLUSTER1=cluster1
export CTX_CLUSTER2=cluster2
# Configure mesh ID and network
cat <<EOF > cluster1.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
values:
global:
meshID: mesh1
multiCluster:
clusterName: cluster1
network: network1
EOF
# Install
istioctl install --context="${CTX_CLUSTER1}" -f cluster1.yamlInstall on Cluster 2:
cat <<EOF > cluster2.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
values:
global:
meshID: mesh1
multiCluster:
clusterName: cluster2
network: network1
EOF
istioctl install --context="${CTX_CLUSTER2}" -f cluster2.yamlEnable Cross-Cluster Service Discovery:
# Create remote secret for cluster2 on cluster1
istioctl x create-remote-secret \
--context="${CTX_CLUSTER2}" \
--name=cluster2 | \
kubectl apply -f - --context="${CTX_CLUSTER1}"
# Create remote secret for cluster1 on cluster2
istioctl x create-remote-secret \
--context="${CTX_CLUSTER1}" \
--name=cluster1 | \
kubectl apply -f - --context="${CTX_CLUSTER2}"Multi-Network Multi-Primary
Clusters on different networks (requires gateways).
Install with East-West Gateway:
# Cluster 1
cat <<EOF > cluster1-multinetwork.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
values:
global:
meshID: mesh1
multiCluster:
clusterName: cluster1
network: network1
EOF
istioctl install --context="${CTX_CLUSTER1}" -f cluster1-multinetwork.yaml
# Install east-west gateway
samples/multicluster/gen-eastwest-gateway.sh \
--mesh mesh1 --cluster cluster1 --network network1 | \
istioctl --context="${CTX_CLUSTER1}" install -y -f -
# Expose services via east-west gateway
kubectl --context="${CTX_CLUSTER1}" apply -n istio-system -f \
samples/multicluster/expose-services.yamlCluster 2 (Same Process):
# Install Istio
cat <<EOF > cluster2-multinetwork.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
values:
global:
meshID: mesh1
multiCluster:
clusterName: cluster2
network: network2
EOF
istioctl install --context="${CTX_CLUSTER2}" -f cluster2-multinetwork.yaml
# Install east-west gateway
samples/multicluster/gen-eastwest-gateway.sh \
--mesh mesh1 --cluster cluster2 --network network2 | \
istioctl --context="${CTX_CLUSTER2}" install -y -f -
# Expose services
kubectl --context="${CTX_CLUSTER2}" apply -n istio-system -f \
samples/multicluster/expose-services.yamlExchange Secrets:
# Cluster2 secret on cluster1
istioctl x create-remote-secret \
--context="${CTX_CLUSTER2}" \
--name=cluster2 | \
kubectl apply -f - --context="${CTX_CLUSTER1}"
# Cluster1 secret on cluster2
istioctl x create-remote-secret \
--context="${CTX_CLUSTER1}" \
--name=cluster1 | \
kubectl apply -f - --context="${CTX_CLUSTER2}"Primary-Remote Setup
Remote cluster uses primary's control plane.
Primary Cluster:
cat <<EOF > cluster1-primary.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
values:
global:
meshID: mesh1
multiCluster:
clusterName: cluster1
network: network1
EOF
istioctl install --context="${CTX_CLUSTER1}" -f cluster1-primary.yamlRemote Cluster:
# Generate remote configuration
istioctl x create-remote-secret \
--context="${CTX_CLUSTER2}" \
--name=cluster2 | \
kubectl apply -f - --context="${CTX_CLUSTER1}"
# Install remote components
cat <<EOF > cluster2-remote.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
profile: remote
values:
global:
meshID: mesh1
multiCluster:
clusterName: cluster2
network: network2
remotePilotAddress: <CLUSTER1_INGRESS_GATEWAY_IP>
EOF
istioctl install --context="${CTX_CLUSTER2}" -f cluster2-remote.yamlVerify Multi-Cluster
# Check remote secrets
kubectl get secrets -n istio-system | grep istio-remote-secret
# Verify endpoints
istioctl proxy-config endpoints <POD_NAME> -n production | grep cluster
# Test cross-cluster connectivity
kubectl exec -n production <POD> -- curl http://service.namespace.svc.cluster.localLinkerd Multi-Cluster
Link multiple Linkerd clusters.
Setup Linkerd Multi-Cluster
Cluster 1:
# Install Linkerd
linkerd install --cluster-domain cluster1.local | \
kubectl --context=cluster1 apply -f -
# Install multicluster components
linkerd multicluster install --cluster-domain cluster1.local | \
kubectl --context=cluster1 apply -f -
# Check installation
linkerd --context=cluster1 check
linkerd --context=cluster1 multicluster checkCluster 2:
# Install Linkerd
linkerd install --cluster-domain cluster2.local | \
kubectl --context=cluster2 apply -f -
# Install multicluster components
linkerd multicluster install --cluster-domain cluster2.local | \
kubectl --context=cluster2 apply -f -
# Check
linkerd --context=cluster2 check
linkerd --context=cluster2 multicluster checkLink Clusters
From Cluster 1 to Cluster 2:
# Generate link
linkerd --context=cluster2 multicluster link --cluster-name cluster2 | \
kubectl --context=cluster1 apply -f -
# Verify link
linkerd --context=cluster1 multicluster check
# View linked clusters
linkerd --context=cluster1 multicluster gatewaysFrom Cluster 2 to Cluster 1:
linkerd --context=cluster1 multicluster link --cluster-name cluster1 | \
kubectl --context=cluster2 apply -f -Export Services
Export Service from Cluster 2:
# Label service for export
kubectl --context=cluster2 label svc/backend \
-n production \
mirror.linkerd.io/exported=true
# Service automatically appears in cluster1 as:
# backend-cluster2.production.svc.cluster1.localVerify Mirrored Service:
# Check mirrored service in cluster1
kubectl --context=cluster1 get svc -n production | grep cluster2
# Test connectivity
kubectl --context=cluster1 exec -n production <POD> -- \
curl http://backend-cluster2.production:8080Unlink Clusters
# Remove link
linkerd --context=cluster1 multicluster unlink --cluster-name cluster2 | \
kubectl delete -f -Cilium Cluster Mesh
Connect Cilium clusters at network layer.
Enable Cluster Mesh
Cluster 1:
# Install Cilium with unique cluster ID
helm install cilium cilium/cilium \
--namespace kube-system \
--set cluster.name=cluster1 \
--set cluster.id=1 \
--set ipam.mode=kubernetes
# Enable cluster mesh
cilium clustermesh enable --context cluster1Cluster 2:
helm install cilium cilium/cilium \
--namespace kube-system \
--set cluster.name=cluster2 \
--set cluster.id=2 \
--set ipam.mode=kubernetes
cilium clustermesh enable --context cluster2Connect Clusters
# Connect cluster1 to cluster2
cilium clustermesh connect \
--context cluster1 \
--destination-context cluster2
# Verify connection
cilium clustermesh status --context cluster1Global Services
Create Global Service:
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: production
annotations:
io.cilium/global-service: "true"
spec:
type: ClusterIP
ports:
- port: 8080
selector:
app: backendVerify Global Service:
# Check service endpoints across clusters
cilium service list | grep backendCross-Cluster Policy
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: cross-cluster-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
io.cilium.k8s.policy.cluster: cluster1
- matchLabels:
app: frontend
io.cilium.k8s.policy.cluster: cluster2Traffic Patterns
Locality-Based Routing (Istio)
Prefer local cluster, failover to remote.
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: backend-locality
spec:
host: backend.production.svc.cluster.local
trafficPolicy:
loadBalancer:
localityLbSetting:
enabled: true
distribute:
- from: us-east/us-east-1/*
to:
"us-east/us-east-1/*": 80
"us-west/us-west-1/*": 20
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30sCross-Cluster Load Balancing (Linkerd)
80/20 split between clusters:
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: backend-multi-cluster
namespace: production
spec:
parentRefs:
- name: backend
rules:
- backendRefs:
- name: backend # Local cluster
port: 8080
weight: 80
- name: backend-cluster2 # Remote cluster
port: 8080
weight: 20Active-Active Deployment
Deploy to both clusters, equal traffic.
# Istio
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend-active-active
spec:
hosts:
- backend
http:
- route:
- destination:
host: backend.production.svc.cluster.local
weight: 50
- destination:
host: backend.production.svc.cluster2.global
weight: 50Failover and HA
Automatic Failover (Istio)
Outlier detection for automatic failover.
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: backend-failover
spec:
host: backend
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 10
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
minHealthPercent: 20
loadBalancer:
localityLbSetting:
enabled: true
failover:
- from: us-east
to: us-westHealth-Based Routing
Route based on endpoint health.
apiVersion: v1
kind: Service
metadata:
name: backend
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "false"
spec:
selector:
app: backend
ports:
- port: 8080
---
apiVersion: v1
kind: Pod
metadata:
name: backend
spec:
containers:
- name: backend
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 3
periodSeconds: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 3
periodSeconds: 3Circuit Breaking for Remote Clusters
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: remote-circuit-breaker
spec:
host: backend.production.svc.cluster2.global
trafficPolicy:
connectionPool:
tcp:
maxConnections: 50
http:
http1MaxPendingRequests: 5
http2MaxRequests: 50
outlierDetection:
consecutiveErrors: 3
interval: 10s
baseEjectionTime: 30s
maxEjectionPercent: 100Disaster Recovery
Cross-Region Failover:
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: dr-failover
spec:
host: backend
trafficPolicy:
loadBalancer:
localityLbSetting:
enabled: true
failover:
- from: us-east
to: eu-west
- from: eu-west
to: us-east
outlierDetection:
consecutiveErrors: 5
interval: 30sBest Practices
Architecture:
- Use multi-primary for production (HA)
- Use primary-remote for cost optimization
- Ensure network connectivity between clusters
- Use unique cluster IDs and names
Service Discovery:
- Test cross-cluster DNS resolution
- Monitor remote secret sync
- Use explicit service FQDNs when needed
- Document service naming conventions
Security:
- Enable mTLS across clusters
- Use same root CA for trust
- Rotate remote secrets regularly
- Monitor cross-cluster auth failures
Performance:
- Prefer local endpoints (locality-based routing)
- Set connection limits for remote calls
- Use circuit breakers for failover
- Monitor cross-cluster latency
Resilience:
- Configure outlier detection
- Set appropriate failover priorities
- Test failover scenarios regularly
- Monitor endpoint health
Operations:
- Automate cluster linking
- Monitor multi-cluster metrics
- Set up cross-cluster alerts
- Document runbooks for failures
Progressive Delivery Patterns
Table of Contents
Canary Deployments
Gradually shift traffic to new version while monitoring metrics.
Manual Canary (Istio)
Stage 1: Deploy v2 with 0% Traffic
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-v2
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: backend
version: v2
template:
metadata:
labels:
app: backend
version: v2
spec:
containers:
- name: backend
image: backend:v2
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: backend
spec:
host: backend
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend-canary
spec:
hosts:
- backend
http:
- route:
- destination:
host: backend
subset: v1
weight: 100
- destination:
host: backend
subset: v2
weight: 0Stage 2: Route 10% to v2
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend-canary
namespace: production
spec:
hosts:
- backend
http:
- route:
- destination:
host: backend
subset: v1
weight: 90
- destination:
host: backend
subset: v2
weight: 10
EOFStage 3: Progressive Increase
# Monitor metrics, then increase
# 10% → 25% → 50% → 75% → 100%
# 25%
kubectl patch vs backend-canary -n production --type merge -p '
{
"spec": {
"http": [{
"route": [
{"destination": {"host": "backend", "subset": "v1"}, "weight": 75},
{"destination": {"host": "backend", "subset": "v2"}, "weight": 25}
]
}]
}
}'
# 50%
kubectl patch vs backend-canary -n production --type merge -p '
{
"spec": {
"http": [{
"route": [
{"destination": {"host": "backend", "subset": "v1"}, "weight": 50},
{"destination": {"host": "backend", "subset": "v2"}, "weight": 50}
]
}]
}
}'
# 100%
kubectl patch vs backend-canary -n production --type merge -p '
{
"spec": {
"http": [{
"route": [
{"destination": {"host": "backend", "subset": "v2"}, "weight": 100}
]
}]
}
}'Stage 4: Cleanup
# Delete v1 deployment
kubectl delete deployment backend-v1 -n production
# Update VirtualService to simple routing
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend
namespace: production
spec:
hosts:
- backend
http:
- route:
- destination:
host: backend
EOFManual Canary (Linkerd)
Traffic Split Configuration:
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: backend-canary
namespace: production
spec:
parentRefs:
- name: backend
kind: Service
rules:
- backendRefs:
- name: backend-v1
port: 8080
weight: 90
- name: backend-v2
port: 8080
weight: 10Update Weights:
# Increase to 25%
kubectl patch httproute backend-canary -n production --type merge -p '
{
"spec": {
"rules": [{
"backendRefs": [
{"name": "backend-v1", "port": 8080, "weight": 75},
{"name": "backend-v2", "port": 8080, "weight": 25}
]
}]
}
}'Canary with Header-Based Routing
Test canary with internal users first.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend-canary-staged
spec:
hosts:
- backend
http:
# Internal testers always see canary
- match:
- headers:
x-canary-user:
exact: "true"
route:
- destination:
host: backend
subset: v2
# Production: gradual rollout
- route:
- destination:
host: backend
subset: v1
weight: 90
- destination:
host: backend
subset: v2
weight: 10Monitoring During Canary
Key Metrics to Watch:
# Error rate comparison
sum(rate(http_requests_total{code=~"5..", version="v2"}[5m]))
/ sum(rate(http_requests_total{version="v2"}[5m]))
# Latency P95 comparison
histogram_quantile(0.95,
sum(rate(http_request_duration_seconds_bucket{version="v2"}[5m])) by (le)
)
# Request rate
sum(rate(http_requests_total{version="v2"}[5m]))Alert on Issues:
# Prometheus alert
- alert: CanaryHighErrorRate
expr: |
sum(rate(http_requests_total{code=~"5..", version="v2"}[5m]))
/ sum(rate(http_requests_total{version="v2"}[5m])) > 0.01
for: 5m
annotations:
summary: "Canary v2 error rate above 1%"Blue/Green Deployments
Instant traffic cutover between versions.
Blue/Green (Linkerd)
Stage 1: Deploy Green Alongside Blue
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-blue
spec:
replicas: 3
selector:
matchLabels:
app: backend
version: blue
template:
metadata:
labels:
app: backend
version: blue
spec:
containers:
- name: backend
image: backend:blue
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-green
spec:
replicas: 3
selector:
matchLabels:
app: backend
version: green
template:
metadata:
labels:
app: backend
version: green
spec:
containers:
- name: backend
image: backend:green
---
apiVersion: v1
kind: Service
metadata:
name: backend-blue
spec:
selector:
app: backend
version: blue
ports:
- port: 8080
---
apiVersion: v1
kind: Service
metadata:
name: backend-green
spec:
selector:
app: backend
version: green
ports:
- port: 8080Stage 2: Test Green with Subset
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: backend-bluegreen-test
spec:
parentRefs:
- name: backend
rules:
# Test traffic: route to green
- matches:
- headers:
- name: x-version
value: green
backendRefs:
- name: backend-green
port: 8080
# Production traffic: route to blue
- backendRefs:
- name: backend-blue
port: 8080Stage 3: Instant Cutover to Green
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: backend-cutover
spec:
parentRefs:
- name: backend
rules:
- backendRefs:
- name: backend-green
port: 8080Stage 4: Rollback if Needed
# Instant rollback to blue
kubectl apply -f - <<EOF
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
name: backend-rollback
namespace: production
spec:
parentRefs:
- name: backend
rules:
- backendRefs:
- name: backend-blue
port: 8080
EOFBlue/Green (Istio)
Cutover Configuration:
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend-bluegreen
spec:
hosts:
- backend
http:
- route:
- destination:
host: backend-green.production.svc.cluster.localRollback:
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend-rollback
spec:
hosts:
- backend
http:
- route:
- destination:
host: backend-blue.production.svc.cluster.localA/B Testing
Route traffic based on user segments.
Cookie-Based A/B Test (Istio)
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: frontend-ab-test
spec:
hosts:
- frontend
http:
# Variant A: existing experience
- match:
- headers:
cookie:
regex: "^(.*?;)?(ab-test=a)(;.*)?$"
route:
- destination:
host: frontend
subset: variant-a
# Variant B: new experience
- match:
- headers:
cookie:
regex: "^(.*?;)?(ab-test=b)(;.*)?$"
route:
- destination:
host: frontend
subset: variant-b
# No cookie: 50/50 split
- route:
- destination:
host: frontend
subset: variant-a
weight: 50
headers:
response:
set:
Set-Cookie: "ab-test=a; Max-Age=86400"
- destination:
host: frontend
subset: variant-b
weight: 50
headers:
response:
set:
Set-Cookie: "ab-test=b; Max-Age=86400"User-Agent Based Routing
Route mobile users differently.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: mobile-routing
spec:
hosts:
- api
http:
- match:
- headers:
user-agent:
regex: ".*(Mobile|Android|iPhone).*"
route:
- destination:
host: api
subset: mobile-optimized
- route:
- destination:
host: api
subset: desktopGeographic Routing
Route based on user location (requires geo headers).
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: geo-routing
spec:
hosts:
- api
http:
- match:
- headers:
x-user-region:
exact: "us-east"
route:
- destination:
host: api-us-east.production.svc.cluster.local
- match:
- headers:
x-user-region:
exact: "eu-west"
route:
- destination:
host: api-eu-west.production.svc.cluster.localAutomated Rollback
Automatically revert on metric failures.
Prometheus-Based Alerts
apiVersion: v1
kind: ConfigMap
metadata:
name: canary-alerts
data:
alerts.yaml: |
groups:
- name: canary
interval: 30s
rules:
# High error rate
- alert: CanaryHighErrors
expr: |
sum(rate(http_requests_total{code=~"5..", version="v2"}[5m]))
/ sum(rate(http_requests_total{version="v2"}[5m])) > 0.01
for: 2m
annotations:
summary: "Canary error rate > 1%"
# High latency
- alert: CanaryHighLatency
expr: |
histogram_quantile(0.95,
sum(rate(http_request_duration_seconds_bucket{version="v2"}[5m])) by (le)
) > 0.5
for: 2m
annotations:
summary: "Canary P95 latency > 500ms"Rollback Script
#!/bin/bash
# rollback-canary.sh
NAMESPACE="production"
SERVICE="backend"
echo "Rolling back canary deployment..."
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: ${SERVICE}-canary
namespace: ${NAMESPACE}
spec:
hosts:
- ${SERVICE}
http:
- route:
- destination:
host: ${SERVICE}
subset: v1
weight: 100
EOF
echo "Rollback complete. All traffic to v1."Flagger Integration
Automated progressive delivery with Flagger.
Install Flagger
# Add Flagger Helm repository
helm repo add flagger https://flagger.app
# Install Flagger for Istio
helm install flagger flagger/flagger \
--namespace istio-system \
--set meshProvider=istio \
--set metricsServer=http://prometheus:9090
# Install Flagger for Linkerd
helm install flagger flagger/flagger \
--namespace linkerd \
--set meshProvider=linkerd \
--set metricsServer=http://prometheus:9090Canary with Flagger (Istio)
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: backend
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
service:
port: 8080
analysis:
interval: 1m
threshold: 5
maxWeight: 50
stepWeight: 10
metrics:
# Success rate must be > 99%
- name: request-success-rate
thresholdRange:
min: 99
interval: 1m
# P95 latency must be < 500ms
- name: request-duration
thresholdRange:
max: 500
interval: 1m
webhooks:
# Pre-rollout checks
- name: pre-rollout
type: pre-rollout
url: http://flagger-loadtester/
timeout: 15s
metadata:
type: bash
cmd: "curl -sd 'test' http://backend-canary:8080/healthz"
# Load testing during rollout
- name: load-test
url: http://flagger-loadtester/
timeout: 5s
metadata:
cmd: "hey -z 1m -q 10 -c 2 http://backend-canary.production:8080/"Canary with Flagger (Linkerd)
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: backend
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
service:
port: 8080
analysis:
interval: 1m
threshold: 5
maxWeight: 50
stepWeight: 10
metrics:
- name: request-success-rate
thresholdRange:
min: 99
interval: 1m
- name: request-duration
thresholdRange:
max: 500
interval: 1mA/B Testing with Flagger
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: frontend-ab
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: frontend
service:
port: 80
analysis:
interval: 1m
iterations: 10
match:
- headers:
x-user-type:
exact: "beta"
metrics:
- name: request-success-rate
thresholdRange:
min: 99Blue/Green with Flagger
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: backend-bluegreen
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
service:
port: 8080
analysis:
interval: 1m
threshold: 10
iterations: 2
maxWeight: 100
stepWeight: 100
metrics:
- name: request-success-rate
thresholdRange:
min: 99Monitor Flagger
# Watch canary progress
kubectl -n production get canaries --watch
# Describe canary status
kubectl -n production describe canary backend
# View Flagger events
kubectl -n production get events --sort-by='.lastTimestamp'Best Practices
Canary Deployments:
- Start with small traffic percentages (5-10%)
- Monitor key metrics: error rate, latency, throughput
- Increase traffic gradually (10% → 25% → 50% → 100%)
- Wait for stabilization between stages
- Set clear rollback criteria
Blue/Green:
- Test green environment thoroughly before cutover
- Use header-based routing for pre-production validation
- Keep blue environment running for quick rollback
- Monitor metrics after cutover
- Automate cutover and rollback procedures
A/B Testing:
- Use consistent user assignment (cookies, headers)
- Define success metrics before test
- Ensure statistical significance
- Isolate test variables
- Document test results
Automated Rollback:
- Define clear success criteria
- Use multiple metrics (error rate, latency, throughput)
- Set appropriate thresholds
- Implement alerts for failures
- Test rollback procedures regularly
Flagger:
- Use load testing webhooks for realistic traffic
- Set appropriate thresholds based on SLOs
- Monitor Flagger events for debugging
- Integrate with alerting systems
- Test analysis configuration in staging first
Related skills
FAQ
Which service mesh should I choose?
The skill recommends Istio Ambient for most cases (8% latency overhead with mTLS), Linkerd for simplicity (33% overhead), and Cilium for eBPF-native infrastructure.
How does mTLS work in the mesh?
The mesh provides automatic encryption and certificate rotation with zero app changes, in STRICT (reject plaintext) or PERMISSIVE modes.