Istio Gateway VirtualServices routing

8/29/2019

I'm attempting to setup a simple routing example with Istio 1.3.0-rc.0 based upon the Book Info example. I am attempting this in EKS with Kubernetes version 1.13. Here is my configuration.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: myapp-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - "*"

---
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
  labels:
    app: myapp
spec:
  ports:
    - port: 3001
      name: http
  selector:
    app: myapp

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
      version: v1
  template:
    metadata:
      labels:
        app: myapp
        version: v1
    spec:
      containers:
        - name: myapp
          image: fake-myapp:v1
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3001

---
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: fake-myapp:v2
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3001
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: myapp-destinationrule
spec:
  host: myapp-service
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2

---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: app-virtualservice
spec:
  hosts:
    - "*"
  gateways:
    - myapp-gateway
  http:
    - match:
        - uri:
            exact: /api
      route:
        - destination:
            host: myapp-service
            subset: v2

---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: myapp-virtualservice
spec:
  hosts:
    - myapp-service
  http:
    - route:
        - destination:
            host: myapp-service
            subset: v2
---

I can reach my services from the external load balancer, however, I am attempting to route traffic to only subset v2 as is defined in my VirtualServices.

However, I only get round robin balancing between the two versions of my Deployment.

I've tried the troubleshooting links which suggest adding the subset to the VirtualService that has my gateway attached, but still without any success.

I've also tried setting a host name explicitly without luck.

What am I missing?

-- duffn
istio
kubernetes

2 Answers

8/30/2019

Here are my observations particularly on the 2 VirtualService's.

  1. On the first VirtualService (app-virtualservice), the match.uri is exact with value /api. Which means request that exactly has path /api will work i.e. POST GATEWAY_URL/api, GET GATEWAY_URL/api. If you have some more extensions, e.g. POST GATEWAY_URL/api/somethingelse, then it won't fall into this routing. Kindly check on this area. If this is a problem, maybe use prefix instead of exact.
  2. On the second VirtualService (myapp-virtualservice), there is no indication of spec.gateways which would specify the gateway it will apply. Also, in this particular instance, VirtualService governs the routing for your Gateway. The DestinationRules apply for the Service (or the Envoy sidecar proxy).

Please check and see if these helps.

-- mOchi
Source: StackOverflow

9/2/2019

This behavior is quite explainable. Once you have created K8s Service pointing to the two different deployments v1 and v2, K8s runtime composes certain endpoints which are listening on the same port, therefore each time you reach application service throughout Istio mesh traffic objects path (Gateway -> Virtual service -> Destination rule -> K8s service) the request randomly hits myapp-v1, myapp-v2 nested Pods, as per user space proxy mode, which is enabled using round robin algorithm by default.

You might probably need to compose two separate k8s services for v1 and v2 deployments, targeting appropriate endpoints respectively, in order to avoid sporadic traffic routing between application parties if you are expecting to route traffic between apps, instead of splitting traffic across the service Subsets.

apiVersion: v1
kind: Service
metadata:
  name: myapp-v1-service
  labels:
    version: v1
spec:
  ports:
    - port: 3001
      name: http
  selector:
    version: v1

apiVersion: v1
    kind: Service
    metadata:
      name: myapp-v2-service
      labels:
        version: v2
    spec:
      ports:
        - port: 3001
          name: http
      selector:
        version: v2
-- mk_sta
Source: StackOverflow