0
votes

I need to define two VirtualService for same host, .i.e.

host: http://customerA.test.example.com, would be used to serve two service namely "srv" and "srvui"

To Achieve this I respectively, defined Virtual Service as:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: srv
  namespace: srv-test01
spec:
  gateways:
  - http-gateway
  hosts:
  - customerA.test.example.com
  http:
  - match:
    - uri:
        prefix: /srv
    route:
    - destination:
        host: srv.srv-test01.svc.cluster.local
        port:
          number: 8080

and

 apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: srvui
      namespace: srv-test01
    spec:
      gateways:
      - http-gateway
      hosts:
      - customerA.test.example.com
      http:
      - match:
        - uri:
            prefix: /srvui
        route:
        - destination:
            host: srvui.srv-test01.svc.cluster.local
            port:
              number: 8080

This has resulted in envoy conf on istio-ingress-gateway as (both virtualService are in same namespace)

"name": "customerA.test.example.com:80",
        "domains": [
         "customerA.test.example.com",
         "customerA.test.example.com:80"
        ],
        "routes": [
         {
          "match": {
           "prefix": "/srv"
          },
          "route": {
           "cluster": "outbound|8080||srv.srv-test01.svc.cluster.local",
           "timeout": "0s",
           "max_grpc_timeout": "0s"
          },
          "decorator": {
           "operation": "srv.srv-test01.svc.cluster.local:8080/srv*"
          },
          "per_filter_config": {
           "mixer": {
            "forward_attributes": {
             "attributes": {
              "destination.service.host": {
               "string_value": "srv.srv-test01.svc.cluster.local"
              },
              "destination.service.uid": {
               "string_value": "istio://srv-test01/services/srv"
              },
              "destination.service.namespace": {
               "string_value": "srv-test01"
              },
              "destination.service.name": {
               "string_value": "srv"
              },
              "destination.service": {
               "string_value": "srv.srv-test01.svc.cluster.local"
              }
             }
            },
            "mixer_attributes": {
             "attributes": {
              "destination.service.host": {
               "string_value": "srv.srv-test01.svc.cluster.local"
              },
              "destination.service.uid": {
               "string_value": "istio://srv-test01/services/srv"
              },
              "destination.service.name": {
               "string_value": "srv"
              },
              "destination.service.namespace": {
               "string_value": "srv-test01"
              },
              "destination.service": {
               "string_value": "srv.srv-test01.svc.cluster.local"
              }
             }
            }
           }
          }
         },
         {
          "match": {
           "prefix": "/srvui"
          },
          "route": {
           "cluster": "outbound|8080||srvui.srv-test01.svc.cluster.local",
           "timeout": "0s",
           "max_grpc_timeout": "0s"
          },
          "decorator": {
           "operation": "srvui.srv-test01.svc.cluster.local:8080/srvui*"
          },
          "per_filter_config": {
           "mixer": {
            "forward_attributes": {
             "attributes": {
              "destination.service.namespace": {
               "string_value": "srv-test01"
              },
              "destination.service.name": {
               "string_value": "srvui"
              },
              "destination.service": {
               "string_value": "srvui.srv-test01.svc.cluster.local"
              },
              "destination.service.host": {
               "string_value": "srvui.srv-test01.svc.cluster.local"
              },
              "destination.service.uid": {
               "string_value": "istio://srv-test01/services/srv"
              }
             }
            },
            "mixer_attributes": {
             "attributes": {
              "destination.service.host": {
               "string_value": "srvui.srv-test01.svc.cluster.local"
              },
              "destination.service.uid": {
               "string_value": "istio://srv-test01/services/srv"
              },
              "destination.service.name": {
               "string_value": "srvui"
              },
              "destination.service.namespace": {
               "string_value": "srv-test01"
              },
              "destination.service": {
               "string_value": "srvui.srv-test01.svc.cluster.local"
              }
             }
            }
           }
          }
         }
        ]
       },

However the problem here is that even the request coming for /srvui are ending up on /srv virtual-service, logs on istio-ingress-gateway

[2019-02-04T05:46:20.822Z] "**GET /srvHTTP/1.1**" 404 - 0 1077 3 2 "xx.xx.xx.xx, xx.xx.xx.xx" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" "5fa6611c-07ab-954c-b871-09398bd6c2e4" "customerA.test.example.com" "10.192.21.210:8080" outbound|8080||srv.srv-test01.svc.cluster.local - 10.192.11.185:80 10.192.20.101:36536  ---> **end up on correct service on backend as per virtualService defination**



[2019-02-04T05:46:40.864Z] "**GET /srvuiHTTP/1.1**" 404 - 0 1079 3 1 "xx.xx.xx.xx, 10.192.10.101" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" "58e17520-a5df-9c90-9ec4-62dbc2bc1307" "customerA.test.example.com" "10.192.21.210:8080" outbound|8080||srv.srv-test01.svc.cluster.local - 10.192.11.185:80 10.192.10.101:54352  ---> Even the context is srvui it is ending up on srv backend.

it looks like it depends on the numbering of VirtualService in its conf for the routing to take effect,

if we configure srvui virtualService first and then srv routing happens correctly.

however the problem with it, we need to maintain the deployment of these service in numbered order, which I would like to avoid

I cannot use "exact" in place of "prefix", because then I would need to defined more than 100 exact URI path

Other solution is to change the name of the service context so that they do not look like subset of each other like here srv and srvui and thus istio-ingress-gateway can route it properly ,however this also require application change.

kindly let me know if there is any other solution, I could implement here.

1

1 Answers

3
votes

That's not surprising as srv is a subset of srvui.

You should be able to use a regex match instead of either exact or prefix. See https://istio.io/docs/reference/config/istio.networking.v1alpha3/#HTTPMatchRequest for more full documentation.

URI to match values are case-sensitive and formatted as follows:

  • exact: "value" for exact string match
  • prefix: "value" for prefix-based match
  • regex: "value" for ECMAscript style regex-based match