Introduction
As applications evolve, releasing new versions safely is crucial. Traditional deployment methods often risk downtime or entire system failures if a new release is faulty. Canary deployments allow gradual rollout of new versions while monitoring performance.
With Istio, we can implement traffic splitting to control how much traffic goes to each version, ensuring a smooth transition without disruptions.
In this post, we’ll walk through:
Setting up Istio in Minikube
Deploying two versions of an app
Using Istio’s VirtualService and DestinationRule for canary rollout
Step 1: Install and Configure Istio in Minikube
Since we are working in a local Minikube cluster, first enable Istio:
minikube start
istioctl install --set profile=demo -y
kubectl label namespace default istio-injection=enabled
The istio-injection=enabled label ensures that Istio automatically injects sidecar proxies into our pods.
Step 2: Deploy Application Versions
We’ll deploy two versions of our application (v1 and v2).
Create myapp:v1 Deployment
Save the following YAML as deployment-v1.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v1
spec:
replicas: 2
selector:
matchLabels:
app: myapp
version: v1
template:
metadata:
labels:
app: myapp
version: v1
spec:
containers:
- name: myapp
image: myapp:v1 # Using locally built image
ports:
- containerPort: 80
Create myapp:v2 Deployment
Save the following YAML as deployment-v2.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v2
spec:
replicas: 1
selector:
matchLabels:
app: myapp
version: v2
template:
metadata:
labels:
app: myapp
version: v2
spec:
containers:
- name: myapp
image: myapp:v2 # Using locally built image
ports:
- containerPort: 80
Apply both deployments:
kubectl apply -f deployment-v1.yaml
kubectl apply -f deployment-v2.yaml
Step 3: Define an Istio Service
We need a service to route traffic to both versions.
Save the following as service.yaml:
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 80
Apply the service:
kubectl apply -f service.yaml
Step 4: Create Istio VirtualService for Traffic Splitting
Now, let’s configure Istio to split traffic between v1 and v2.
Save the following YAML as virtual-service.yaml:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- route:
- destination:
host: myapp
subset: v1
weight: 80
- destination:
host: myapp
subset: v2
weight: 20
This configuration sends 80% of traffic to v1 and 20% to v2.
Apply the VirtualService:
kubectl apply -f virtual-service.yaml
Step 5: Define an Istio DestinationRule
To allow version-based routing, we need a DestinationRule.
Save the following YAML as destination-rule.yaml:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: myapp
spec:
host: myapp
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
Apply the DestinationRule:
kubectl apply -f destination-rule.yaml
Step 6: Test Traffic Splitting
Now, let’s check the traffic distribution:
kubectl run -it --rm --image=curlimages/curl test -- curl http://myapp
Run this multiple times—you should see 80% responses from v1 and 20% from v2.
Conclusion
By implementing Istio’s VirtualService and DestinationRule, we successfully built a canary deployment that gradually rolls out a new version without impacting all users at once.
Key Takeaways:
Istio simplifies traffic control for Kubernetes applications.
Canary deployments allow safe testing of new versions.
Traffic splitting can be adjusted dynamically as confidence in v2 increases.
This approach ensures zero downtime deployments, improving stability and user experience.
What’s your experience with Istio? Drop a comment below!![]()