Istio: Service mesh for Kubernetes microservices
Open-source service mesh platform that provides traffic management, security, and observability for microservices. With 37K+ GitHub stars, Istio uses Envoy proxy sidecars to connect, secure, control, and observe services without modifying application code.
- Step 1
What is Istio?
Istio is an open-source service mesh platform designed to connect, secure, control, and observe microservices running in Kubernetes and other platforms. With over 37,000 GitHub stars and backing from Google, IBM, and the Cloud Native Computing Foundation (CNCF), Istio has become the de facto standard for service mesh implementations in cloud-native environments.
A service mesh is an infrastructure layer that handles service-to-service communication, providing features like traffic management, security, and observability without requiring changes to application code. Istio achieves this by injecting an Envoy proxy sidecar alongside each microservice, creating a data plane that intercepts all network traffic. The control plane (Istiod) manages these proxies, providing centralized configuration and policy enforcement.
Key capabilities include intelligent traffic routing (blue/green deployments, canary releases, A/B testing), automatic mutual TLS (mTLS) encryption between services, fine-grained access control, distributed tracing, metrics collection, circuit breaking, fault injection for chaos engineering, and request retries with timeouts. Istio abstracts these complex networking concerns from developers, allowing them to focus on business logic while operations teams manage traffic behavior, security policies, and observability at the infrastructure layer.
- Step 2
Technology stack
Istio is built on a modern cloud-native architecture combining Go, C++, and Kubernetes-native patterns. The platform employs a two-plane design separating control logic from data flow.
Control Plane (Istiod):
- Written in Go for high performance and Kubernetes integration
- Single binary consolidating Pilot (traffic management), Citadel (security), and Galley (configuration)
- Service discovery abstraction across platforms (Kubernetes, VMs, Consul)
- Certificate Authority (CA) for automated mTLS certificate generation and rotation
- Configuration distribution via xDS (Envoy Discovery Service) APIs
- Policy enforcement and telemetry collection coordination
Data Plane (Envoy Proxy):
- High-performance proxy written in C++ by Lyft, now a CNCF graduated project
- Deployed as sidecar containers alongside application pods
- Dynamic service discovery and load balancing
- HTTP/1.1, HTTP/2, gRPC, WebSocket, and TCP protocol support
- TLS termination and origination with SNI routing
- Circuit breakers, health checks, and outlier detection
- Observability with metrics (Prometheus format), distributed tracing (Jaeger, Zipkin), and access logs
- WebAssembly (WASM) extension support for custom logic
Configuration APIs:
- Custom Resource Definitions (CRDs) for Kubernetes-native configuration
- Gateway API support (Kubernetes standard for L4/L7 routing)
- VirtualService, DestinationRule, Gateway, ServiceEntry, and more
- Declarative YAML-based policy definitions
Integration Ecosystem:
- Prometheus for metrics scraping and storage
- Grafana for visualization dashboards
- Jaeger or Zipkin for distributed tracing
- Kiali for service mesh topology visualization
- Open Policy Agent (OPA) for advanced authorization
Istio runs on any Kubernetes distribution (EKS, GKE, AKS, OpenShift, Rancher) and also supports virtual machines and bare metal through workload entries.
Control Plane: ├── Istiod (Go) │ ├── Pilot (traffic management) │ ├── Citadel (security/CA) │ └── Galley (configuration) ├── xDS APIs (Envoy config) └── Service Discovery Data Plane: ├── Envoy Proxy (C++) │ ├── L4/L7 load balancing │ ├── TLS termination │ ├── Circuit breaking │ ├── Health checks │ └── Telemetry collection └── WASM extensions Configuration: ├── Kubernetes CRDs ├── Gateway API └── Istio APIs ├── VirtualService ├── DestinationRule ├── Gateway ├── ServiceEntry └── AuthorizationPolicy Observability: ├── Prometheus (metrics) ├── Grafana (dashboards) ├── Jaeger/Zipkin (tracing) └── Kiali (topology) - Step 3
Prerequisites
Before installing Istio, ensure you have a working Kubernetes environment and the necessary tools.
Kubernetes Cluster:
- Kubernetes version 1.25 or later (1.28+ recommended for production)
- Minimum 4 vCPUs and 8GB RAM for testing (more for production workloads)
- kubectl configured to communicate with your cluster
- Admin access to install cluster-scoped resources (CRDs, ClusterRoles)
Supported Platforms:
- Cloud: Amazon EKS, Google GKE, Azure AKS, IBM Cloud, Alibaba Cloud, Oracle Cloud
- Self-managed: kubeadm, kops, Rancher, OpenShift, Tanzu
- Local development: kind, minikube, Docker Desktop, k3d, MicroK8s
Local Testing Options: For evaluating Istio locally, kind (Kubernetes in Docker) provides the most production-like environment:
kind create cluster --name istio-testAlternatively, use minikube with sufficient resources:
minikube start --cpus=4 --memory=8192Network Requirements:
- Outbound internet access for downloading Istio images and components
- If using LoadBalancer services, ensure your cluster has a load balancer provisioner (MetalLB for on-prem, cloud provider integrations for managed Kubernetes)
kubectl Access: Verify cluster access before proceeding:
kubectl cluster-info kubectl get nodesYou should see your cluster API server endpoint and healthy nodes.
- Step 4
Installation: Using istioctl (Recommended)
The istioctl command-line tool provides the simplest and most flexible way to install and manage Istio. It supports multiple installation profiles optimized for different use cases.
Step 1: Download Istio
The downloadIstio script automatically fetches the latest release for your OS:
curl -L https://istio.io/downloadIstio | sh -This creates a directory like
istio-1.30.0containing:bin/istioctl- CLI tool for installation and managementsamples/- Example applications (Bookinfo, httpbin, etc.)manifests/- Kubernetes YAML manifests
Add istioctl to your PATH:
cd istio-1.30.0 export PATH=$PWD/bin:$PATHMake this permanent by adding to
~/.bashrcor~/.zshrc:echo 'export PATH="$HOME/istio-1.30.0/bin:$PATH"' >> ~/.bashrcStep 2: Choose an Installation Profile
Istio provides several profiles balancing features and resource usage:
default- Production-ready baseline (recommended for most deployments)demo- Full feature set for evaluation (high resource usage, not for production)minimal- Bare minimum components (control plane only)ambient- Ambient mesh mode without sidecars (experimental as of 2026)preview- Experimental features for testing
For testing and learning, use the demo profile:
istioctl install --set profile=demo -yFor production, use the default profile with custom overrides:
istioctl install --set profile=default -yStep 3: Verify Installation
Check that Istiod and other components are running:
kubectl get pods -n istio-systemYou should see:
istiod-*- Control plane pod (Running)istio-ingressgateway-*- Ingress gateway (if included in profile)istio-egressgateway-*- Egress gateway (demo profile only)
Verify the installation with istioctl:
istioctl verify-installThis command validates that all expected resources are present and healthy.
# Download and install Istio curl -L https://istio.io/downloadIstio | sh - cd istio-1.30.0 export PATH=$PWD/bin:$PATH # Install with demo profile (testing) istioctl install --set profile=demo -y # Or install with default profile (production) istioctl install --set profile=default -y # Verify installation kubectl get pods -n istio-system istioctl verify-install # View installed profile istioctl profile dump demo # Compare profiles istioctl profile diff default demo - Step 5
Installation: Using Helm
Helm charts provide more control over Istio configuration and are preferred for production deployments with GitOps workflows. Istio's Helm charts are split into base (CRDs) and istiod (control plane) for granular version management.
Step 1: Add Istio Helm Repository
helm repo add istio https://istio-release.storage.googleapis.com/charts helm repo updateStep 2: Install Istio Base (CRDs)
The base chart installs Custom Resource Definitions required by Istio:
helm install istio-base istio/base \ -n istio-system \ --create-namespaceStep 3: Install Istiod (Control Plane)
helm install istiod istio/istiod \ -n istio-system \ --waitStep 4: Install Ingress Gateway (Optional)
For external traffic ingress:
helm install istio-ingressgateway istio/gateway \ -n istio-system \ --set service.type=LoadBalancerCustomizing with values.yaml:
Create a
values.yamlfile for production-grade configuration:global: tracer: zipkin: address: jaeger-collector.observability:9411 proxy: resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 512Mi logAsJson: true meshConfig: accessLogFile: /dev/stdout enableTracing: true defaultConfig: holdApplicationUntilProxyStarts: trueInstall with custom values:
helm install istiod istio/istiod \ -n istio-system \ -f values.yamlUpgrading Istio with Helm:
helm upgrade istiod istio/istiod -n istio-systemUninstalling:
helm uninstall istiod -n istio-system helm uninstall istio-base -n istio-system kubectl delete namespace istio-system# Add Istio Helm repository helm repo add istio https://istio-release.storage.googleapis.com/charts helm repo update # Install base (CRDs) helm install istio-base istio/base \ -n istio-system \ --create-namespace # Install control plane helm install istiod istio/istiod \ -n istio-system \ --wait # Install ingress gateway helm install istio-ingressgateway istio/gateway \ -n istio-system # Verify installation kubectl get all -n istio-system helm list -n istio-system # Upgrade helm upgrade istiod istio/istiod -n istio-system - Step 6
Enable automatic sidecar injection
Istio's sidecar injection automatically adds an Envoy proxy container to each pod in labeled namespaces. This is the core mechanism that brings pods into the service mesh.
How it works: When you label a namespace with
istio-injection=enabled, Istio's mutating admission webhook intercepts pod creation requests and injects two additional containers:- istio-init - An init container that configures iptables rules to redirect inbound/outbound traffic through the Envoy proxy
- istio-proxy - The Envoy sidecar that handles all network traffic
Enable for a namespace:
kubectl label namespace default istio-injection=enabledVerify the label:
kubectl get namespace -L istio-injectionDeploy a test application:
When you deploy pods in an injection-enabled namespace, sidecars are automatically added:
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yamlCheck that pods have 2/2 containers (app + sidecar):
kubectl get podsYou should see output like:
NAME READY STATUS RESTARTS AGE productpage-v1-xxx 2/2 Running 0 1m details-v1-xxx 2/2 Running 0 1m reviews-v1-xxx 2/2 Running 0 1mSelective injection with pod annotations:
Override namespace-level settings on individual pods:
apiVersion: v1 kind: Pod metadata: annotations: sidecar.istio.io/inject: "false" # Disable for this pod spec: containers: - name: myapp image: myapp:v1Manual injection (for CI/CD pipelines):
Inject sidecars at deployment time without webhook:
istioctl kube-inject -f deployment.yaml | kubectl apply -f -Disable injection for a namespace:
kubectl label namespace default istio-injection-Note: Existing pods are not affected by label changes. You must restart pods (rollout, delete) for injection changes to take effect.
# Enable automatic sidecar injection kubectl label namespace default istio-injection=enabled # Verify label kubectl get namespace -L istio-injection # Deploy an app (sidecars injected automatically) kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml # Check that pods have 2/2 containers kubectl get pods # Describe a pod to see sidecar details kubectl describe pod <pod-name> # Manual injection (alternative to webhook) istioctl kube-inject -f deployment.yaml | kubectl apply -f - # Disable injection kubectl label namespace default istio-injection- # Restart pods to apply injection changes kubectl rollout restart deployment/<deployment-name> - Step 7
Traffic management: VirtualService and DestinationRule
Istio's traffic management APIs allow you to control request routing, load balancing, retries, timeouts, and circuit breaking without changing application code. The two primary resources are VirtualService and DestinationRule.
VirtualService defines routing rules for how requests are routed to services. Think of it as a routing table that matches conditions (URI, headers) and directs traffic to destination subsets.
Example: Route 90% of traffic to v1, 10% to v2 (canary deployment):
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews spec: hosts: - reviews http: - match: - headers: end-user: exact: jason route: - destination: host: reviews subset: v2 - route: - destination: host: reviews subset: v1 weight: 90 - destination: host: reviews subset: v2 weight: 10DestinationRule defines policies for traffic after routing decisions are made, including load balancing, connection pool settings, and outlier detection (circuit breaking).
Example: Define subsets and circuit breaker:
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: reviews spec: host: reviews trafficPolicy: loadBalancer: simple: LEAST_REQUEST connectionPool: tcp: maxConnections: 100 http: http1MaxPendingRequests: 1 maxRequestsPerConnection: 2 outlierDetection: consecutive5xxErrors: 5 interval: 30s baseEjectionTime: 30s subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2Apply these configurations:
kubectl apply -f virtualservice.yaml kubectl apply -f destinationrule.yamlOther traffic management features:
- Fault injection - Test resilience by injecting delays or HTTP errors
- Request timeouts - Automatically fail requests that exceed time limits
- Retries - Automatically retry failed requests with exponential backoff
- Mirroring - Duplicate traffic to v2 for testing without affecting users
- Header manipulation - Add, remove, or modify HTTP headers
# Traffic splitting (90/10 canary) apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews spec: hosts: - reviews http: - route: - destination: host: reviews subset: v1 weight: 90 - destination: host: reviews subset: v2 weight: 10 --- # Load balancing and circuit breaking apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: reviews spec: host: reviews trafficPolicy: loadBalancer: simple: LEAST_REQUEST outlierDetection: consecutive5xxErrors: 5 interval: 30s subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 - Step 8
Security: Mutual TLS (mTLS)
Istio automatically secures service-to-service communication with mutual TLS encryption, ensuring that all traffic within the mesh is encrypted and authenticated. This happens transparently without application code changes.
How mTLS works in Istio:
- Istiod acts as a Certificate Authority (CA), generating and distributing X.509 certificates to each Envoy sidecar
- Certificates are automatically rotated before expiration (default: 24-hour lifetime, rotated after 12 hours)
- When service A calls service B, their sidecars establish a mutual TLS connection, verifying each other's identity
- Traffic between pods is encrypted; application containers communicate over localhost with their sidecar
mTLS Modes:
STRICT- Only accept mTLS connections (recommended for production)PERMISSIVE- Accept both mTLS and plaintext (useful during migration)DISABLE- No mTLS enforcement (not recommended)
Enable strict mTLS mesh-wide:
apiVersion: security.istio.io/v1beta1 kind: PeerAuthentication metadata: name: default namespace: istio-system spec: mtls: mode: STRICTApply the policy:
kubectl apply -f peer-authentication.yamlPer-namespace mTLS:
apiVersion: security.istio.io/v1beta1 kind: PeerAuthentication metadata: name: default namespace: production spec: mtls: mode: STRICTVerify mTLS is active:
Check that traffic uses mTLS by examining Envoy stats:
istioctl proxy-config secret <pod-name> -o json | jq '[.dynamicActiveSecrets[] | select(.name == "default")]'Alternatively, use Kiali's service graph which shows lock icons on encrypted connections.
Authorization policies:
Once mTLS establishes identity, use AuthorizationPolicy for fine-grained access control:
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: allow-reviews namespace: default spec: selector: matchLabels: app: reviews action: ALLOW rules: - from: - source: principals: ["cluster.local/ns/default/sa/productpage"] to: - operation: methods: ["GET"]This policy allows only the
productpageservice account to make GET requests toreviews.# Enable strict mTLS mesh-wide apiVersion: security.istio.io/v1beta1 kind: PeerAuthentication metadata: name: default namespace: istio-system spec: mtls: mode: STRICT --- # Fine-grained authorization apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: allow-reviews namespace: default spec: selector: matchLabels: app: reviews action: ALLOW rules: - from: - source: principals: ["cluster.local/ns/default/sa/productpage"] to: - operation: methods: ["GET"] - Step 9
Observability: Metrics, tracing, and visualization
Istio provides comprehensive observability out of the box, collecting metrics, traces, and logs from all service interactions without requiring application instrumentation.
Metrics with Prometheus:
Istio automatically exports Prometheus-format metrics from Envoy proxies. Key metrics include:
- Request rates, durations, and sizes
- Success/error rates (4xx, 5xx responses)
- TCP connection counts and bytes transferred
- Circuit breaker trip counts
Deploy Prometheus (if not already present):
kubectl apply -f samples/addons/prometheus.yamlVisualization with Grafana:
Grafana dashboards provide pre-built views of Istio metrics:
kubectl apply -f samples/addons/grafana.yaml kubectl port-forward -n istio-system svc/grafana 3000:3000Access Grafana at
http://localhost:3000and explore:- Istio Mesh Dashboard - Overall mesh health
- Istio Service Dashboard - Per-service metrics
- Istio Workload Dashboard - Per-pod metrics
Distributed tracing with Jaeger:
Istio generates trace spans for each request, showing the complete path through your microservices:
kubectl apply -f samples/addons/jaeger.yaml kubectl port-forward -n istio-system svc/tracing 16686:80Access Jaeger at
http://localhost:16686. Select a service and click "Find Traces" to see request timelines.Service topology with Kiali:
Kiali provides a real-time graph of service communication:
kubectl apply -f samples/addons/kiali.yaml kubectl port-forward -n istio-system svc/kiali 20001:20001Access Kiali at
http://localhost:20001. The graph view shows:- Service topology with traffic flow animation
- Health status (green/yellow/red indicators)
- mTLS status (lock icons on encrypted edges)
- Traffic metrics overlays (requests per second, error rates)
Access logs:
Enable access logging for all proxies:
istioctl install --set meshConfig.accessLogFile=/dev/stdoutOr via Telemetry API for specific workloads:
apiVersion: telemetry.istio.io/v1alpha1 kind: Telemetry metadata: name: mesh-default namespace: istio-system spec: accessLogging: - providers: - name: envoyView proxy logs:
kubectl logs <pod-name> -c istio-proxy# Deploy observability addons kubectl apply -f samples/addons/prometheus.yaml kubectl apply -f samples/addons/grafana.yaml kubectl apply -f samples/addons/jaeger.yaml kubectl apply -f samples/addons/kiali.yaml # Port-forward to access dashboards kubectl port-forward -n istio-system svc/grafana 3000:3000 & kubectl port-forward -n istio-system svc/kiali 20001:20001 & kubectl port-forward -n istio-system svc/tracing 16686:80 & # Access dashboards # Grafana: http://localhost:3000 # Kiali: http://localhost:20001 # Jaeger: http://localhost:16686 # Enable access logs istioctl install --set meshConfig.accessLogFile=/dev/stdout # View proxy logs kubectl logs <pod-name> -c istio-proxy - Step 10
Gateway configuration for external traffic
Istio Gateway resources manage inbound and outbound traffic at the edge of the mesh, replacing traditional Kubernetes Ingress resources with more powerful L4-L7 capabilities.
Gateway defines a load balancer operating at the edge of the mesh that receives incoming HTTP/TCP connections. Think of it as configuring a reverse proxy (Envoy) that sits at your cluster boundary.
Example: HTTP Gateway with virtual service:
First, define a Gateway resource:
apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: bookinfo-gateway spec: selector: istio: ingressgateway # Use Istio's default ingress gateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "bookinfo.example.com"Then, attach a VirtualService to route traffic:
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: bookinfo spec: hosts: - "bookinfo.example.com" gateways: - bookinfo-gateway http: - match: - uri: exact: /productpage route: - destination: host: productpage port: number: 9080Apply the configuration:
kubectl apply -f gateway.yaml kubectl apply -f virtualservice.yamlGet the ingress gateway external IP:
kubectl get svc istio-ingressgateway -n istio-systemIf using a LoadBalancer, you'll see an EXTERNAL-IP. For local testing without a load balancer, use port-forward:
kubectl port-forward -n istio-system svc/istio-ingressgateway 8080:80HTTPS with TLS termination:
Create a TLS secret from your certificate:
kubectl create secret tls bookinfo-credential \ --cert=bookinfo.example.com.crt \ --key=bookinfo.example.com.key \ -n istio-systemUpdate the Gateway to use HTTPS:
servers: - port: number: 443 name: https protocol: HTTPS tls: mode: SIMPLE credentialName: bookinfo-credential hosts: - "bookinfo.example.com"Egress Gateway (controlling outbound traffic):
By default, Istio allows all outbound traffic. To control external service access:
- Configure Istio to block unknown traffic
- Define ServiceEntry for allowed external services
- Route through an egress gateway for centralized monitoring
Example ServiceEntry for external API:
apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: external-api spec: hosts: - api.example.com ports: - number: 443 name: https protocol: HTTPS location: MESH_EXTERNAL resolution: DNS# HTTP Gateway apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: bookinfo-gateway spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- # VirtualService routing through gateway apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: bookinfo spec: hosts: - "*" gateways: - bookinfo-gateway http: - match: - uri: exact: /productpage route: - destination: host: productpage port: number: 9080 - Step 11
Common use cases and patterns
Istio enables several deployment patterns that are difficult or impossible to implement reliably at the application layer.
1. Canary Deployments:
Gradually roll out new versions by shifting traffic percentages:
http: - route: - destination: host: myapp subset: v1 weight: 95 - destination: host: myapp subset: v2 weight: 5Monitor v2 metrics in Grafana. If healthy, increase weight to 10%, 25%, 50%, 100%.
2. Blue/Green Deployments:
Instantaneous switchover between versions:
http: - route: - destination: host: myapp subset: blue # Change to green when ready3. A/B Testing:
Route specific user segments to different versions:
http: - match: - headers: user-group: exact: beta-testers route: - destination: host: myapp subset: v2 - route: - destination: host: myapp subset: v14. Fault Injection (Chaos Engineering):
Test resilience by injecting artificial faults:
http: - fault: delay: percentage: value: 10 fixedDelay: 5s abort: percentage: value: 5 httpStatus: 500 route: - destination: host: myapp5. Request Mirroring (Dark Traffic):
Send live traffic copy to v2 without affecting users:
http: - route: - destination: host: myapp subset: v1 mirror: host: myapp subset: v2 mirrorPercentage: value: 1006. Multi-Cluster Service Mesh:
Extend the mesh across multiple Kubernetes clusters for:
- High availability across regions
- Disaster recovery
- Development/staging cluster separation with production
Ambient multicluster support entered beta in March 2026, simplifying cross-cluster mTLS and service discovery.
7. Zero-Trust Security:
Implement "deny by default" with explicit allow policies:
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: deny-all namespace: production spec: {} # Empty spec = deny allThen create specific allow policies for each service interaction.
- Step 12
Configuration and tuning
Istio provides extensive configuration options for optimizing performance, resource usage, and behavior.
Proxy resource limits:
Adjust CPU and memory for Envoy sidecars via annotations:
apiVersion: v1 kind: Pod metadata: annotations: sidecar.istio.io/proxyCPU: "200m" sidecar.istio.io/proxyMemory: "256Mi" sidecar.istio.io/proxyCPULimit: "1000m" sidecar.istio.io/proxyMemoryLimit: "512Mi" spec: containers: - name: myapp image: myapp:v1Mesh-wide configuration:
The IstioOperator resource (for istioctl) or Helm values control global settings:
apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: name: production-config spec: meshConfig: # Enable access logs accessLogFile: /dev/stdout accessLogFormat: | [%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%" # Distributed tracing enableTracing: true defaultConfig: tracing: sampling: 10.0 # Sample 10% of requests # Hold app startup until proxy is ready defaultConfig: holdApplicationUntilProxyStarts: trueApply with:
istioctl install -f production-config.yamlPerformance tuning:
- Reduce sidecar memory: Set
ISTIO_META_DNS_CAPTURE=falseto disable DNS proxying - Faster startup: Use
holdApplicationUntilProxyStarts: trueto prevent race conditions - Lower latency: Tune connection pool sizes in DestinationRule
- High throughput: Increase
maxRequestsPerConnectionandhttp2MaxRequests
Monitoring Istio itself:
Istiod exposes metrics on port 15014:
kubectl port-forward -n istio-system deploy/istiod 15014:15014 curl http://localhost:15014/metricsKey metrics:
pilot_xds_pushes_total- Configuration updates pushed to proxiespilot_proxy_convergence_time- Time for config to reach all proxiespilot_conflict- Configuration conflicts
Debug commands:
# View effective config for a pod istioctl proxy-config all <pod-name> # Check why traffic is not working istioctl analyze # View Envoy admin interface kubectl port-forward <pod-name> 15000:15000 # Then visit http://localhost:15000 # Capture traffic for debugging istioctl dashboard envoy <pod-name># View proxy configuration istioctl proxy-config listeners <pod-name> istioctl proxy-config routes <pod-name> istioctl proxy-config clusters <pod-name> istioctl proxy-config endpoints <pod-name> # Analyze configuration issues istioctl analyze istioctl analyze -n production # Check version compatibility istioctl x precheck # Dashboard access istioctl dashboard controlz deployment/istiod -n istio-system istioctl dashboard envoy <pod-name> # Debug logging (temporarily increase verbosity) istioctl proxy-config log <pod-name> --level debug # Monitor control plane kubectl logs -n istio-system deploy/istiod -f - Reduce sidecar memory: Set
- Step 13
Upgrading Istio
Istio supports canary upgrades, allowing you to run two control plane versions simultaneously and migrate workloads gradually.
In-place upgrade (simpler, brief downtime):
- Download the new Istio version:
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.31.0 sh - cd istio-1.31.0- Check upgrade compatibility:
istioctl x precheck- Perform the upgrade:
istioctl upgradeIstioctl will show a diff of changes and ask for confirmation.
- Restart workloads to pick up the new sidecar version:
kubectl rollout restart deployment -n productionCanary upgrade (zero downtime, safer):
- Install the new control plane alongside the old one:
istioctl install --set revision=1-31-0 -y- Label a test namespace to use the new control plane:
kubectl label namespace test istio.io/rev=1-31-0 --overwrite kubectl label namespace test istio-injection-- Restart pods in the test namespace:
kubectl rollout restart deployment -n test- Verify functionality, then migrate production namespaces:
kubectl label namespace production istio.io/rev=1-31-0 --overwrite kubectl rollout restart deployment -n production- After all namespaces are migrated, remove the old control plane:
istioctl uninstall --revision=1-30-0 -yBest practices:
- Always check the release notes for breaking changes
- Test in a non-production environment first
- Use canary upgrades for production clusters
- Monitor metrics during and after upgrade
- Keep Istio versions within N-1 support (e.g., 1.30 → 1.31 is supported, 1.28 → 1.31 is not)
# Canary upgrade process # 1. Install new control plane with revision istioctl install --set revision=1-31-0 -y # 2. Verify both control planes running kubectl get pods -n istio-system -L istio.io/rev # 3. Migrate a namespace to new version kubectl label namespace test istio.io/rev=1-31-0 --overwrite kubectl label namespace test istio-injection- kubectl rollout restart deployment -n test # 4. Verify pods use new sidecar kubectl get pods -n test -o jsonpath='{.items[*].metadata.annotations.sidecar\.istio\.io/status}' # 5. Migrate remaining namespaces kubectl label namespace production istio.io/rev=1-31-0 --overwrite kubectl rollout restart deployment -n production # 6. Remove old control plane istioctl uninstall --revision=1-30-0 -y - Step 14
Ambient mesh mode (Sidecar-less architecture)
Istio Ambient Mesh, which reached multicluster beta in March 2026, is a sidecar-less service mesh architecture that separates L4 and L7 functionality into distinct components.
Why ambient mode?
Traditional sidecar mode has challenges:
- Higher resource overhead (CPU/memory per pod)
- Slower pod startup times
- Operational complexity (sidecar version management)
- Increased attack surface per pod
Ambient mode addresses these by moving Envoy proxies out of application pods into shared infrastructure.
Architecture:
- ztunnel (Zero Trust Tunnel) - A per-node L4 proxy written in Rust, providing mTLS, basic routing, and telemetry
- waypoint proxy - Optional L7 Envoy proxy (one per namespace or service), handling advanced features like traffic splitting, retries, and request-level policies
Benefits:
- 90% reduction in proxy resource usage (shared vs per-pod)
- Faster pod startup (no sidecar injection)
- Simplified upgrades (upgrade node agents vs restarting all pods)
- Gradual L7 adoption (start with L4 ztunnel, add waypoints only where needed)
Installation:
istioctl install --set profile=ambient -yEnroll a namespace in ambient mode:
kubectl label namespace production istio.io/dataplane-mode=ambientThis enables mTLS and L4 telemetry without sidecars.
Add L7 features with waypoint proxy:
istioctl waypoint apply -n productionNow you can use VirtualService, DestinationRule, and other L7 policies in that namespace.
Current status (2026):
Ambient mode is production-ready for single-cluster deployments. Multicluster ambient entered beta in March 2026. Microsoft's Azure Kubernetes Application Network uses ambient mode as its foundation.
When to use ambient vs sidecar:
- Use ambient if you prioritize resource efficiency, simpler operations, or want to add mesh incrementally
- Use sidecar if you need per-pod isolation, run untrusted workloads, or use advanced per-pod customization
# Install Istio in ambient mode istioctl install --set profile=ambient -y # Verify ztunnel DaemonSet running kubectl get daemonset -n istio-system ztunnel # Enroll namespace in ambient mesh (L4 only) kubectl label namespace production istio.io/dataplane-mode=ambient # Deploy waypoint proxy for L7 features istioctl waypoint apply -n production # Verify waypoint proxy kubectl get pods -n production -l gateway.istio.io/managed=waypoint # Remove waypoint (keep L4 features) istioctl waypoint delete -n production # Remove from ambient mesh entirely kubectl label namespace production istio.io/dataplane-mode- - Step 15
Troubleshooting common issues
Here are solutions to frequent Istio problems:
Issue 1: Pods show 1/2 containers, CrashLoopBackOff for istio-proxy
Cause: Init container failed to configure iptables, often due to insufficient permissions.
Solution: If running on GKE with Autopilot or other restricted environments, use Istio CNI plugin:
istioctl install --set components.cni.enabled=true --set profile=demo -yIssue 2: "503 Service Unavailable" errors
Cause: DestinationRule references subsets that don't match any pods.
Solution: Check that subset labels match pod labels:
kubectl get pods --show-labels istioctl proxy-config clusters <pod-name> | grep <service>Ensure your DestinationRule
subset.labelsmatch actual pod labels.Issue 3: Configuration not taking effect
Cause: Configuration conflicts or validation errors.
Solution: Run analyze to detect issues:
istioctl analyzeCommon problems:
- Multiple VirtualServices for the same host
- DestinationRule subsets without matching VirtualService
- Invalid regex in match conditions
Issue 4: mTLS failures ("upstream connect error or disconnect/reset before headers")
Cause: Mismatch between PeerAuthentication mode and DestinationRule TLS settings.
Solution: If PeerAuthentication is STRICT, ensure DestinationRule doesn't disable TLS:
trafficPolicy: tls: mode: ISTIO_MUTUAL # Required for mTLSIssue 5: High proxy memory usage
Cause: Large configuration (many services/routes) or high concurrent connection count.
Solutions:
- Use Sidecar resource to limit config scope:
apiVersion: networking.istio.io/v1beta1 kind: Sidecar metadata: name: default namespace: production spec: egress: - hosts: - "./" - "istio-system/*"- Increase proxy memory limits via annotations
- Consider ambient mode for resource-constrained environments
Issue 6: Envoy not starting (CrashLoopBackOff immediately after upgrade)
Cause: Incompatible Envoy version or corrupted config.
Solution: Drain old config and restart:
kubectl delete pod <pod-name>If persistent, check for API version mismatches:
kubectl get virtualservices -o yaml | grep apiVersionDebug tools:
# Get detailed proxy sync status istioctl proxy-status # View rejected configuration istioctl proxy-config all <pod-name> -o json # Enable debug logging temporarily istioctl proxy-config log <pod-name> --level debug # Check control plane health kubectl logs -n istio-system deploy/istiod - Step 16
Resources
Official Documentation: https://istio.io/latest/docs/
GitHub Repository: https://github.com/istio/istio (37K+ stars)
Getting Started Guide: https://istio.io/latest/docs/setup/getting-started/
Community:
- Istio Slack: https://slack.istio.io
- Discuss: https://discuss.istio.io
- Stack Overflow: Tag
istio - Reddit: r/istio
Training and Certification:
- Istio Fundamentals (Solo.io, free)
- Certified Istio Administrator by Solo.io
- Istio workshops: https://www.istioworkshop.io
Key Concepts Documentation:
- Architecture: https://istio.io/latest/docs/ops/deployment/architecture/
- Traffic Management: https://istio.io/latest/docs/concepts/traffic-management/
- Security: https://istio.io/latest/docs/concepts/security/
- Observability: https://istio.io/latest/docs/concepts/observability/
Tools:
- Kiali (service mesh observability): https://kiali.io
- GetEnvoy (Envoy distributions): https://www.getenvoy.io
- istioctl reference: https://istio.io/latest/docs/reference/commands/istioctl/
Related Projects:
- Envoy Proxy: https://www.envoyproxy.io
- Kubernetes Gateway API: https://gateway-api.sigs.k8s.io
- SPIFFE/SPIRE (identity framework): https://spiffe.io
Books:
- "Istio in Action" by Christian Posta and Rinor Maloku (Manning)
- "Istio: Up and Running" by Lee Calcote and Zack Butcher (O'Reilly)
Release Notes: https://istio.io/latest/news/releases/
Official: https://istio.io Docs: https://istio.io/latest/docs/ GitHub: https://github.com/istio/istio Slack: https://slack.istio.io Discussions: https://discuss.istio.io Tools: - Kiali: https://kiali.io - istioctl: https://istio.io/latest/docs/reference/commands/istioctl/ - Envoy: https://www.envoyproxy.io Learning: - Istio Workshop: https://www.istioworksh op.io - Solo.io Training: https://academy.solo.io
Feature requests
Sign in to suggest features or vote on existing ones.
No feature requests yet.
Discussion
Sign in to join the discussion.
No comments yet.