-
Notifications
You must be signed in to change notification settings - Fork 49
Added fault injection topics #776
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
Merged
Merged
Changes from all commits
Commits
Show all changes
4 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,205 @@ | ||
| Inject artificial latency into requests with an {{< reuse "agw-docs/snippets/policy.md" >}} to test how your clients and upstream services handle slow responses. Fault injection is useful for verifying that timeouts, retries, and client-side deadlines behave as expected. To learn more, you can use fault injection alongside [Timeouts]({{< link-hextra path="/resiliency/timeouts/" >}}) and [Retries]({{< link-hextra path="/resiliency/retry/" >}}). | ||
|
|
||
| The injected delay counts against the request timeout. If the delay is longer than the configured [request timeout]({{< link-hextra path="/resiliency/timeouts/" >}}), the request times out. | ||
|
|
||
| {{< reuse "agw-docs/snippets/agentgateway/prereq.md" >}} | ||
|
|
||
| ## Inject a delay {#inject-a-delay} | ||
|
|
||
| 1. Create an HTTPRoute for the httpbin app. | ||
| ```yaml {paths="delay-in-trafficpolicy"} | ||
| kubectl apply -n httpbin -f- <<EOF | ||
| apiVersion: gateway.networking.k8s.io/v1 | ||
| kind: HTTPRoute | ||
| metadata: | ||
| name: httpbin-delay | ||
| namespace: httpbin | ||
| spec: | ||
| hostnames: | ||
| - faultinjection.example | ||
| parentRefs: | ||
| - name: agentgateway-proxy | ||
| namespace: {{< reuse "agw-docs/snippets/namespace.md" >}} | ||
| rules: | ||
| - backendRefs: | ||
| - kind: Service | ||
| name: httpbin | ||
| port: 8000 | ||
| EOF | ||
| ``` | ||
|
|
||
| 2. Create an {{< reuse "agw-docs/snippets/policy.md" >}} that injects a fixed 2-second delay into the requests that the HTTPRoute handles. | ||
| ```yaml {paths="delay-in-trafficpolicy"} | ||
| kubectl apply -f- <<EOF | ||
| apiVersion: {{< reuse "agw-docs/snippets/api-version.md" >}} | ||
| kind: {{< reuse "agw-docs/snippets/policy.md" >}} | ||
| metadata: | ||
| name: httpbin-delay | ||
| namespace: httpbin | ||
| spec: | ||
| targetRefs: | ||
| - group: gateway.networking.k8s.io | ||
| kind: HTTPRoute | ||
| name: httpbin-delay | ||
| traffic: | ||
| delay: | ||
| duration: 2s | ||
| EOF | ||
| ``` | ||
|
|
||
| {{< reuse "agw-docs/snippets/review-table.md" >}} | ||
|
|
||
| | Field | Description | | ||
| | -- | -- | | ||
| | `targetRefs` | The route, gateway, or listener to apply the delay to. In this example, the policy targets the `httpbin-delay` HTTPRoute. | | ||
| | `traffic.delay.duration` | The latency to inject before the request is forwarded to the backend. Set either a duration string, such as `2s` or `500ms`, or a CEL expression that is evaluated against the request. For more information, see [Inject a probabilistic or random delay](#inject-a-probabilistic-or-random-delay). | | ||
|
|
||
| 3. Send a request along the route and verify that the response is delayed by about 2 seconds. | ||
| {{< tabs >}} | ||
| {{% tab name="Cloud Provider LoadBalancer" %}} | ||
| ```sh | ||
| curl -s -o /dev/null -w "%{time_total}s\n" http://$INGRESS_GW_ADDRESS/get -H "host: faultinjection.example" | ||
| ``` | ||
| {{% /tab %}} | ||
| {{% tab name="Port-forward for local testing" %}} | ||
| ```sh | ||
| curl -s -o /dev/null -w "%{time_total}s\n" localhost:8080/get -H "host: faultinjection.example" | ||
| ``` | ||
| {{% /tab %}} | ||
| {{< /tabs >}} | ||
|
|
||
| Example output: | ||
| ```console | ||
| 2.01s | ||
| ``` | ||
|
|
||
| 4. Optional: Verify that the delay policy is applied in the proxy configuration. | ||
|
|
||
| 1. Port-forward the gateway proxy on port 15000. | ||
| ```sh | ||
| kubectl port-forward deploy/agentgateway-proxy -n {{< reuse "agw-docs/snippets/namespace.md" >}} 15000 | ||
| ``` | ||
|
|
||
| 2. Find the delay policy in the config dump. | ||
| ```sh | ||
| curl -s http://localhost:15000/config_dump | jq '[.policies[] | select(.policy.traffic.delay?)] | .[0]' | ||
| ``` | ||
|
|
||
| ## Inject a probabilistic or random delay {#inject-a-probabilistic-or-random-delay} | ||
|
|
||
| Because `duration` accepts a CEL expression, you can inject latency into only a subset of requests, or add jitter. The expression is evaluated against each request and returns either a duration or a number that is interpreted as milliseconds. A non-positive result injects no delay. | ||
|
|
||
| | Expression | Effect | | ||
| | -- | -- | | ||
| | `duration("500ms")` | A fixed 500ms delay, expressed as a CEL duration. | | ||
| | `random() < 0.1 ? 500 : 0` | A 500ms delay on approximately 10% of requests, and no delay otherwise. | | ||
| | `int(random() * 500.0)` | A random delay between 0 and 500ms (jitter) on every request. | | ||
|
|
||
| For example, the following policy delays approximately 10% of requests by 500ms. | ||
|
|
||
| ```yaml | ||
| kubectl apply -f- <<EOF | ||
| apiVersion: {{< reuse "agw-docs/snippets/api-version.md" >}} | ||
| kind: {{< reuse "agw-docs/snippets/policy.md" >}} | ||
| metadata: | ||
| name: httpbin-delay | ||
| namespace: httpbin | ||
| spec: | ||
| targetRefs: | ||
| - group: gateway.networking.k8s.io | ||
| kind: HTTPRoute | ||
| name: httpbin-delay | ||
| traffic: | ||
| delay: | ||
| duration: "random() < 0.1 ? 500 : 0" | ||
| EOF | ||
| ``` | ||
|
|
||
| {{< doc-test paths="delay-in-trafficpolicy" >}} | ||
| # WHAT THIS TEST VALIDATES: | ||
| # * The httpbin-delay HTTPRoute (host faultinjection.example) is Accepted. | ||
| # * The httpbin-delay AgentgatewayPolicy (traffic.delay.duration: 2s) is Accepted. | ||
| # * A request to /get with host faultinjection.example returns 200 (the injected | ||
| # delay does not break the request). | ||
| # * The delay policy is present in the proxy config dump. | ||
| # WHAT THIS TEST DOES NOT VALIDATE (and why): | ||
| # * That the response is actually delayed by ~2s — Different layer: YAMLTest has | ||
| # no response-latency assertion, so timing is not measured. | ||
| # * The probabilistic/random CEL delay example — Display-only block, not tagged. | ||
| # Warm up the new faultinjection.example hostname before asserting (two-phase proxy warmup). | ||
| for i in $(seq 1 60); do | ||
| curl -s --max-time 5 -o /dev/null "http://${INGRESS_GW_ADDRESS}:80/get" -H "host: faultinjection.example" && break | ||
| sleep 2 | ||
| done | ||
| {{< /doc-test >}} | ||
|
|
||
| {{< doc-test paths="delay-in-trafficpolicy" >}} | ||
| YAMLTest -f - <<'EOF' | ||
| - name: wait for httpbin-delay HTTPRoute to be accepted | ||
| wait: | ||
| target: | ||
| kind: HTTPRoute | ||
| metadata: | ||
| namespace: httpbin | ||
| name: httpbin-delay | ||
| jsonPath: "$.status.parents[0].conditions[?(@.type=='Accepted')].status" | ||
| jsonPathExpectation: | ||
| comparator: equals | ||
| value: "True" | ||
| polling: | ||
| timeoutSeconds: 300 | ||
| intervalSeconds: 5 | ||
| - name: wait for httpbin-delay AgentgatewayPolicy to be accepted | ||
| wait: | ||
| target: | ||
| kind: AgentgatewayPolicy | ||
| metadata: | ||
| namespace: httpbin | ||
| name: httpbin-delay | ||
| jsonPath: "$.status.ancestors[0].conditions[?(@.type=='Accepted')].status" | ||
| jsonPathExpectation: | ||
| comparator: equals | ||
| value: "True" | ||
| polling: | ||
| timeoutSeconds: 300 | ||
| intervalSeconds: 5 | ||
| - name: verify request through the delayed route returns 200 | ||
| retries: 1 | ||
| http: | ||
| url: "http://${INGRESS_GW_ADDRESS}:80" | ||
| path: /get | ||
| method: GET | ||
| headers: | ||
| host: "faultinjection.example" | ||
| source: | ||
| type: local | ||
| expect: | ||
| statusCode: 200 | ||
| - name: verify delay policy in config dump | ||
| http: | ||
| url: http://localhost:15000 | ||
| skipSslVerification: true | ||
| method: GET | ||
| path: /config_dump | ||
| source: | ||
| type: pod | ||
| usePortForward: true | ||
| selector: | ||
| kind: Deployment | ||
| metadata: | ||
| namespace: agentgateway-system | ||
| name: agentgateway-proxy | ||
| expect: | ||
| bodyContains: | ||
| - '"duration"' | ||
| EOF | ||
| {{< /doc-test >}} | ||
|
|
||
| ## Cleanup | ||
|
|
||
| {{< reuse "agw-docs/snippets/cleanup.md" >}} Run the following commands. | ||
|
|
||
| ```sh | ||
| kubectl delete httproute httpbin-delay -n httpbin | ||
| kubectl delete {{< reuse "agw-docs/snippets/policy.md" >}} httpbin-delay -n httpbin | ||
| ``` |
16 changes: 16 additions & 0 deletions
16
content/docs/kubernetes/main/resiliency/fault-injection.md
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,16 @@ | ||
| --- | ||
| title: Fault injection | ||
| weight: 20 | ||
| description: Inject artificial latency into requests to test how your clients and services handle slow responses. | ||
| test: | ||
| delay-in-trafficpolicy: | ||
| - file: ${versionRoot}/quickstart/install.md | ||
| path: experimental | ||
| - file: ${versionRoot}/setup/gateway.md | ||
| path: all | ||
| - file: ${versionRoot}/install/sample-app.md | ||
| path: install-httpbin | ||
| - path: delay-in-trafficpolicy | ||
| --- | ||
|
|
||
| {{< reuse "agw-docs/pages/resiliency/fault-injection.md" >}} |
144 changes: 144 additions & 0 deletions
144
content/docs/standalone/main/configuration/resiliency/fault-injection.md
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,144 @@ | ||
| --- | ||
| title: Fault injection | ||
| weight: 20 | ||
| description: Inject artificial latency into requests to test how your clients and services handle slow responses. | ||
| # TODO: re-enable once the agentgateway:latest-dev image includes the standalone | ||
| # `delay` policy (added in agentgateway#2613 / commit c844384d). Until then the | ||
| # --validate-only doc-test fails with "unknown field `delay`". | ||
| # test: | ||
| # fault-injection: | ||
| # - file: ${versionRoot}/configuration/resiliency/fault-injection.md | ||
| # path: fault-injection | ||
| --- | ||
|
|
||
| Attaches to: {{< badge content="Route" path="/configuration/routes/">}} | ||
|
|
||
| {{< reuse "agw-docs/snippets/config-styles-note.md" >}} | ||
|
|
||
| {{< doc-test paths="fault-injection" >}} | ||
| {{< reuse "agw-docs/snippets/install-agentgateway-binary.md" >}} | ||
| {{< /doc-test >}} | ||
|
|
||
| Fault injection adds artificial latency to matching requests before agentgateway forwards them to the backend. Use it to test how your clients and upstream services behave when responses are slow, such as verifying that timeouts, retries, and client-side deadlines work as expected. | ||
|
|
||
| The injected delay counts against the request timeout. If the delay is longer than the configured [request timeout]({{< link-hextra path="/configuration/resiliency/timeouts/" >}}), the request times out. | ||
|
|
||
| ## Inject a delay | ||
|
|
||
| Set `delay.duration` in the route policies. The `duration` can be either of the following values. | ||
|
|
||
| | Value | Description | | ||
| | -- | -- | | ||
| | A duration string | A fixed latency to inject, such as `2s` or `500ms`. | | ||
| | A CEL expression | An expression that is evaluated against each request and returns a duration or a number of milliseconds. Use this option for conditional, probabilistic, or randomized delays. A non-positive result injects no delay. | | ||
|
|
||
| The following example injects a fixed 2-second delay before agentgateway forwards requests to the backend. | ||
|
|
||
| {{< tabs >}} | ||
| {{< tab name="Simplified (MCP)" >}} | ||
| ```yaml | ||
| # yaml-language-server: $schema=https://agentgateway.dev/schema/config | ||
| mcp: | ||
| port: 3000 | ||
| policies: | ||
| delay: | ||
| duration: 2s | ||
| targets: | ||
| - name: everything | ||
| stdio: | ||
| cmd: npx | ||
| args: ["@modelcontextprotocol/server-everything"] | ||
| ``` | ||
| {{< /tab >}} | ||
| {{< tab name="Routing-based" >}} | ||
| ```yaml | ||
| # yaml-language-server: $schema=https://agentgateway.dev/schema/config | ||
| binds: | ||
| - port: 3000 | ||
| listeners: | ||
| - routes: | ||
| - policies: | ||
| delay: | ||
| duration: 2s | ||
| backends: | ||
| - host: localhost:8080 | ||
| ``` | ||
| {{< /tab >}} | ||
| {{< /tabs >}} | ||
|
|
||
| ## Inject a probabilistic or random delay | ||
|
|
||
| Because `duration` accepts a CEL expression, you can inject latency into only a subset of requests, or add jitter. The expression returns either a duration or a number that is interpreted as milliseconds. | ||
|
|
||
| | Expression | Effect | | ||
| | -- | -- | | ||
| | `duration("500ms")` | A fixed 500ms delay, expressed as a CEL duration. | | ||
| | `random() < 0.1 ? 500 : 0` | A 500ms delay on approximately 10% of requests, and no delay otherwise. | | ||
| | `int(random() * 500.0)` | A random delay between 0 and 500ms (jitter) on every request. | | ||
|
|
||
| The following example delays approximately 10% of requests by 500ms. | ||
|
|
||
| ```yaml | ||
| # yaml-language-server: $schema=https://agentgateway.dev/schema/config | ||
| binds: | ||
| - port: 3000 | ||
| listeners: | ||
| - routes: | ||
| - policies: | ||
| delay: | ||
| duration: "random() < 0.1 ? 500 : 0" | ||
| backends: | ||
| - host: localhost:8080 | ||
| ``` | ||
|
|
||
| {{< doc-test paths="fault-injection" >}} | ||
| # WHAT THIS TEST VALIDATES: | ||
| # * The delay (fault injection) policy is accepted by agentgateway in the | ||
| # routing-based, simplified MCP, and CEL-expression forms. | ||
| # WHAT THIS TEST DOES NOT VALIDATE (and why): | ||
| # * That the latency is actually injected at runtime — verifying that would | ||
| # require timing a live request against a running backend, which this page | ||
| # omits. | ||
| cat <<'EOF' > config.yaml | ||
| # yaml-language-server: $schema=https://agentgateway.dev/schema/config | ||
| binds: | ||
| - port: 3000 | ||
| listeners: | ||
| - routes: | ||
| - policies: | ||
| delay: | ||
| duration: 2s | ||
| backends: | ||
| - host: localhost:8080 | ||
| EOF | ||
| agentgateway -f config.yaml --validate-only | ||
|
|
||
| cat <<'EOF' > config-mcp.yaml | ||
| # yaml-language-server: $schema=https://agentgateway.dev/schema/config | ||
| mcp: | ||
| port: 3000 | ||
| policies: | ||
| delay: | ||
| duration: 2s | ||
| targets: | ||
| - name: everything | ||
| stdio: | ||
| cmd: npx | ||
| args: ["@modelcontextprotocol/server-everything"] | ||
| EOF | ||
| agentgateway -f config-mcp.yaml --validate-only | ||
|
|
||
| cat <<'EOF' > config-cel.yaml | ||
| # yaml-language-server: $schema=https://agentgateway.dev/schema/config | ||
| binds: | ||
| - port: 3000 | ||
| listeners: | ||
| - routes: | ||
| - policies: | ||
| delay: | ||
| duration: "random() < 0.1 ? 500 : 0" | ||
| backends: | ||
| - host: localhost:8080 | ||
| EOF | ||
| agentgateway -f config-cel.yaml --validate-only | ||
| {{< /doc-test >}} | ||
Oops, something went wrong.
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.
does this page need a cleanup section too at the end?
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.