I have managed to run one grpc service in a root path. But I tried to add more grpc service by adding custom path route in virtual service which doesn't work. Any help would be highly appreciated.
This is the gateway:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
I have this virtual service routing to only one grpc service and is working fine
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-virtual-svc
spec:
hosts:
- "*"
gateways:
- my-gateway
http:
- name: "my-grpc-1"
match:
- uri:
prefix: "/"
route:
- destination:
port:
number: 9090
host: my-grpc-1-svc
But I wanted to try something like below but it is not working
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-virtual-svc
spec:
hosts:
- "*"
gateways:
- my-gateway
http:
- name: "my-grpc-1"
match:
- uri:
prefix: "/my-grpc-1"
route:
- destination:
port:
number: 9090
host: my-grpc-1-svc
- name: "my-grpc-2"
match:
- uri:
prefix: "/my-grpc-2"
route:
- destination:
port:
number: 9090
host: my-grpc-2-svc
That´s probably does not work because your app listen on /
and with your first virtual service, which works, istio send requests to /
, which is not happening with your second virtual service.
The answer here would be to add rewrite to your second virtual service.
HTTPRewrite can be used to rewrite specific parts of a HTTP request before forwarding the request to the destination. Rewrite primitive can be used only with HTTPRouteDestination. The following example demonstrates how to rewrite the URL prefix for api call (/ratings) to ratings service before making the actual API call.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings-route
spec:
hosts:
- ratings.prod.svc.cluster.local
http:
- match:
- uri:
prefix: /ratings
rewrite:
uri: /v1/bookRatings
route:
- destination:
host: ratings.prod.svc.cluster.local
subset: v1
so it would look like this
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-virtual-svc
spec:
hosts:
- "*"
gateways:
- my-gateway
http:
- name: "my-grpc-1"
match:
- uri:
prefix: "/my-grpc-1"
rewrite:
uri: "/"
route:
- destination:
port:
number: 9090
host: my-grpc-1-svc
- name: "my-grpc-2"
match:
- uri:
prefix: "/my-grpc-2"
rewrite:
uri: "/"
route:
- destination:
port:
number: 9090
host: my-grpc-2-svc
Related documentation about it is here.
I think you could try to do it with FQN of the gRPC services as mentioned in this github issue comment
Another idea would be to use nginx like mentioned here.
Convenient way for routing grpc is Ingress. But it needs to add some settings for ngnix:
If you prefer to forward encrypted traffic to your POD and terminate TLS at the gRPC server itself, add the ingress annotation \ nginx.ingress.kubernetes.io/backend-protocol: "GRPCS".
or else
Note that gRPC services must be specified as backend services. nginx.ingress.kubernetes.io/grpc-backend: "true"
Here are some tips when working with grpc and istio (tested with istio 1.9.2).
1.Set protocol in service:
kind: Service
metadata:
name: my-grpc-service
spec:
ports:
- number: 9009
appProtocol: grpc
2.set protocol in gateway:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-gateway
spec:
servers:
- port:
number: 80
name: grpc
protocol: GRPC
hosts:
- "*"
3.grpc generated uri path prefix will be the same as package
value in .proto file:
syntax = "proto3";
package somepath;
use it as match.uri.prefix
:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-virtual-svc
spec:
http:
- name: "my-grpc-1"
match:
- uri:
prefix: "/somepath"