How to Set Up Istio Service Mesh from Scratch (2026)
Step-by-step guide to installing and configuring Istio service mesh on Kubernetes. Covers traffic management, mTLS, observability, canary deployments, and production best practices.
Service mesh sounds complicated. And honestly, Istio has earned that reputation. But in 2026, Istio's ambient mesh mode has dramatically simplified things — no more sidecar proxies for basic features.
This guide takes you from a bare Kubernetes cluster to a fully functional Istio mesh with mTLS, traffic management, and observability.
Prerequisites
- Kubernetes cluster 1.28+ (EKS, GKE, AKS, or local with kind/minikube)
kubectlconfigured- 4+ GB RAM available in the cluster
- Helm 3.x installed
Step 1: Install Istio
Using istioctl (Recommended)
# Download istioctl
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.23.0 sh -
cd istio-1.23.0
export PATH=$PWD/bin:$PATH
# Install with the default profile
istioctl install --set profile=default -yVerify:
istioctl verify-install
kubectl get pods -n istio-systemNAME READY STATUS RESTARTS AGE
istiod-5b8c6f6d4f-x2k4m 1/1 Running 0 2m
istio-ingressgateway-7d9bc5f8b-9j3kl 1/1 Running 0 2m
Using Helm (For GitOps)
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 istiod (control plane)
helm install istiod istio/istiod -n istio-system --wait
# Install ingress gateway
helm install istio-ingress istio/gateway -n istio-systemStep 2: Enable Sidecar Injection
Istio works by injecting an Envoy sidecar proxy into each pod. Enable it per namespace:
kubectl label namespace default istio-injection=enabledAny new pods in the default namespace will automatically get the Envoy sidecar.
Verify after deploying an app:
kubectl get podsNAME READY STATUS RESTARTS AGE
my-app-7b4f6d8c9-x2k4m 2/2 Running 0 1m
Notice 2/2 — that's your app container plus the Envoy sidecar.
Step 3: Deploy a Sample Application
Let's deploy a multi-service app to demonstrate Istio's features:
# frontend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: frontend
version: v1
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
version: v1
spec:
containers:
- name: frontend
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 80
---
# backend v1
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-v1
labels:
app: backend
version: v1
spec:
replicas: 2
selector:
matchLabels:
app: backend
version: v1
template:
metadata:
labels:
app: backend
version: v1
spec:
containers:
- name: backend
image: hashicorp/http-echo
args: ["-text=Hello from backend v1"]
ports:
- containerPort: 5678
---
# backend v2
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-v2
labels:
app: backend
version: v2
spec:
replicas: 2
selector:
matchLabels:
app: backend
version: v2
template:
metadata:
labels:
app: backend
version: v2
spec:
containers:
- name: backend
image: hashicorp/http-echo
args: ["-text=Hello from backend v2"]
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
selector:
app: backend
ports:
- port: 80
targetPort: 5678kubectl apply -f frontend.yamlStep 4: Traffic Management — Canary Deployments
Route 90% of traffic to backend v1, 10% to backend v2:
# destination-rule.yaml
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: backend
spec:
host: backend
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
---
# virtual-service.yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend
spec:
hosts:
- backend
http:
- route:
- destination:
host: backend
subset: v1
weight: 90
- destination:
host: backend
subset: v2
weight: 10kubectl apply -f destination-rule.yaml
kubectl apply -f virtual-service.yamlGradually shift traffic by updating the weights. Once v2 is validated, go to 100%:
http:
- route:
- destination:
host: backend
subset: v2
weight: 100Header-Based Routing
Route beta testers to v2:
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend
spec:
hosts:
- backend
http:
- match:
- headers:
x-beta-user:
exact: "true"
route:
- destination:
host: backend
subset: v2
- route:
- destination:
host: backend
subset: v1Step 5: mTLS — Zero-Trust Networking
Istio can enforce mutual TLS between all services automatically. Enable strict mTLS:
# peer-authentication.yaml
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: STRICTkubectl apply -f peer-authentication.yamlNow all service-to-service communication in the default namespace is encrypted with mTLS. No certificate management needed — Istio handles certificate issuance, rotation, and validation automatically through its built-in CA.
Verify mTLS is working:
istioctl x describe pod frontend-7b4f6d8c9-x2k4mPilot reports that pod is STRICT mTLS and target rules match:
backend.default.svc.cluster.local:80 -> backend (STRICT mTLS)
Authorization Policies
Restrict which services can talk to each other:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: backend-policy
namespace: default
spec:
selector:
matchLabels:
app: backend
action: ALLOW
rules:
- from:
- source:
principals:
- "cluster.local/ns/default/sa/frontend"
to:
- operation:
methods: ["GET"]
paths: ["/api/*"]Only the frontend service account can access backend, and only via GET requests to /api/*.
Step 6: Observability — Kiali, Jaeger, Prometheus
Install the observability addons:
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/addons/prometheus.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/addons/grafana.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/addons/jaeger.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/addons/kiali.yamlKiali — Service Mesh Dashboard
istioctl dashboard kialiKiali shows:
- Real-time service topology graph
- Traffic flow with request rates
- Error rates per service
- mTLS status for all connections
- Configuration validation
Jaeger — Distributed Tracing
istioctl dashboard jaegerIstio automatically adds trace headers to all requests. You can see the full request path across services without instrumenting your code.
Grafana — Metrics Dashboards
istioctl dashboard grafanaPre-built dashboards for:
- Request volume, latency, and error rates (RED metrics)
- TCP connection metrics
- Control plane performance
Step 7: Expose Services with Istio Gateway
# gateway.yaml
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: app-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "app.example.com"
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: app-tls-cert
hosts:
- "app.example.com"
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: app-routes
spec:
hosts:
- "app.example.com"
gateways:
- app-gateway
http:
- match:
- uri:
prefix: /api
route:
- destination:
host: backend
port:
number: 80
- route:
- destination:
host: frontend
port:
number: 80Step 8: Fault Injection for Testing
Test your application's resilience:
# Inject 5-second delay for 10% of requests
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend-fault
spec:
hosts:
- backend
http:
- fault:
delay:
percentage:
value: 10
fixedDelay: 5s
route:
- destination:
host: backend# Return 503 for 5% of requests
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: backend-abort
spec:
hosts:
- backend
http:
- fault:
abort:
percentage:
value: 5
httpStatus: 503
route:
- destination:
host: backendAmbient Mesh — Istio Without Sidecars
Istio 1.22+ introduced ambient mesh mode, which removes the need for sidecar proxies:
istioctl install --set profile=ambient -yInstead of injecting sidecars into every pod, ambient mesh uses:
- ztunnel — a per-node L4 proxy for mTLS and basic traffic management
- waypoint proxies — optional L7 proxies deployed only where needed
Enable ambient mode for a namespace:
kubectl label namespace default istio.io/dataplane-mode=ambientBenefits:
- No sidecar resource overhead (saves ~128 MB per pod)
- No need to restart pods when upgrading Istio
- Simpler debugging (your app only has 1 container)
- L7 features available on-demand via waypoint proxies
Production Checklist
# 1. Verify Istio health
istioctl analyze --all-namespaces
# 2. Check proxy sync status
istioctl proxy-status
# 3. Enable access logging
istioctl install --set meshConfig.accessLogFile=/dev/stdout
# 4. Set resource limits for sidecars
# In your IstioOperator or Helm values:
# proxy.resources.requests.cpu: 100m
# proxy.resources.requests.memory: 128Mi
# 5. Enable strict mTLS cluster-wide
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICT
EOFLearn More
Istio has a steep learning curve but massive payoff for microservices architectures. For structured learning, KodeKloud's Kubernetes and service mesh courses provide hands-on labs where you can practice Istio configurations safely.
For running your own Istio-enabled cluster, DigitalOcean Kubernetes offers affordable managed clusters that work well for service mesh experimentation.
Istio isn't simple. But neither is managing security, traffic, and observability for dozens of microservices without it. Pick your complexity.
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
Cilium Complete Guide: eBPF-Powered Kubernetes Networking and Security in 2026
Master Cilium — the eBPF-based CNI that's become the default for Kubernetes networking. Covers installation, network policies, Hubble observability, and service mesh mode.
How to Set Up Istio Service Mesh on Kubernetes from Scratch in 2026
Step-by-step guide to installing and configuring Istio service mesh on Kubernetes — traffic management, mTLS, observability, and canary routing with practical examples.
How to Set Up Tailscale for Zero-Trust Access to Your DevOps Infrastructure
Step-by-step guide to setting up Tailscale for secure access to Kubernetes clusters, databases, and internal tools without traditional VPNs.