One of the most powerful features of Istio is to manage the traffic within your service mesh dynamically. In this part of the tutorial, we'll deploy a new version for our service and use it to take a look some of the different traffic management features of Istio.
Let's modify our existing Hello World app to print a different message as the new version of the service. In Startup.cs change the message to print v2
:
await context.Response.WriteAsync("Hello World v2!");
Build and push the Docker image for v2 (replace meteatamel
with your actual DockerHub):
docker build -t meteatamel/istio-helloworld-csharp:v2 .
docker push meteatamel/istio-helloworld-csharp:v2
We're now ready to deploy v2 to our Service Mesh. We need to first create a Kubernetes deployment for the new service. Inside the istio
folder, create service-v1v2.yaml file:
apiVersion: v1
kind: Service
metadata:
name: helloworld-csharp-service
labels:
app: helloworld-csharp
spec:
ports:
- port: 8080
name: http
selector:
app: helloworld-csharp
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: helloworld-csharp-deployment-v1
spec:
replicas: 1
template:
metadata:
labels:
app: helloworld-csharp
version: v1
spec:
containers:
- name: helloworld-csharp
# Replace meteatamel with your actual DockerHub
image: meteatamel/istio-helloworld-csharp:v1
imagePullPolicy: Always #IfNotPresent
ports:
- containerPort: 8080
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: helloworld-csharp-deployment-v2
spec:
replicas: 1
template:
metadata:
labels:
app: helloworld-csharp
version: v2
spec:
containers:
- name: helloworld-csharp
# Replace meteatamel with your actual DockerHub
image: meteatamel/istio-helloworld-csharp:v2
imagePullPolicy: Always #IfNotPresent
ports:
- containerPort: 8080
This creates a new deployment for v2
. Let's deploy it:
kubectl apply -f service-v1v2.yaml
service "helloworld-csharp-service" unchanged
deployment.extensions "helloworld-csharp-deployment-v1" unchanged
deployment.extensions "helloworld-csharp-deployment-v2" created
Wait for pods to be initialized for v2
. Once all pods are ready, ping GATEWAY_URL:
curl "http://${GATEWAY_URL}"
Hello World!
curl "http://${GATEWAY_URL}"
xs
Hello World v2!
Notice how the response is rotating between v1
and v2
. This is because both deployments are behind the same Kubernetes service that is exposed behind the Istio Gateway.
What if you want to pin down to a specific version of the service? For example, let's make our service only use v2
deployment. That's quite easy to do in Istio. You need a couple of things to set this up. First, you need a DestionationRule to define what's called a subset
for each version. Then, you need to update the VirtualService to point to v2
subset.
To create the subsets, create destinationrule.yaml file inside istio
folder:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: helloworld-csharp-destinationrule
spec:
host: helloworld-csharp-service
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
Notice how the DestinationRule associates Kubernetes labels with subset names.
Create the DestionationRule:
kubectl apply -f destinationrule.yaml
destinationrule.networking.istio.io "helloworld-csharp-destinationrule" created
Finally, let's point the VirtualService to v2
subset. Create virtualservice-v2.yaml file inside istio
folder:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld-csharp-virtualservice
spec:
hosts:
- "*"
gateways:
- helloworld-csharp-gateway
http:
- route:
- destination:
host: helloworld-csharp-service
subset: v2
Update the VirtualService:
kubectl apply -f virtualservice-v2.yaml
virtualservice.networking.istio.io "helloworld-csharp-virtualservice" configured
Now, if we now ping the GATEWAY_URL, it will always get a response from v2
:
curl "http://${GATEWAY_URL}"
Hello World v2!
Sometimes, you might want to split traffic between versions for testing. For example, you might want to send 75% of the traffic to the v1
and 25% of the traffic to the v2
version of the service. You can easily achieve this with Istio.
Create a new Create virtualservice-weights.yaml file inside istio
folder file to refer to the two subsets with different weights:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld-csharp-virtualservice
spec:
hosts:
- "*"
gateways:
- helloworld-csharp-gateway
http:
- route:
- destination:
host: helloworld-csharp-service
subset: v1
weight: 75
- destination:
host: helloworld-csharp-service
subset: v2
weight: 25
Update the VirtualService:
kubectl apply -f virtualservice-weights.yaml
virtualservice.networking.istio.io "helloworld-csharp-virtualservice" configured
Now, we'll get a response mostly from v1
and sometimes from v2
.
Another useful development task to do for testing is to inject faults or delays into the traffic and see how services behave in response.
For example, you might want to return a bad request (HTTP 400) response for 50% of the traffic to v1
. Create virtualservice-fault-abort.yaml file:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld-csharp-virtualservice
spec:
hosts:
- "*"
gateways:
- helloworld-csharp-gateway
http:
- fault:
abort:
percent: 50
httpStatus: 400
route:
- destination:
host: helloworld-csharp-service
subset: v1
Update the VirtualService:
kubectl apply -f virtualservice-fault-abort.yaml
virtualservice.networking.istio.io "helloworld-csharp-virtualservice" configured
Now, we'll get HTTP 400 errors from v1
half of the time:
curl "http://${GATEWAY_URL}"
fault filter abort
Or you might want to add 5 seconds delay to all requests. Create virtualservice-fault-delay.yaml file:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld-csharp-virtualservice
spec:
hosts:
- "*"
gateways:
- helloworld-csharp-gateway
http:
- fault:
delay:
fixedDelay: 5s
percent: 100
route:
- destination:
host: helloworld-csharp-service
subset: v1
Update the VirtualService:
kubectl apply -f virtualservice-fault-delay.yaml
virtualservice.networking.istio.io "helloworld-csharp-virtualservice" configured
And you'll see responses delay 5s all the time!
This concludes our tutorial. In the next step, we'll cleanup resources.