-
Notifications
You must be signed in to change notification settings - Fork 831
docs: add GRPC Timeouts task (BackendTrafficPolicy) #9631
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
guanchzhou
wants to merge
3
commits into
envoyproxy:main
Choose a base branch
from
guanchzhou:eg-grpc-timeouts-docs
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+182
−0
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <<EOF | kubectl apply -f - | ||
| apiVersion: gateway.envoyproxy.io/v1alpha1 | ||
| kind: BackendTrafficPolicy | ||
| metadata: | ||
| name: grpc-timeouts | ||
| spec: | ||
| targetRefs: | ||
| - group: gateway.networking.k8s.io | ||
| kind: GRPCRoute | ||
| name: yages | ||
| timeout: | ||
| http: | ||
| requestTimeout: "5s" | ||
| EOF | ||
| ``` | ||
|
|
||
| {{% /tab %}} | ||
| {{% tab header="Apply from file" %}} | ||
| Save and apply the following resource to your cluster: | ||
|
|
||
| ```yaml | ||
| --- | ||
| apiVersion: gateway.envoyproxy.io/v1alpha1 | ||
| kind: BackendTrafficPolicy | ||
| metadata: | ||
| name: grpc-timeouts | ||
| spec: | ||
| targetRefs: | ||
| - group: gateway.networking.k8s.io | ||
| kind: GRPCRoute | ||
| name: yages | ||
| timeout: | ||
| http: | ||
| requestTimeout: "5s" | ||
| ``` | ||
|
|
||
| {{% /tab %}} | ||
| {{< /tabpane >}} | ||
|
|
||
| ## 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 <<EOF | kubectl apply -f - | ||
| apiVersion: gateway.envoyproxy.io/v1alpha1 | ||
| kind: BackendTrafficPolicy | ||
| metadata: | ||
| name: grpc-timeouts | ||
| spec: | ||
| targetRefs: | ||
| - group: gateway.networking.k8s.io | ||
| kind: GRPCRoute | ||
| name: yages | ||
| timeout: | ||
| http: | ||
| # Disable the per-request timeout so long-lived streams are not cut off. | ||
| requestTimeout: "0s" | ||
| # Allow streams to run indefinitely; set a non-zero value to cap them. | ||
| maxStreamDuration: "0s" | ||
| # Reclaim streams with no activity for more than 1 hour. | ||
| streamIdleTimeout: "1h" | ||
| EOF | ||
| ``` | ||
|
|
||
| {{% /tab %}} | ||
| {{% tab header="Apply from file" %}} | ||
| Save and apply the following resource to your cluster: | ||
|
|
||
| ```yaml | ||
| --- | ||
| apiVersion: gateway.envoyproxy.io/v1alpha1 | ||
| kind: BackendTrafficPolicy | ||
| metadata: | ||
| name: grpc-timeouts | ||
| spec: | ||
| targetRefs: | ||
| - group: gateway.networking.k8s.io | ||
| kind: GRPCRoute | ||
| name: yages | ||
| timeout: | ||
| http: | ||
| # Disable the per-request timeout so long-lived streams are not cut off. | ||
| requestTimeout: "0s" | ||
| # Allow streams to run indefinitely; set a non-zero value to cap them. | ||
| maxStreamDuration: "0s" | ||
| # Reclaim streams with no activity for more than 1 hour. | ||
| streamIdleTimeout: "1h" | ||
| ``` | ||
|
|
||
| {{% /tab %}} | ||
| {{< /tabpane >}} | ||
|
|
||
| ## 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 <your.slow.Method> | ||
| # 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 | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When readers follow this task top-to-bottom, the unary example has already created a
BackendTrafficPolicytargetingGRPCRoute/yages, and this streaming example creates a second policy for that same route. Envoy Gateway processes BackendTrafficPolicies in creation order andresolveBackendTrafficPolicyRouteTargetRefrejects a later policy that targets an already-attached route asConflicted, sogrpc-stream-timeoutwill not be accepted and the streaming timeout settings won't take effect unless the reader deletes/reuses the first policy or uses a separate route.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch — fixed in 2c85563. Both examples now reuse a single
BackendTrafficPolicynamedgrpc-timeouts, and I added a note in Prerequisites that a GRPCRoute accepts only one BackendTrafficPolicy (a second is rejected asConflicted), so the two examples are alternatives and re-applying updates the same policy rather than creating a conflicting second one.