Overview
Let’s answer the most fundamental question first: what does a Service Mesh do?
In one sentence: it handles the messy communication stuff between microservices for you.
In a microservices architecture, when service A calls service B, what looks like a simple HTTP request actually involves a bunch of concerns: what if it times out? How many retries? Should we circuit break? How do we do canary traffic? Certificate management? Distributed tracing?
The traditional approach is for each service to handle these itself—Java uses Spring Cloud, Go uses go-kit, Python uses various libraries. The problem is that different languages each do their own thing, upgrading an SDK means recompiling and redeploying everything, and ops has no way to manage it uniformly.
Service Mesh strips these communication concerns out of business code and puts them in an independent proxy layer (Sidecar or node-level proxy). Business code just sends HTTP requests; the proxy handles retries, circuit breaking, encryption, and tracing. Developers are happy, ops are happy.
Istio is the most mainstream implementation in the Service Mesh space, jointly developed by Google, IBM, and Lyft, open-sourced in 2017, and now the second most prominent CNCF project after Kubernetes. This article walks you through Istio from zero, covering architecture principles, installation, traffic management, security policies, and observability.
Architecture Overview: Control Plane and Data Plane
Istio’s architecture is clean, split into two parts:
- Control Plane: Istiod, responsible for managing and configuring data plane proxies. Think of it as the “brain”
- Data Plane: A set of proxies that intercept and handle all network communication between microservices. Think of it as the “hands and feet”
The data plane has two modes—this is Istio’s most fundamental design choice.
Sidecar Mode: The Classic Approach
Sidecar mode has been around since Istio 1.0 and is the most mature approach. An Envoy proxy container is injected into every Pod, and all traffic in and out of that Pod goes through Envoy first.
┌─────────────────────────────────┐
│ Pod │
│ ┌───────────┐ ┌─────────────┐ │
│ │ App │←→│ Envoy │ │
│ │ Container │ │ Sidecar │ │
│ └───────────┘ └─────────────┘ │
└─────────────────────────────────┘
↑ ↓
Inbound Outbound
Advantages:
- Mature and stable, battle-tested at large scale in production
- Full L4 + L7 feature support (load balancing, routing, circuit breaking, retries, etc.)
- Pod-level granular traffic control
Disadvantages:
- Extra container per Pod, high resource overhead (Envoy defaults to 100-200MB memory)
- Sidecar injection requires Pod restart
- Sidecar upgrades affect business workloads
Ambient Mode: The New Sidecarless Approach
Ambient mode is a new architecture introduced by Istio in 2022, production-ready for single-cluster use cases since version 1.22. The key change: instead of injecting a Sidecar into every Pod, a ztunnel proxy (a lightweight L4 proxy written in Rust) runs on each node, and all node traffic goes through it.
┌──────────────────────────────┐
│ Node │
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ Pod A │ │ Pod B │ │
│ │ (App) │ │ (App) │ │
│ └────┬────┘ └────┬────┘ │
│ │ │ │
│ ┌────┴────────────┴────┐ │
│ │ ztunnel (L4) │ │
│ │ per-node proxy │ │
│ └──────────────────────┘ │
│ │
│ ┌──────────────────────┐ │
│ │ waypoint (L7, opt.) │ │
│ │ per-namespace Envoy │ │
│ └──────────────────────┘ │
└──────────────────────────────┘
When L7 features are needed (like HTTP routing, content-level policies), a waypoint Envoy proxy can optionally be deployed at the namespace level.
Advantages:
- Low resource overhead, non-intrusive to Pods
- Join the mesh without restarting Pods
- L4 security (mTLS) covers the entire cluster at zero cost
- Enable L7 on demand—don’t pay Envoy overhead for services that don’t need it
Disadvantages:
- Relatively new, less production validation than Sidecar mode
- Some L7 features depend on waypoint, adding an architectural layer
- Multi-cluster support only reached Beta in 1.29
How to Choose
| Dimension | Sidecar Mode | Ambient Mode |
|---|---|---|
| Maturity | Production-grade, large-scale validation | Single-cluster GA, multi-cluster Beta |
| Resource Overhead | High (one Envoy per Pod) | Low (one ztunnel per node) |
| L7 Features | Full by default | Requires waypoint deployment |
| Pod Intrusiveness | Requires Sidecar injection | Non-intrusive |
| Upgrade Impact | Requires Pod restart | No Pod restart needed |
| Best For | Existing Sidecar architecture | New clusters, or L4-only security scenarios |
My recommendation: go Ambient for new clusters. If you only need mTLS and basic traffic management, Ambient’s ztunnel is sufficient and saves significant resources. Deploy waypoints only for namespaces that need L7 features. For existing Sidecar clusters, follow Istio’s official migration guide to transition gradually.
Installation: From Scratch
Prerequisites
- Kubernetes 1.28+
kubectlconfigured with cluster access- At least 4 CPU cores, 8GB RAM cluster resources
Install istioctl
# Download the latest istioctl
curl -L https://istio.io/downloadIstio | sh -
# Enter the extracted directory
cd istio-*
# Add istioctl to PATH
export PATH=$PWD/bin:$PATH
# Verify installation
istioctl version
Install Istio (Sidecar Mode)
# Install using default profile (good for getting started)
istioctl install --set profile=demo -y
# Verify installation
istioctl verify-install
The demo profile includes Istiod, Ingress Gateway, and Egress Gateway—suitable for learning and testing. For production, use the default profile or customize with Helm.
Install Istio (Ambient Mode)
# Ambient mode installation
istioctl install --set profile=ambient -y
# Verify
kubectl get pods -n istio-system
# Should see istiod and ztunnel
Deploy Sample Application
Istio provides the Bookinfo sample application, consisting of four microservices, to demonstrate various traffic management features:
# Deploy Bookinfo
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
# Inject Sidecar (Sidecar mode)
kubectl label namespace default istio-injection=enabled
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
# Or enable mesh in Ambient mode
kubectl label namespace default istio.io/dataplane-mode=ambient
# Verify services are running
kubectl get services
kubectl get pods
Expose Service Externally
# Apply Ingress Gateway configuration
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
# Get Ingress Gateway external IP
kubectl get svc istio-ingressgateway -n istio-system
# Access the application
export GATEWAY_URL=$(kubectl -n istio-system get svc istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl -s "http://$GATEWAY_URL/productpage" | grep -o "<title>.*</title>"
Traffic Management: Istio’s Core Capability
VirtualService: Traffic Routing
VirtualService defines how traffic is routed. For example, canary deployment—90% traffic to v1, 10% to v2:
# virtual-service-canary.yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 90
- destination:
host: reviews
subset: v2
weight: 10
Paired with DestinationRule to define subsets:
# destination-rule-subsets.yaml
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
The effect: when users access the reviews service, 90% of requests go to v1 and 10% to v2. No business code changes needed—pure YAML-driven canary deployment.
Timeouts and Retries
Microservice timeout and retry strategies used to require code; now a VirtualService config handles it:
# virtual-service-timeout-retry.yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
timeout: 3s # Request timeout 3 seconds
retries:
attempts: 3 # Max 3 retries
perTryTimeout: 1s # Per-retry timeout 1 second
retryOn: 5xx,reset,connect-failure # When to retry
Here’s a pitfall to avoid: more retries isn’t better. If a service is already overloaded, retries amplify traffic (retry storm) and can take it down completely. Keep attempts at 3 or below, and always pair with circuit breaking.
Circuit Breaking
Circuit breaking means: when a service instance errors too much, temporarily stop sending requests to it, give it a breather. In Istio, this is configured via DestinationRule:
# destination-rule-circuit-breaker.yaml
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 5 # 5 consecutive 5xx errors
interval: 30s # Detection interval
baseEjectionTime: 30s # Ejection duration
maxEjectionPercent: 50 # Eject at most 50% of instances
connectionPool:
tcp:
maxConnections: 100 # Max connections
http:
http1MaxPendingRequests: 50 # Max pending requests
maxRequestsPerConnection: 10 # Max requests per connection
outlierDetection does passive health checking—when an instance returns 5xx errors consecutively beyond a threshold, it gets kicked out of the load balancing pool for 30 seconds. After 30 seconds, it’s tried again; if it still errors, it gets kicked again. That’s “circuit breaking.”
Fault Injection
Istio can actively inject faults to test system resilience. This isn’t destruction—it’s chaos engineering. Finding issues before they blow up in production is always better:
# virtual-service-fault-injection.yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: "test-user"
fault:
delay:
percentage:
value: 100.0
fixedDelay: 7s # Inject 7 second delay
route:
- destination:
host: reviews
subset: v1
- route:
- destination:
host: reviews
subset: v1
This config injects a 7-second delay for test-user requests to test whether timeout configurations work. Regular users are unaffected.
Security Policies: mTLS and Authorization
Automatic mTLS
Istio’s most effortless security feature is automatic mTLS (mutual TLS encryption). Communication within the service mesh is encrypted by default, with zero business code changes.
In Sidecar mode, mTLS defaults to PERMISSIVE mode (accepting both encrypted and plaintext), making gradual migration easy. Once all services are in the mesh, switch to STRICT:
# peer-authentication-strict.yaml
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICT
In Ambient mode, mTLS is handled automatically by ztunnel at the L4 layer—all mesh traffic is encrypted by default, no configuration needed.
Authorization Policies
mTLS solves “encrypting communication”; authorization policies solve “who can access whom”:
# authorization-policy.yaml
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: productpage-viewer
namespace: default
spec:
selector:
matchLabels:
app: productpage
action: ALLOW
rules:
# Rule 1: Allow access from istio-ingressgateway
- from:
- source:
namespaces: ["istio-system"]
to:
- operation:
methods: ["GET"]
paths: ["/productpage"]
This policy means: only GET /productpage requests from the istio-system namespace can access the productpage service; everything else is denied.
In Ambient mode, L4 authorization policies are executed directly by ztunnel, while L7 authorization policies require a waypoint:
# L7 authorization policy in Ambient mode
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: http-headers-check
namespace: default
spec:
targetRefs:
- kind: Gateway
group: gateway.networking.k8s.io
name: waypoint
action: DENY
rules:
- to:
- operation:
paths: ["/admin/*"]
when:
- key: request.headers[x-user-role]
notValues: ["admin"] # Deny non-admin users access to /admin
Observability: Metrics, Logs, Tracing
Istio automatically generates observability data for all services in the mesh, with no business code changes required.
Metrics
Istio’s default exposed metrics include:
| Metric | Type | Meaning |
|---|---|---|
istio_requests_total | Counter | Total requests (grouped by method/status/service) |
istio_request_duration_milliseconds | Histogram | Request latency distribution |
istio_request_bytes | Histogram | Request body size distribution |
istio_response_bytes | Histogram | Response body size distribution |
istio_tcp_connections_opened_total | Counter | Total TCP connections opened |
istio_tcp_connections_closed_total | Counter | Total TCP connections closed |
Works out of the box with Prometheus + Grafana:
# Deploy Prometheus and Grafana (using Istio's built-in addons)
kubectl apply -f samples/addons/prometheus.yaml
kubectl apply -f samples/addons/grafana.yaml
kubectl apply -f samples/addons/kiali.yaml
# Port forward to access Grafana
kubectl port-forward svc/grafana 3000:3000 -n istio-system
Distributed Tracing
Istio automatically generates trace spans for requests. Connect Jaeger or Zipkin to see the complete call chain:
# Deploy Jaeger
kubectl apply -f samples/addons/jaeger.yaml
# Port forward to access
kubectl port-forward svc/tracing 16686:16686 -n istio-system
Open Jaeger UI, select service productpage, and you can see the complete call chain across the four bookinfo services. Which step is slow, where errors occur—it’s all visible.
Kiali: Mesh Visualization
Kiali is Istio’s visualization tool, showing service topology, traffic flow, and health status:
# Port forward to access Kiali
kubectl port-forward svc/kiali 20001:20001 -n istio-system
Kiali’s service topology graph is a troubleshooting weapon—any red-marked service link indicates errors on that path. Click through for details and pinpoint which Pod is causing the problem.
Production Practice Recommendations
Resource Planning
| Component | CPU Request | Memory Request | Scale |
|---|---|---|---|
| Istiod | 500m | 2GB | Per 1000 Pods |
| Ingress Gateway | 500m | 512MB | Per 1000 RPS |
| Envoy Sidecar | 100m | 128MB | Per Pod |
| ztunnel (Ambient) | 200m | 256MB | Per node |
Common Pitfalls
Pitfall 1: Sidecar injection failure
Check namespace labels:
# Sidecar mode
kubectl label namespace default istio-injection=enabled
# Ambient mode
kubectl label namespace default istio.io/dataplane-mode=ambient
If Pods were created before labeling, they need to be manually restarted for injection.
Pitfall 2: 503 errors, services can’t communicate
Likely a DestinationRule subset mismatch with actual Pod labels. Check:
# Check Pod labels
kubectl get pods --show-labels
# Confirm DestinationRule subset labels match Pods
Pitfall 3: L7 policies not working in Ambient mode
Ambient mode’s ztunnel only handles L4. L7 policies require a waypoint:
# Deploy waypoint in namespace
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: waypoint
namespace: default
labels:
istio.io/waypoint-for: service
spec:
gatewayClassName: istio-waypoint
listeners:
- name: mesh
port: 15008
protocol: HBONE
EOF
Migration Recommendations
If you already have a Spring Cloud or Dubbo microservices system, don’t switch everything at once. Recommended gradual migration:
- Start with one edge service joining Istio, validate basic functionality
- Gradually expand scope, running stability tests for each newly onboarded service
- mTLS: PERMISSIVE first, then STRICT—switch to strict mode only after confirming all services support encrypted communication
- Traffic management: take over gradually—start with observability only (read-only), then switch to traffic management
Summary
Service Mesh isn’t a silver bullet, but it genuinely solves the core pain points of microservice communication management. Istio, as the most mature open-source solution in this space, is worth the investment to learn.
A few core takeaways:
On architecture choice, Ambient mode is the new direction. Sidecar’s resource overhead and operational complexity are real burdens at large scale. Ambient’s ztunnel + waypoint layered design is more sensible. But if you’re already on Sidecar, don’t rush to switch—Sidecar mode has more complete L7 features, and Ambient’s waypoint still has limitations in some scenarios.
Traffic management is the first feature you’ll actually use. Canary deployment, timeout retries, circuit breaking—things that used to require code or middleware are now a few YAML files. But remember: retries aren’t better in higher numbers, and circuit breaking thresholds should be set based on actual capacity.
Security starts with mTLS. Automatic mTLS is a zero-cost security upgrade—you get it just by joining the mesh. For authorization policies, start with a whitelist (ALLOW) approach, then consider DENY policies after confirming no false positives.
Observability is a passive benefit. No code changes needed—Istio gives you metrics, logs, and traces automatically. Once you set up Prometheus + Grafana + Kiali + Jaeger, you’ll discover problems you never knew existed—this is both a blessing and a challenge, because you’ll see a lot of “dirty data” that was previously hidden.
One last thing: Istio has a steep learning curve. Don’t expect to master it in a day. Start with the demo, get the basic flow working, then practice in production. Running into issues is normal—the key is having observability data to help you pinpoint them when they happen.
References & Acknowledgments
The following resources were referenced during the writing of this article. Thanks to the original authors for their contributions:
- Sidecar or ambient? | Istio — Istio official documentation, introduces the differences between Sidecar and Ambient modes and selection guidance
- Istio Official Blog — Istio project updates, including 2026 Steering Committee election, Ambient multi-cluster Beta, and more
- Istio Introduces Multi-Cluster, Ambient Mode, and Inference Features — Tencent Cloud Developer Community, covers Istio Ambient multi-cluster support and Gateway API Inference Extension
- Service Mesh Introduction: Service Communication Infrastructure Revolution under Kubernetes — Analyzes Service Mesh control plane and data plane architecture, and Envoy vs Linkerd comparison
- Istio-Tutorial Complete Getting Started — Complete steps from environment setup to service deployment, including Sidecar proxy mechanism analysis
- Java Programmer Microservices and Service Mesh Integration — Detailed introduction to Istio installation, traffic governance strategies, and security mechanisms in Kubernetes