diff --git a/site/content/en/latest/tasks/traffic/grpc-timeouts.md b/site/content/en/latest/tasks/traffic/grpc-timeouts.md new file mode 100644 index 0000000000..6d6d4829c5 --- /dev/null +++ b/site/content/en/latest/tasks/traffic/grpc-timeouts.md @@ -0,0 +1,182 @@ +--- +title: "GRPC Timeouts" +--- + +Unlike [HTTPRoute][], the Gateway API [GRPCRoute][] resource does not (yet) expose a native +`timeouts` field — see the upstream tracking issue [Support Request Timeouts for GRPCRoute][gapi-3139]. +Until that lands, Envoy Gateway lets you configure timeouts for gRPC traffic with a +[BackendTrafficPolicy][] that targets the `GRPCRoute`. + +The default request timeout is 15 seconds in Envoy Proxy, which will terminate long-lived +streaming RPCs. The relevant `spec.timeout.http` fields are: + +- **requestTimeout**: the maximum duration for the entire response to be received from the + upstream. This bounds **unary** RPCs. Set it to `"0s"` to disable it for **streaming** RPCs, + which otherwise would be cut off once the timeout elapses. +- **maxStreamDuration**: the maximum duration of a stream, measured from when the request is sent + until the response stream is fully consumed. It does not apply to non-streaming requests. Set it + to `"0s"` to allow streams to run indefinitely. +- **streamIdleTimeout**: the amount of time a stream may exist with no upstream or downstream + activity. Use this to reclaim idle streams without capping a healthy long-lived stream's total + duration. + +## Prerequisites + +{{< boilerplate prerequisites >}} + +Follow the [GRPC Routing](../grpc-routing) task to set up a `Gateway` and a `GRPCRoute` named +`yages` before configuring timeouts. + +__Note:__ A `GRPCRoute` can have at most one `BackendTrafficPolicy` attached to it; a second policy +targeting the same route is rejected as `Conflicted`. The two examples below are therefore +alternatives that reuse the same policy name (`grpc-timeouts`) — pick the one that matches your +workload. Re-applying with the same `metadata.name` updates the existing policy rather than creating +a conflicting second one. + +## Unary RPCs + +Set `requestTimeout` to bound the duration of unary RPCs. Here, unary calls that take longer than +5 seconds are terminated with a timeout. + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + +## Streaming RPCs + +For server-streaming, client-streaming, or bidirectional-streaming RPCs, `requestTimeout` would +terminate the stream once it elapses. Disable it with `"0s"` and, if you want an upper bound, use +`maxStreamDuration` (or `streamIdleTimeout` to reclaim only idle streams). The example below lets +streams run indefinitely while reclaiming streams that are idle for more than 1 hour. + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + +## Verification + +First confirm the policy is accepted: + +```shell +kubectl get backendtrafficpolicy/grpc-timeouts -o yaml +``` + +The status should reflect `Accepted=True` on the targeted `GRPCRoute` ancestor. + +Then confirm the timeout is actually programmed into the Envoy route config with +[egctl](../../operations/egctl): + +```shell +egctl config envoy-proxy route \ + --labels gateway.envoyproxy.io/owning-gateway-name=eg,gateway.envoyproxy.io/owning-gateway-namespace=default \ + -o yaml | grep -A2 -E 'timeout|maxStreamDuration' +``` + +For the **unary** example you should see the route's `timeout` set to the configured +`requestTimeout` (e.g. `timeout: 5s`). For the **streaming** example you should see +`timeout: 0s` (disabled) together with `maxStreamDuration` on the route action. + +To exercise the timeout end-to-end you need a gRPC backend that can delay or stream (the +sample `yages` echo server used in the [GRPC Routing](../grpc-routing) task returns +immediately). Against such a backend, a unary call that exceeds `requestTimeout` returns +gRPC status `DEADLINE_EXCEEDED` (HTTP `504`), for example with +[grpcurl](https://github.com/fullstorydev/grpcurl): + +```shell +grpcurl -plaintext -authority=grpc-example.com ${GATEWAY_HOST}:80 +# ERROR: +# Code: DeadlineExceeded +``` + +[HTTPRoute]: https://gateway-api.sigs.k8s.io/reference/api-types/httproute/ +[GRPCRoute]: https://gateway-api.sigs.k8s.io/reference/api-types/grpcroute/ +[BackendTrafficPolicy]: ../../../api/extension_types#backendtrafficpolicy +[gapi-3139]: https://github.com/kubernetes-sigs/gateway-api/issues/3139