<p>I'm wondering how I can match gRPC routes on the same port. Here's an example of what I was hoping to accomplish with my VirtualService:</p>

<pre><code>apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: istio-ingress
spec:
  hosts:
  - "*"
  gateways:
  - istio-gateway
  http:
  - match:
    - uri:
      prefix: "/custom.api/stream"
    - port: 31400
    route:
    - destination:
        host: stream-handler.default.svc.cluster.local
        port:
          number: 8444
    timeout: 60s
    retries:
      attempts: 3
      perTryTimeout: 2s
  - match:
    - port: 31400
    route:
    - destination:
        host: api.default.svc.cluster.local
        port:
          number: 8443
    timeout: 60s
    retries:
      attempts: 3
      perTryTimeout: 2s
</code></pre>

<p>So basically: for all requests into 31400 the first match looks for requests to stream at "/custom.api/stream" which has a destination of my stream server.</p>

<p>The second rule as a catch all to gain entry to my main API.</p>

<p>My goal is to have all connections coming through 31400 and then splinter off the request to a dedicated internal service. In the future I'll likely split off services even further (not just for streaming). ie. entire groups of the endpoint might be handled by separate clusters.</p>

<p>When I deploy this rule though the whole VS seems to fail and nothing responds.</p>

ddibiase
<p>Ports are externally exposed in the <code>Ingressgateway</code> and should be internally configured using a <code>Gateway</code>. The <code>VirtualService</code> is intended for layer 7 routing only (once attached to a <code>Gateway</code>).</p>

<p>In your <em><code>match</code></em> configuration, you're specifying that the <em>addressed</em> host should receive requests in the port 31400, not that the service is listening there. From <a href="https://istio.io/docs/reference/config/networking/v1alpha3/virtual-service/#HTTPMatchRequest" rel="nofollow noreferrer">the documentation</a>:</p>

<blockquote>
  <p><strong>port</strong>: Specifies the ports on the host that is being addressed. Many services only expose a single port or label ports with the protocols they support, in these cases it is not required to explicitly select the port.</p>
</blockquote>

<p>In your case, you might want to create a new <code>Gateway</code> to take care of the exposed port's configuration and then, attach the routing part using your <code>VirtualService</code>:</p>

<pre><code>apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: grpc-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 31400
      name: grpc
      protocol: GRPC
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: grpc-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - grcp-gateway
  http:
  - match:
    - uri:
      exact: "/custom.api/stream"
    route:
    - destination:
        host: stream-handler.default.svc.cluster.local
        port:
          number: 8444
    timeout: 60s
    retries:
      attempts: 3
      perTryTimeout: 2s
  - match:
    - uri:
      prefix: "/"
    route:
    - destination:
        host: api.default.svc.cluster.local
        port:
          number: 8443
    timeout: 60s
    retries:
      attempts: 3
      perTryTimeout: 2s
</code></pre>

<p>Since <code>match</code> <a href="https://istio.io/docs/reference/config/networking/v1alpha3/virtual-service/#HTTPMatchRequest" rel="nofollow noreferrer">cannot be empty</a>, you need to <em>prefix it</em> to pick up whatever is coming except for the previous URI <em>exact</em> match.</p>
