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:
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
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.
The second rule as a catch all to gain entry to my main API.
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.
When I deploy this rule though the whole VS seems to fail and nothing responds.
Here are my observations:
http.match.port
. I don't think port
is used correctly here. If this is supposed to indicate the listening to incoming requests to port 31400, then this should actually be in the Gateway YAML specification istio-gateway
.istio-gateway
. Basically, it is there where you specify that you are listening to port.number: 31400
. The VirtualService is where you indicate to which service/host and port you want to route or "splinter off the request".Please check and see if it helps.
Ports are externally exposed in the Ingressgateway
and should be internally configured using a Gateway
. The VirtualService
is intended for layer 7 routing only (once attached to a Gateway
).
In your match
configuration, you're specifying that the addressed host should receive requests in the port 31400, not that the service is listening there. From the documentation:
port: 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.
In your case, you might want to create a new Gateway
to take care of the exposed port's configuration and then, attach the routing part using your VirtualService
:
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
Since match
cannot be empty, you need to prefix it to pick up whatever is coming except for the previous URI exact match.