Istio Hands-on Part 4 - Traffic Management with VirtualService and DestinationRule

·2 min read

Objective

This part uses two Istio resources:

  • VirtualService defines how traffic is routed.
  • DestinationRule defines where traffic can go.

You will:

  • Deploy two versions of the backend
  • Split traffic between them
  • Do a canary release
  • Inject latency and add retries

Istio Part 4

Step 1: Current state

From Part 3 you have:

  • A frontend deployment that calls backend
  • Sidecar injection enabled
  • Working frontend to backend traffic

This part adds a second backend version, v2.

Step 2: Deploy backend v1 and v2

Terminal window
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-v1
spec:
replicas: 1
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
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-v2
spec:
replicas: 1
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: 5678
EOF

Check:

Terminal window
kubectl get pods -l app=backend

Expected output:

backend-v1-xxxxx 2/2 Running
backend-v2-xxxxx 2/2 Running

Step 3: Add a DestinationRule

A DestinationRule defines subsets. A subset is a group of pods selected by label. Routing rules point at subsets.

Terminal window
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: backend
spec:
host: backend
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
EOF

Check:

Terminal window
kubectl get destinationrule

Expected output:

NAME HOST AGE
backend backend 9s

Step 4: Create a VirtualService

Start with all traffic to v1.

Route weights
v1v2
Terminal window
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
spec:
hosts:
- backend
http:
- route:
- destination:
host: backend
subset: v1
weight: 100
- destination:
host: backend
subset: v2
weight: 0
EOF

Step 5: Test the route

Terminal window
kubectl exec deploy/frontend -- curl -s http://backend

Expected output:

Hello from Backend v1

Step 6: Split traffic 80/20

Move 20% of requests to v2.

Route weights
v1v2
Terminal window
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
spec:
hosts:
- backend
http:
- route:
- destination:
host: backend
subset: v1
weight: 80
- destination:
host: backend
subset: v2
weight: 20
EOF

Send ten requests:

Terminal window
for i in {1..10}; do kubectl exec deploy/frontend -- curl -s http://backend; done

Expected output, mixed:

Hello from Backend v2
Hello from Backend v2
Hello from Backend v1
Hello from Backend v1
Hello from Backend v1
...

This is a canary release. No application code changed.

Step 7: Inject latency

Make half of the requests wait three seconds.

Terminal window
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
spec:
hosts:
- backend
http:
- fault:
delay:
percentage:
value: 50
fixedDelay: 3s
route:
- destination:
host: backend
subset: v1
weight: 100
EOF

Test with timing:

Terminal window
for i in {1..5}; do kubectl exec deploy/frontend -- time curl -s http://backend; done

About half of the requests take three seconds:

Hello from Backend v1
real 0m 3.01s
user 0m 0.00s
sys 0m 0.00s
Hello from Backend v1
real 0m 0.01s
user 0m 0.00s
sys 0m 0.00s
Hello from Backend v1
real 0m 0.00s
user 0m 0.00s
sys 0m 0.00s
Hello from Backend v1
real 0m 3.02s
user 0m 0.00s
sys 0m 0.00s
Hello from Backend v1
real 0m 0.01s
user 0m 0.00s
sys 0m 0.00s

Remove the fault rule:

Terminal window
kubectl delete virtualservice backend

Step 8: Add retries

Tell Istio to retry failed calls up to three times, with a two-second limit per try.

Terminal window
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
spec:
hosts:
- backend
http:
- retries:
attempts: 3
perTryTimeout: 2s
retryOn: gateway-error,connect-failure,refused-stream
route:
- destination:
host: backend
subset: v1
EOF

Summary

Feature Resource What it does
Traffic splitting VirtualService + DestinationRule Route a share of requests to each version
Fault injection VirtualService Add delays or errors for testing
Retries VirtualService Retry failed calls

All of this is configuration in the mesh. The application does not change. Part 5 shows how to watch this traffic with metrics and graphs.

New posts, straight to your inbox

Comments