Skip to content
Back to Blog
DevOps

Istio Service Mesh: Traffic Management and mTLS

Deploy Istio service mesh on Kubernetes: mutual TLS, traffic shifting, circuit breaking, observability, and access policies.

Dec 2025
18 min read

Introduction

Istio is a service mesh that adds observability, traffic management, and security to microservices without changing application code. In a microservices architecture with dozens of services, managing things like mutual TLS between services, circuit breakers, retries, and distributed tracing becomes complex. Istio handles all of this at the infrastructure level using sidecar proxies (Envoy). This guide teaches you to deploy and use Istio effectively.

How Istio Works

Istio injects a sidecar proxy (Envoy) alongside every pod:

TEXT
Without Istio:               With Istio:
┌──────────────┐             ┌────────────────────────┐
│   Service A  │─────────────│  Service A  │  Envoy  │
└──────────────┘             └────────────────────────┘
       │                                │
       ▼                                ▼ (intercepted)
┌──────────────┐             ┌────────────────────────┐
│   Service B  │             │  Envoy  │  Service B  │
└──────────────┘             └────────────────────────┘

All traffic passes through Envoy sidecars, which:
- Enforce mTLS between services
- Collect metrics and traces
- Apply routing rules and retries

Installing Istio

BASH
# Download Istio
curl -L https://istio.io/downloadIstio | sh -
cd istio-1.20.0
export PATH=$PWD/bin:$PATH

# Install with demo profile (good for learning)
istioctl install --set profile=demo -y

# Verify installation
kubectl get pods -n istio-system

# Enable automatic sidecar injection for a namespace
kubectl label namespace default istio-injection=enabled

# Verify injection is working (deploy test app)
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
kubectl get pods  # Should see 2 containers per pod (app + istio-proxy)

Traffic Management

Istio uses VirtualService and DestinationRule to control traffic:

YAML
# VirtualService: defines routing rules
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp
spec:
  hosts:
  - myapp
  http:
  # Canary: 10% traffic to v2
  - route:
    - destination:
        host: myapp
        subset: v1
      weight: 90
    - destination:
        host: myapp
        subset: v2
      weight: 10

---
# DestinationRule: defines subsets (versions)
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: myapp
spec:
  host: myapp
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  trafficPolicy:
    connectionPool:
      http:
        http2MaxRequests: 1000
    outlierDetection:    # Circuit breaker
      consecutive5xxErrors: 5
      interval: 30s
      baseEjectionTime: 30s

Retries and Timeouts

YAML
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: payment-service
spec:
  hosts:
  - payment-service
  http:
  - timeout: 5s          # Total timeout for request
    retries:
      attempts: 3         # Retry up to 3 times
      perTryTimeout: 2s   # Each try max 2s
      retryOn: "connect-failure,reset,503"
    route:
    - destination:
        host: payment-service

mTLS Between Services

YAML
# Enable strict mTLS for all services in namespace
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production
spec:
  mtls:
    mode: STRICT    # All traffic must use mTLS

---
# Allow specific service to use permissive (during migration)
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: legacy-service
  namespace: production
spec:
  selector:
    matchLabels:
      app: legacy
  mtls:
    mode: PERMISSIVE

Authorization Policies

YAML
# Only allow frontend to call backend
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: backend-policy
  namespace: production
spec:
  selector:
    matchLabels:
      app: backend
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/production/sa/frontend"]
  - to:
    - operation:
        methods: ["GET", "POST"]
        paths: ["/api/*"]

Observability with Kiali

Kiali provides a dashboard showing the service mesh topology:

BASH
# Install observability addons
kubectl apply -f samples/addons/

# Access Kiali dashboard
istioctl dashboard kiali

# Access Grafana (Istio metrics)
istioctl dashboard grafana

# Access Jaeger (distributed tracing)
istioctl dashboard jaeger

Kiali shows:

  • Service dependency graph with traffic flow
  • Error rates and latency per service
  • mTLS status between services
  • Traffic split percentages for canary deployments

Ingress Gateway

YAML
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: myapp-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: myapp-tls-cert
    hosts:
    - app.company.com

---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp-ingress
spec:
  hosts:
  - app.company.com
  gateways:
  - myapp-gateway
  http:
  - route:
    - destination:
        host: myapp
        port:
          number: 8080

Debugging Istio Issues

BASH
# Check sidecar injection
kubectl get pod myapp-xxx -o jsonpath='{.spec.containers[*].name}'
# Should show: myapp istio-proxy

# Check proxy configuration
istioctl proxy-config cluster myapp-xxx.default

# Check if mTLS is working
istioctl x check-inject -n production

# View Envoy access logs
kubectl logs myapp-xxx -c istio-proxy | head -20

# Analyze configuration for issues
istioctl analyze -n production

# Check traffic policies applied
istioctl proxy-config listener myapp-xxx.default

Istio adds significant operational complexity but pays off in large microservice deployments where you need consistent security, observability, and traffic control across dozens of services. Start with observability only (no policy enforcement) before enabling mTLS and authorization policies.