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

DimensionSidecar ModeAmbient Mode
MaturityProduction-grade, large-scale validationSingle-cluster GA, multi-cluster Beta
Resource OverheadHigh (one Envoy per Pod)Low (one ztunnel per node)
L7 FeaturesFull by defaultRequires waypoint deployment
Pod IntrusivenessRequires Sidecar injectionNon-intrusive
Upgrade ImpactRequires Pod restartNo Pod restart needed
Best ForExisting Sidecar architectureNew 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+
  • kubectl configured 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:

MetricTypeMeaning
istio_requests_totalCounterTotal requests (grouped by method/status/service)
istio_request_duration_millisecondsHistogramRequest latency distribution
istio_request_bytesHistogramRequest body size distribution
istio_response_bytesHistogramResponse body size distribution
istio_tcp_connections_opened_totalCounterTotal TCP connections opened
istio_tcp_connections_closed_totalCounterTotal 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

ComponentCPU RequestMemory RequestScale
Istiod500m2GBPer 1000 Pods
Ingress Gateway500m512MBPer 1000 RPS
Envoy Sidecar100m128MBPer Pod
ztunnel (Ambient)200m256MBPer 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:

  1. Start with one edge service joining Istio, validate basic functionality
  2. Gradually expand scope, running stability tests for each newly onboarded service
  3. mTLS: PERMISSIVE first, then STRICT—switch to strict mode only after confirming all services support encrypted communication
  4. 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:

  1. Sidecar or ambient? | Istio — Istio official documentation, introduces the differences between Sidecar and Ambient modes and selection guidance
  2. Istio Official Blog — Istio project updates, including 2026 Steering Committee election, Ambient multi-cluster Beta, and more
  3. Istio Introduces Multi-Cluster, Ambient Mode, and Inference Features — Tencent Cloud Developer Community, covers Istio Ambient multi-cluster support and Gateway API Inference Extension
  4. Service Mesh Introduction: Service Communication Infrastructure Revolution under Kubernetes — Analyzes Service Mesh control plane and data plane architecture, and Envoy vs Linkerd comparison
  5. Istio-Tutorial Complete Getting Started — Complete steps from environment setup to service deployment, including Sidecar proxy mechanism analysis
  6. Java Programmer Microservices and Service Mesh Integration — Detailed introduction to Istio installation, traffic governance strategies, and security mechanisms in Kubernetes