github.com/projectcontour/contour@v1.28.2/site/content/docs/1.26/guides/grpc.md (about) 1 --- 2 title: Configuring ingress to gRPC services with Contour 3 --- 4 5 ## Example gRPC Service 6 7 The below examples use the [gRPC server][1] used in Contour end to end tests. 8 The server implements a service `yages.Echo` with two methods `Ping` and `Reverse`. 9 It also implements the [gRPC health checking service][2] (see [here][3] for more details) and is bundled with the [gRPC health probe][4]. 10 11 An example base deployment and service for a gRPC server utilizing plaintext HTTP/2 are provided here: 12 13 ```yaml 14 --- 15 apiVersion: apps/v1 16 kind: Deployment 17 metadata: 18 labels: 19 app.kubernetes.io/name: grpc-echo 20 name: grpc-echo 21 spec: 22 replicas: 2 23 selector: 24 matchLabels: 25 app.kubernetes.io/name: grpc-echo 26 template: 27 metadata: 28 labels: 29 app.kubernetes.io/name: grpc-echo 30 spec: 31 containers: 32 - name: grpc-echo 33 image: ghcr.io/projectcontour/yages:v0.1.0 34 ports: 35 - name: grpc 36 containerPort: 9000 37 readinessProbe: 38 exec: 39 command: ["/grpc-health-probe", "-addr=localhost:9000"] 40 --- 41 apiVersion: v1 42 kind: Service 43 metadata: 44 labels: 45 app.kubernetes.io/name: grpc-echo 46 name: grpc-echo 47 spec: 48 selector: 49 app.kubernetes.io/name: grpc-echo 50 ports: 51 - port: 9000 52 protocol: TCP 53 targetPort: grpc 54 ``` 55 56 ## HTTPProxy Configuration 57 58 Configuring proxying to a gRPC service with HTTPProxy is as simple as specifying the protocol Envoy uses with the upstream application via the `spec.routes[].services[].protocol` field. 59 For example, in the resource below, for proxying plaintext gRPC to the `yages` sample app, the protocol is set to `h2c` to denote HTTP/2 over cleartext. 60 For TLS secured gRPC, the protocol used would be `h2`. 61 62 Route path prefix matching can be used to match a specific gRPC message if required. 63 64 ```yaml 65 --- 66 apiVersion: projectcontour.io/v1 67 kind: HTTPProxy 68 metadata: 69 name: my-grpc-service 70 spec: 71 virtualhost: 72 fqdn: my-grpc-service.foo.com 73 routes: 74 - conditions: 75 - prefix: /yages.Echo/Ping # Matches a specific gRPC method. 76 services: 77 - name: grpc-echo 78 port: 9000 79 protocol: h2c 80 - conditions: 81 - prefix: / # Matches everything else. 82 services: 83 - name: grpc-echo 84 port: 9000 85 protocol: h2c 86 ``` 87 88 Using the sample deployment above along with this HTTPProxy example, you can test calling this plaintext gRPC server with the following [grpcurl][5] command: 89 90 ``` 91 grpcurl -plaintext -authority=my-grpc-service.foo.com <load balancer IP and port if needed> yages.Echo/Ping 92 ``` 93 94 If implementing a streaming RPC, it is likely you will need to adjust per-route timeouts to ensure streams are kept alive for the appropriate durations needed. 95 Relevant timeout fields to adjust include the HTTPProxy `spec.routes[].timeoutPolicy.response` field which defaults to 15s and should be increased as well as the global timeout policy configurations in the Contour configuration file `timeouts.request-timeout` and `timeouts.max-connection-duration`. 96 97 ## Ingress v1 Configuration 98 99 To configure routing for gRPC requests with Ingress v1, you must add an annotation on the upstream Service resource as below. 100 101 ```yaml 102 --- 103 apiVersion: v1 104 kind: Service 105 metadata: 106 labels: 107 app.kubernetes.io/name: grpc-echo 108 annotations: 109 projectcontour.io/upstream-protocol.h2c: "9000" 110 name: grpc-echo 111 spec: 112 selector: 113 app.kubernetes.io/name: grpc-echo 114 ports: 115 - port: 9000 116 protocol: TCP 117 targetPort: grpc 118 ``` 119 120 The annotation key must follow the form `projectcontour.io/upstream-protocol.{protocol}` where `{protocol}` is `h2c` for plaintext gRPC or `h2` for TLS encrypted gRPC to the upstream application. 121 The annotation value contains a comma-separated list of port names and/or numbers that must match with the ones defined in the Service definition. 122 123 Using the Service above with the Ingress resource below should achieve the same configuration as with an HTTPProxy. 124 125 ```yaml 126 --- 127 apiVersion: networking.k8s.io/v1 128 kind: Ingress 129 metadata: 130 name: my-grpc-service 131 spec: 132 rules: 133 - host: my-grpc-service.foo.com 134 http: 135 paths: 136 - path: / 137 backend: 138 service: 139 name: grpc-echo 140 port: 141 number: 9000 142 pathType: Prefix 143 ``` 144 145 ## Gateway API Configuration 146 147 Gateway API now supports a specific resource [GRPCRoute][6] for routing gRPC requests. 148 149 Configuring GRPCRoute for routing gRPC requests needs to specify parentRefs, hostnames, and routing rules with specific backendRefs. In the below example, route path matching is conducted via method matching rule for declared services and their methods. 150 151 ```yaml 152 apiVersion: gateway.networking.k8s.io/v1alpha2 153 kind: GRPCRoute 154 metadata: 155 name: yages 156 spec: 157 parentRefs: 158 - namespace: projectcontour 159 name: contour 160 hostnames: 161 - my-grpc-service.foo.com 162 rules: 163 - matches: 164 - method: 165 service: yages.Echo 166 method: Ping 167 - method: 168 service: grpc.reflection.v1alpha.ServerReflection 169 method: ServerReflectionInfo 170 backendRefs: 171 - name: grpc-echo 172 port: 9000 173 ``` 174 Using the sample deployment above along with this GRPCRoute example, you can test calling this plaintext gRPC server with the same grpcurl command: 175 176 ```yaml 177 grpcurl -plaintext -authority=my-grpc-service.foo.com <load balancer IP and port if needed> yages.Echo/Ping 178 ``` 179 Note that the second matching method for service of ServerReflection is required by grpcurl command. 180 181 When using GRPCRoute, user should annotate their Service similarly to when using Ingress Configuration, to indicate the protocol to use when connecting to the backend Service, i.e. h2c for HTTP plaintext and h2 for TLS encrypted HTTPS. If it's not specified, Contour will infer the protocol based on the Gateway Listener protocol, h2c for HTTP and h2 for HTTPS. 182 183 184 185 186 ## gRPC-Web 187 188 Contour configures Envoy to automatically convert [gRPC-Web][7] HTTP/1 requests to gRPC over HTTP/2 RPC calls to an upstream service. 189 This is a convenience addition to make usage of gRPC web application client libraries and the like easier. 190 191 Note that you still must provide configuration of the upstream protocol to have gRPC-Web requests converted to gRPC to the upstream app. 192 If your upstream application does not in fact support gRPC, you may get a protocol error. 193 In that case, please see [this issue][8]. 194 195 For example, with the example deployment and routing configuration provided above, an example HTTP/1.1 request and response via `curl` looks like: 196 197 ``` 198 curl \ 199 -s -v \ 200 <load balancer IP and port if needed>/yages.Echo/Ping \ 201 -XPOST \ 202 -H 'Host: my-grpc-service.foo.com' \ 203 -H 'Content-Type: application/grpc-web-text' \ 204 -H 'Accept: application/grpc-web-text' \ 205 -d'AAAAAAA=' 206 ``` 207 208 This `curl` command sends and receives gRPC messages as base 64 encoded text over HTTP/1.1. 209 Piping the output to `base64 -d | od -c` we can see the raw text gRPC response: 210 211 ``` 212 0000000 \0 \0 \0 \0 006 \n 004 p o n g 200 \0 \0 \0 036 213 0000020 g r p c - s t a t u s : 0 \r \n g 214 0000040 r p c - m e s s a g e : \r \n 215 0000056 216 ``` 217 218 [1]: https://github.com/projectcontour/yages 219 [2]: https://pkg.go.dev/google.golang.org/grpc/health/grpc_health_v1 220 [3]: https://github.com/grpc/grpc/blob/master/doc/health-checking.md 221 [4]: https://github.com/grpc-ecosystem/grpc-health-probe 222 [5]: https://github.com/fullstorydev/grpcurl 223 [6]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRoute 224 [7]: https://github.com/grpc/grpc-web 225 [8]: https://github.com/projectcontour/contour/issues/4290