Skip to content
Codeloom
DevOps

Service Mesh with Istio: A Practical Introduction

Learn what a service mesh is, why Istio exists, and how to configure traffic management, observability, and mTLS for your microservices.

·5 min read · By Codeloom
Intermediate 11 min read

What you'll learn

  • What a service mesh is and the problems it solves
  • Istio architecture: data plane vs control plane
  • Traffic routing with VirtualService and DestinationRule
  • Automatic mTLS between services
  • Observability features you get for free

Prerequisites

None — this post is self-contained.

When you have five microservices, you can manage inter-service communication with application code. When you have fifty, you cannot. A service mesh moves networking concerns like retries, timeouts, circuit breaking, mutual TLS, and traffic shaping out of application code and into infrastructure. Istio is the most widely adopted service mesh for Kubernetes, and this article covers the fundamentals you need to get started.

What a Service Mesh Does

Every microservice in your cluster communicates over the network. Without a service mesh, each service handles its own retry logic, timeout configuration, TLS certificate management, and traffic routing. This means duplicated logic across languages and frameworks, inconsistent behavior, and no centralized visibility.

A service mesh injects a sidecar proxy next to every pod. All inbound and outbound traffic flows through this proxy. The proxy handles retries, timeouts, mTLS, load balancing, and telemetry collection without the application knowing about it. Your code makes a plain HTTP call; the mesh handles everything else.

Istio Architecture

Istio has two components:

Data plane: Envoy sidecar proxies injected into every pod. These proxies intercept all network traffic and apply the rules you configure. Envoy is a high-performance, battle-tested proxy originally built at Lyft.

Control plane: The istiod process that configures all the Envoy proxies. It distributes routing rules, manages certificates for mTLS, and collects telemetry. In older Istio versions this was split into Pilot, Citadel, and Galley, but modern Istio consolidates everything into istiod.

Installing Istio

Install the Istio CLI and deploy the demo profile for learning:

curl -L https://istio.io/downloadIstio | sh -
cd istio-*
export PATH=$PWD/bin:$PATH

istioctl install --set profile=demo -y

Enable automatic sidecar injection for your namespace:

kubectl label namespace default istio-injection=enabled

Any pod created in this namespace now gets an Envoy sidecar automatically. Existing pods need a restart to pick up the sidecar.

Traffic Management

Istio’s traffic management uses two key resources: VirtualService and DestinationRule.

Routing Traffic Between Versions

Suppose you have two versions of a service deployed with different labels:

# v1 deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: reviews
      version: v1
  template:
    metadata:
      labels:
        app: reviews
        version: v1
    spec:
      containers:
        - name: reviews
          image: myregistry/reviews:1.0
---
# v2 deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v2
spec:
  replicas: 2
  selector:
    matchLabels:
      app: reviews
      version: v2
  template:
    metadata:
      labels:
        app: reviews
        version: v2
    spec:
      containers:
        - name: reviews
          image: myregistry/reviews:2.0

Define subsets with a DestinationRule:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2

Route 90 percent of traffic to v1 and 10 percent to v2:

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

This gives you canary deployments at the mesh level without touching application code or ingress annotations.

Timeouts and Retries

Add fault tolerance configuration to the VirtualService:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
    - timeout: 3s
      retries:
        attempts: 3
        perTryTimeout: 1s
        retryOn: 5xx,reset,connect-failure
      route:
        - destination:
            host: reviews
            subset: v1

Every call to the reviews service now has a 3-second total timeout, with up to 3 retries on server errors. This policy applies regardless of whether the caller is written in Go, Python, or Java.

Mutual TLS

Istio enables mTLS between services by default in recent versions. Every sidecar gets a certificate from istiod, and all inter-service traffic is encrypted and authenticated automatically.

Verify mTLS is active:

istioctl x describe pod reviews-v1-abc123

To enforce strict mTLS and reject any plaintext connections:

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: default
spec:
  mtls:
    mode: STRICT

With strict mode, a service outside the mesh cannot call services inside the mesh without a valid certificate. This provides zero-trust networking within your cluster.

Observability

Istio’s sidecar proxies emit detailed telemetry without any application instrumentation. You get:

Metrics: Request rate, error rate, and latency for every service-to-service call, exposed as Prometheus metrics. Install Kiali to visualize the service graph:

kubectl apply -f samples/addons/kiali.yaml
kubectl apply -f samples/addons/prometheus.yaml
kubectl apply -f samples/addons/grafana.yaml
istioctl dashboard kiali

Distributed tracing: Envoy propagates trace headers automatically. Deploy Jaeger to collect traces:

kubectl apply -f samples/addons/jaeger.yaml
istioctl dashboard jaeger

Access logs: Configure Envoy to log every request with upstream and downstream metadata for debugging.

The key benefit is that you get golden signal metrics for every service without adding a single line of instrumentation code. The mesh observes the traffic as it flows through the proxies.

When Not to Use a Service Mesh

A service mesh adds complexity. Every pod gets an extra container, which increases memory usage, adds latency (typically 1-3ms per hop), and introduces a new system to operate and upgrade.

Do not adopt a service mesh if you have fewer than ten services, if your team is not comfortable operating Kubernetes, or if you do not have specific problems that a mesh solves. Start with simple retries in your HTTP client, mTLS with cert-manager, and basic Prometheus metrics. Move to a mesh when the maintenance burden of doing those things per-service exceeds the cost of operating the mesh.

Wrap-up

A service mesh like Istio centralizes traffic management, security, and observability for microservices. It trades operational complexity for consistent behavior across services regardless of language or framework. Start with the demo profile, experiment with traffic splitting and mTLS, and adopt it in production only when the problems it solves outweigh the overhead it introduces.