I'd like to expose a virtual service in a gateway in such a way that it will respond to both grpc and REST request at the same port/host.
The discriminator between the two call mode is the Content-Type: application/json
is for REST, everything else will be for grpc.
The upstream service exposes only a grcp endpoint, so on the REST path I'd like to use the grpc transcoding filter. This is the setup:
this is my virtual service:
kind: VirtualService
metadata:
labels:
app.kubernetes.io/name: hello
app.kubernetes.io/version: "1.0"
name: hello
spec:
gateways:
- istio-system/mesh-gateway
hosts:
- 'hello.mesh.control-cluster-raffa.demo.red-chesterfield.com'
http:
- name: transcoded
match:
- name: rest-content-type
headers:
"Content-Type":
exact: "application/json"
route:
- destination:
host: hello
port:
number: 9000
- name: primary
route:
- destination:
host: hello
port:
number: 9000
I am not sure how to write the envoy filter so that it applies to only one branch of the VirtualService, but it would look somethign like this I think:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: grpc-json-transcoder
spec:
workloadSelector:
labels:
istio: ingressgateway
configPatches:
- applyTo: NETWORK_FILTER # http connection manager is a filter in Envoy
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
patch:
operation: INSERT_AFTER
value:
name: envoy.filters.http.grpc_json_transcoder
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder
proto_descriptor: "/var/config/proto/proto.pb"
services: ["hello.HelloGrpc"]
print_options:
add_whitespace: true
always_print_primitive_fields: true
always_print_enums_as_ints: false
preserve_proto_field_names: false
Here are some questions:
- this filter should be applied to the ingress-gateway. In my case the gateway is not in the same namespace as the virtual service, where does the filter goes? I assume in the envoy filter namespace.
- this gateway is share with many other services, how can I make sure that the filter does not interfere with other virtual services?
- how can I make sure that the filter applies only to the http route named "transcoded" in the virtual service?
- this filter requires reading a file, I assume this file will need to be mounted in the ingress gateway, correct?