Module 2: Exercises
This exercise section provides hands-on practice with Istio traffic management. You will learn how to configure Gateways, create VirtualServices with various routing patterns, implement path-based routing, perform weighted traffic splitting, and combine these components for complete traffic control.
Prerequisites
Before starting these exercises, ensure you have:
-
Access to an OpenShift cluster with Service Mesh 3 (Istio >= 1.23) installed
-
Your namespace (
$NAMESPACE) configured with sidecar injection enabled (from Module 1) -
The
ocCLI tool installed and configured -
Basic understanding of Kubernetes Services and Deployments
Exercise 1: Create and Configure a Gateway
In this exercise, you will create a Gateway resource to allow external traffic into your service mesh.
Step 1: Set Your Namespace
Ensure your namespace variable is set:
export NAMESPACE={USER}-sandbox
Verify the namespace exists and has sidecar injection enabled:
oc get namespace $NAMESPACE --show-labels | grep istio.io/rev
Step 2: Verify Istio Ingress Gateway
Check that the Istio ingress gateway is running:
oc get pods -n istio-system -l app=istio-ingressgateway
Note the service name and external access method:
oc get svc -n istio-system istio-ingressgateway
Step 3: Create a Basic Gateway
Create a Gateway that accepts HTTP traffic on port 80:
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: my-gateway
namespace: ${NAMESPACE}
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
EOF
Step 4: Verify Gateway Creation
Verify the Gateway was created successfully:
oc get gateway -n $NAMESPACE
View the Gateway configuration:
oc get gateway my-gateway -n $NAMESPACE -o yaml
Step 5: Create a Gateway with HTTPS
Create an additional Gateway that accepts HTTPS traffic on port 443:
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: my-https-gateway
namespace: ${NAMESPACE}
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: my-tls-secret
hosts:
- "myapp.example.com"
EOF
| In a production environment, you would need to create the TLS secret referenced in the Gateway configuration. |
Exercise 2: Create VirtualServices with Basic Routing
In this exercise, you will create VirtualServices to route traffic to your services.
Step 1: Deploy Sample Applications
Deploy two sample applications to use for routing:
oc apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: ${NAMESPACE}
spec:
replicas: 2
selector:
matchLabels:
app: frontend
version: v1
template:
metadata:
labels:
app: frontend
version: v1
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: frontend
namespace: ${NAMESPACE}
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 80
name: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: ${NAMESPACE}
spec:
replicas: 2
selector:
matchLabels:
app: backend
version: v1
template:
metadata:
labels:
app: backend
version: v1
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: ${NAMESPACE}
spec:
selector:
app: backend
ports:
- port: 80
targetPort: 80
name: http
EOF
Wait for the pods to be ready:
oc get pods -n $NAMESPACE -l app=frontend
oc get pods -n $NAMESPACE -l app=backend
Step 2: Create a Basic VirtualService
Create a VirtualService that routes all traffic to the frontend service:
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: frontend
namespace: ${NAMESPACE}
spec:
hosts:
- frontend
http:
- route:
- destination:
host: frontend
weight: 100
EOF
Exercise 3: Implement Path-Based Routing
In this exercise, you will create a VirtualService that routes traffic based on URI paths.
Step 1: Create a Path-Based VirtualService
Create a VirtualService that routes different paths to different services:
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp
namespace: ${NAMESPACE}
spec:
hosts:
- myapp.example.com
gateways:
- my-gateway
http:
- match:
- uri:
prefix: "/api"
route:
- destination:
host: backend
weight: 100
- match:
- uri:
prefix: "/"
route:
- destination:
host: frontend
weight: 100
EOF
This VirtualService:
* Routes requests to /api/* to the backend service
* Routes all other requests to the frontend service
Step 2: Verify Path-Based Routing
Check the VirtualService configuration:
oc get virtualservice myapp -n $NAMESPACE -o yaml
Step 3: Test Path-Based Routing
Get the ingress gateway external address:
INGRESS_HOST=$(oc get svc -n istio-system istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
echo $INGRESS_HOST
If no external address is available, you can use port-forwarding:
oc port-forward -n istio-system svc/istio-ingressgateway 8080:80 &
Test the frontend route:
curl -H "Host: myapp.example.com" http://localhost:8080/
Test the backend API route:
curl -H "Host: myapp.example.com" http://localhost:8080/api
Step 4: Create More Complex Path Matching
Create a VirtualService with multiple path patterns:
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: complex-routing
namespace: ${NAMESPACE}
spec:
hosts:
- complex.example.com
gateways:
- my-gateway
http:
- match:
- uri:
exact: "/api/v1/users"
route:
- destination:
host: backend
weight: 100
- match:
- uri:
prefix: "/api/v2"
route:
- destination:
host: backend
weight: 100
- match:
- uri:
regex: "^/static/.*\\.(jpg|png|gif)$"
route:
- destination:
host: frontend
weight: 100
- route:
- destination:
host: frontend
weight: 100
EOF
This example demonstrates:
* Exact path matching (/api/v1/users)
* Prefix matching (/api/v2/*)
* Regex matching (static image files)
* Default route (catch-all)
Exercise 4: Implement Weighted Traffic Splitting
In this exercise, you will implement weighted traffic splitting for canary deployments.
Step 1: Deploy Multiple Versions
Deploy a second version of the frontend application:
oc apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-v2
namespace: ${NAMESPACE}
spec:
replicas: 2
selector:
matchLabels:
app: frontend
version: v2
template:
metadata:
labels:
app: frontend
version: v2
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
EOF
Wait for the new pods to be ready:
oc get pods -n $NAMESPACE -l app=frontend
Step 2: Create DestinationRule with Subsets
Create a DestinationRule to define service subsets (versions):
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: frontend
namespace: ${NAMESPACE}
spec:
host: frontend
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
EOF
Verify the DestinationRule:
oc get destinationrule -n $NAMESPACE
oc get destinationrule frontend -n $NAMESPACE -o yaml
Step 3: Create VirtualService with Weighted Splitting
Create a VirtualService that splits traffic 90% to v1 and 10% to v2:
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: frontend-canary
namespace: ${NAMESPACE}
spec:
hosts:
- frontend
http:
- route:
- destination:
host: frontend
subset: v1
weight: 90
- destination:
host: frontend
subset: v2
weight: 10
EOF
Step 4: Test Weighted Traffic Splitting
Send multiple requests and observe the traffic distribution. You can check the Envoy access logs to see which version receives each request:
for i in {1..20}; do
oc run curl-test-$i --image=curlimages/curl:latest --rm -i --restart=Never -n $NAMESPACE -- curl -s http://frontend > /dev/null
done
Check the logs to see traffic distribution:
oc logs -n $NAMESPACE -l app=frontend,version=v1 -c istio-proxy --tail=10
oc logs -n $NAMESPACE -l app=frontend,version=v2 -c istio-proxy --tail=10
Step 5: Adjust Traffic Weights
Update the VirtualService to increase traffic to v2 (50/50 split):
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: frontend-canary
namespace: ${NAMESPACE}
spec:
hosts:
- frontend
http:
- route:
- destination:
host: frontend
subset: v1
weight: 50
- destination:
host: frontend
subset: v2
weight: 50
EOF
Step 6: Complete Canary Deployment
Finally, route 100% of traffic to v2:
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: frontend-canary
namespace: ${NAMESPACE}
spec:
hosts:
- frontend
http:
- route:
- destination:
host: frontend
subset: v2
weight: 100
EOF
Exercise 5: Combine Gateway and VirtualService
In this exercise, you will combine a Gateway and VirtualService to provide complete external access to your services.
Step 1: Create a Complete Gateway Configuration
Ensure you have a Gateway that accepts traffic for your application:
oc get gateway my-gateway -n $NAMESPACE
If it doesn’t exist, create it:
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: my-gateway
namespace: ${NAMESPACE}
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "myapp.example.com"
EOF
Step 2: Create VirtualService for Gateway
Create a VirtualService that works with the Gateway to route external traffic:
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp-external
namespace: ${NAMESPACE}
spec:
hosts:
- myapp.example.com
gateways:
- my-gateway
http:
- match:
- uri:
prefix: "/api"
route:
- destination:
host: backend
port:
number: 80
weight: 100
- route:
- destination:
host: frontend
port:
number: 80
weight: 100
EOF
Step 3: Verify Gateway and VirtualService Integration
Check both resources:
oc get gateway,virtualservice -n $NAMESPACE
View the complete configuration:
oc get gateway my-gateway -n $NAMESPACE -o yaml
oc get virtualservice myapp-external -n $NAMESPACE -o yaml
Step 4: Test External Access
Get the ingress gateway address:
INGRESS_HOST=$(oc get svc -n istio-system istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
INGRESS_PORT=$(oc get svc -n istio-system istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
If using port-forwarding:
oc port-forward -n istio-system svc/istio-ingressgateway 8080:80 &
Test the frontend:
curl -H "Host: myapp.example.com" http://localhost:8080/
Test the API:
curl -H "Host: myapp.example.com" http://localhost:8080/api
Step 5: Add Header-Based Routing
Enhance the VirtualService to include header-based routing:
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp-external
namespace: ${NAMESPACE}
spec:
hosts:
- myapp.example.com
gateways:
- my-gateway
http:
- match:
- headers:
x-canary:
exact: "true"
route:
- destination:
host: frontend
subset: v2
weight: 100
- match:
- uri:
prefix: "/api"
route:
- destination:
host: backend
port:
number: 80
weight: 100
- route:
- destination:
host: frontend
port:
number: 80
weight: 100
EOF
Test with the canary header:
curl -H "Host: myapp.example.com" -H "x-canary: true" http://localhost:8080/
Summary
In these exercises, you have:
-
Created and configured Gateways to accept external traffic
-
Created VirtualServices with basic routing patterns
-
Implemented path-based routing to direct traffic based on URI paths
-
Configured weighted traffic splitting for canary deployments
-
Combined Gateways and VirtualServices for complete external traffic management
-
Used DestinationRules to define service subsets for version-based routing
These skills form the foundation of Istio traffic management and are essential for implementing advanced deployment strategies in production environments.
Troubleshooting
If you encounter issues:
-
Gateway not accepting traffic: Verify the Gateway selector matches your ingress gateway pods and check that the gateway pods are running
-
VirtualService not routing: Ensure the VirtualService hosts match the Gateway hosts, and verify the destination services exist
-
Traffic not splitting correctly: Check that DestinationRule subsets match the pod labels, and verify the weight percentages sum to 100
-
External access not working: Verify the ingress gateway service has an external IP or use port-forwarding for testing
-
Path matching not working: Check the match conditions are correct and that routes are ordered properly (most specific first)