How To Route Traffic Between Service Versions Using Istio.

Overview
Organizations deploying microservices often need to safely roll out new versions of applications (e.g., ML models, APIs) without disrupting users. Istio, a service mesh for Kubernetes, enables precise traffic control between different service versions using:
Canary Deployments (gradual traffic shift)
A/B Testing (user-segmented routing)
Blue-Green Deployments (instant cutover)
This guide demonstrates how to route traffic between two service versions (v1 and v2) using Istio’s VirtualService
and DestinationRule.
Prerequisites
A running Kubernetes cluster (Minikube, AKS, EKS, or GKE)
Istio installed (
istioctl install --set profile=demo -y
)kubectl
andistioctl
configured
Step 1: Deploy the Sample Application
We’ll use a simple HTTP service (http-echo
) that returns its version.
1.1 Deploy v1 and v2
# echo-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-v1
spec:
replicas: 1
selector:
matchLabels:
app: echo
version: v1
template:
metadata:
labels:
app: echo
version: v1
spec:
containers:
- name: echo
image: hashicorp/http-echo
args: ["-text=Response from v1"]
ports:
- containerPort: 5678
# echo-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-v2
spec:
replicas: 1
selector:
matchLabels:
app: echo
version: v2
template:
metadata:
labels:
app: echo
version: v2
spec:
containers:
- name: echo
image: hashicorp/http-echo
args: ["-text=Response from v2"]
ports:
- containerPort: 5678
Apply the deployments:
kubectl apply -f echo-v1.yaml -f echo-v2.yaml
1.2 Create a Kubernetes Service
# echo-service.yaml
apiVersion: v1
kind: Service
metadata:
name: echo-service
spec:
ports:
- port: 80
targetPort: 5678
protocol: TCP
name: http
selector:
app: echo
Apply the service:
kubectl apply -f echo-service.yaml
Step 2: Configure Istio Traffic Routing
2.1 Enable Automatic Sidecar Injection
kubectl label namespace default istio-injection=enabled
2.2 Define DestinationRule (Subsets for v1 and v2)
# echo-dr.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: echo-dr
spec:
host: echo-service
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
2.3 Configure VirtualService (90% v1, 10% v2)
# echo-vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: echo-vs
spec:
hosts:
- echo-service
http:
- route:
- destination:
host: echo-service
subset: v1
weight: 90
- destination:
host: echo-service
subset: v2
weight: 10
Apply Istio rules:
kubectl apply -f echo-dr.yaml -f echo-vs.yaml
Step 3: Verify Traffic Distribution
3.1 Test Using curl Inside Cluster
for i in {1..10}; do
kubectl exec -it $(kubectl get pod -l app=echo -o jsonpath='{.items[0].metadata.name}') -c istio-proxy -- curl -s echo-service
done
Expected Output:
~9 responses:
Response from v1
~1 response:
Response from v2
3.2 Monitor Traffic in Kiali
istioctl dashboard kiali
Open
http://localhost:20001
Navigate to Graph → echo-service to visualize traffic distribution.
Step 4: Adjust Traffic Weights (Optional)
To shift more load to v2
, modify echo-vs.yaml
:
http:
- route:
- destination:
host: echo-service
subset: v1
weight: 50
- destination:
host: echo-service
subset: v2
weight: 50
Reapply:
kubectl apply -f echo-vs.yaml
Conclusion
By following this approach, teams can:
Safely roll out updates (Canary)
Test new versions with select users (A/B)
Monitor traffic in real-time (Kiali, Prometheus)
For header-based routing (A/B testing) or mirroring traffic, refer to the Istio documentation.
Next Steps:
Explore fault injection for resilience testing.
Implement mTLS for secure service communication.
Subscribe to my newsletter
Read articles from Gloria Anwan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
