Istio Service Mesh

Traffic Management

Demo Virtual Services

In this lesson, you will learn how to adjust traffic weight distribution between different versions of the reviews application and implement header-based routing rules. This guide details how to define application versions with Destination Rules, create a Virtual Service to manage traffic distribution, and apply advanced routing policies based on request headers.

──────────────────────────────

1. Define Destination Rules

Before modifying traffic distribution, you must define the different versions of your application using Destination Rules. Apply the default Destination Rules from the Samples directory with the following command:

kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml

Expected output:

destinationrule.networking.istio.io/productpage created
destinationrule.networking.istio.io/reviews created
destinationrule.networking.istio.io/ratings created
destinationrule.networking.istio.io/details created

Tip

Destination Rules allow Istio to control traffic policies for different versions (or subsets) of an application.

──────────────────────────────

2. Create a Virtual Service with Traffic Weight Distribution

Create a Virtual Service for the reviews application to split traffic between two subsets (v1 and v2) with a 75-25% distribution. Ensure that the total weight equals 100.

The YAML configuration below sets up the Virtual Service:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
    - route:
        - destination:
            host: reviews
            subset: v1
          weight: 75
        - destination:
            host: reviews
            subset: v2
          weight: 25

Apply the Virtual Service and verify its configuration with the commands below:

kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml
vi virtual-service1.yaml  # Edit the file if necessary
kubectl apply -f virtual-service1.yaml
istioctl analyze

You should see output similar to:

destinationrule.networking.istio.io/productpage created
destinationrule.networking.istio.io/reviews created
destinationrule.networking.istio.io/ratings created
destinationrule.networking.istio.io/details created
virtualservice.networking.istio.io/reviews created
✓ No validation issues found when analyzing namespace: default.

──────────────────────────────

3. Verify Configuration via Kiali

Switch to Kiali to inspect your Istio configurations. In Kiali, you will see that the Destination Rule for the reviews service defines three subsets (v1, v2, and v3):

kind: DestinationRule
apiVersion: networking.istio.io/v1alpha3
metadata:
  name: reviews
  namespace: default
  uid: c6c8b84c-b264-40fe-bb25-61cf563ba0bf
  resourceVersion: "9596"
  generation: 1
  creationTimestamp: '2021-08-14T00:46:09Z'
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: >
      {"apiVersion":"networking.istio.io/v1alpha3","kind":"DestinationRule","metadata":{"annotations":{},"name":"reviews"},"namespace":"default","spec":{"host":"reviews","subsets":[{"labels":{"version":"v1"},"name":"v1"},{"labels":{"version":"v2"},"name":"v2"},{"labels":{"version":"v3"},"name":"v3"}}]}
spec:
  host: reviews
  subsets:
  - labels:
      version: v1
    name: v1
  - labels:
      version: v2
    name: v2
  - labels:
      version: v3
    name: v3

The Virtual Service confirms the weight distribution as follows:

kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
  name: reviews
  namespace: default
  uid: d8d3b172-395e-47fe-8f2f-a8e9f03e015e
  resourceVersion: "9666"
  generation: 1
  creationTimestamp: "2021-08-14T00:49:11Z"
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: >
      {"apiVersion":"networking.istio.io/v1alpha3","kind":"VirtualService","metadata":{"annotations":{},"name":"reviews","namespace":"default"},"spec":{"hosts":["reviews"],"http":[{"route":[{"destination":{"host":"reviews","subset":"v1"},"weight":75},{"destination":{"host":"reviews","subset":"v2"},"weight":25}]}]}}
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 75
    - destination:
        host: reviews
        subset: v2
      weight: 25

In Kiali's visual graph, you will observe that traffic is split between v1 and v2 based on the specified weights.

──────────────────────────────

4. Testing and Adjusting Traffic Distribution

When you access the reviews application, version v1 should be more frequent than version v2, reflecting the 75-25 traffic split. This difference becomes more apparent as traffic increases.

Adjusting Weight Distribution

To modify the split—for instance, routing 99% of traffic to v1 and only 1% to v2—update the configuration as shown below:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
  namespace: default
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: >
      {"apiVersion":"networking.istio.io/v1alpha3","kind":"VirtualService","metadata":{"annotations":{},"name":"reviews","namespace":"default"},"spec":{"hosts":["reviews"],"http":[{"route":[{"destination":{"host":"reviews","subset":"v1"},"weight":99},{"destination":{"host":"reviews","subset":"v2"},"weight":1}]}]}}
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 99
    - destination:
        host: reviews
        subset: v2
      weight: 1

After applying this change, monitor the application to notice the significant traffic shift toward version v1.

Testing Tip

Consider using load testing tools to generate sufficient traffic. This helps in accurately observing the effects of different weight distributions.

──────────────────────────────

5. Routing Requests Based on Headers

In addition to traffic splitting, Virtual Services allow you to create advanced routing policies based on request headers. This feature is particularly useful if you want to serve different application versions based on user attributes.

Example 1: Routing KodeKloud Users to v2

This configuration directs requests with an "end-user" header value of "kodekloud" to subset v2, while all other requests are routed to subset v1:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
  namespace: default
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: >
      {"apiVersion":"networking.istio.io/v1alpha3","kind":"VirtualService","metadata":{"annotations":{},"name":"reviews","namespace":"default"},"spec":{"hosts":["reviews"],"http":[{"route":[{"destination":{"host":"reviews","subset":"v1"},"weight":75},{"destination":{"host":"reviews","subset":"v2"},"weight":25}]}]}}
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: kodekloud
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v1

When a KodeKloud user signs in, the "end-user" header is set to "kodekloud", and the user sees the version v2 experience (represented with a black star).

Example 2: Introducing a Test Group for a New Version

To gradually roll out a new version (v3) for test users, extend the Virtual Service with an additional match rule. In this approach:

  • Requests with "end-user: kodekloud" continue to use v2.
  • Requests with "end-user: testuser" are directed to v3.
  • All other requests default to v1.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
  namespace: default
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: >
      {"apiVersion":"networking.istio.io/v1alpha3","kind":"VirtualService","metadata":{"annotations":{},"name":"reviews"},"spec":{"hosts":["reviews"],"http":[{"route":[{"destination":{"host":"reviews","subset":"v1"},"weight":75},{"destination":{"host":"reviews","subset":"v2"},"weight":25}]}}}
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: kodekloud
    route:
    - destination:
        host: reviews
        subset: v2
  - match:
    - headers:
        end-user:
          exact: testuser
    route:
    - destination:
        host: reviews
        subset: v3
  - route:
    - destination:
        host: reviews
        subset: v1

With this configuration:

  • Requests with "end-user: kodekloud" are routed to version v2.
  • Requests with "end-user: testuser" go to the new version v3.
  • All other requests default to version v1.

When users sign in with their respective usernames, these routing rules take effect without interfering with the predefined traffic weights.

──────────────────────────────

Conclusion

Virtual Services empower you to control and manage traffic flow between different application versions seamlessly. In this lesson, you learned how to:

  • Define application versions using Destination Rules.
  • Configure weight-based traffic splitting through a Virtual Service.
  • Validate the configuration with Istio analysis tools and Kiali.
  • Implement header-based routing to tailor the user experience based on request attributes.

These strategies enable safe feature rollouts, A/B testing, and dynamic production traffic management.

For more detailed information, refer to the following resources:

Happy routing!

Watch Video

Watch video content

Practice Lab

Practice lab

Previous
Demo Gateways