Skip to content
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

docs: add docs for ratelimit invert match headers #4483

Merged
merged 2 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion api/v1alpha1/ratelimit_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ type HeaderMatch struct { // TODO: zhaohuabing this type could be replaced with
//
// +optional
// +kubebuilder:default=false
// +notImplementedHide
Invert *bool `json:"invert,omitempty"`
}

Expand Down
52 changes: 48 additions & 4 deletions site/content/en/latest/tasks/traffic/global-rate-limit.md
Original file line number Diff line number Diff line change
Expand Up @@ -433,11 +433,11 @@ server: envoy

```

## Rate Limit Distinct Users
## Rate Limit Distinct Users Except Admin

Here is an example of a rate limit implemented by the application developer to limit distinct users who can be differentiated based on the
value in the `x-user-id` header. Here, user `one` (recognised from the traffic flow using the header `x-user-id` and value `one`) will be rate limited at 3 requests/hour
and so will user `two` (recognised from the traffic flow using the header `x-user-id` and value `two`).
and so will user `two` (recognised from the traffic flow using the header `x-user-id` and value `two`). But if `x-user-id` is `admin`, it will not be rate limited even beyond 3 requests/hour.

{{< tabpane text=true >}}
{{% tab header="Apply from stdin" %}}
Expand All @@ -461,6 +461,9 @@ spec:
- headers:
- type: Distinct
name: x-user-id
- name: x-user-id
value: admin
invert: true
limit:
requests: 3
unit: Hour
Expand Down Expand Up @@ -636,6 +639,47 @@ transfer-encoding: chunked

```

But when the value for header `x-user-id` is set to `admin` and 4 requests are sent, all 4 of them should respond with 200 OK.

```shell
for i in {1..4}; do curl -I --header "Host: ratelimit.example" --header "x-user-id: admin" http://${GATEWAY_HOST}/get ; sleep 1; done
```

```console
HTTP/1.1 200 OK
content-type: application/json
x-content-type-options: nosniff
date: Wed, 08 Feb 2023 02:33:31 GMT
content-length: 460
x-envoy-upstream-service-time: 4
server: envoy

HTTP/1.1 200 OK
content-type: application/json
x-content-type-options: nosniff
date: Wed, 08 Feb 2023 02:33:32 GMT
content-length: 460
x-envoy-upstream-service-time: 2
server: envoy

HTTP/1.1 200 OK
content-type: application/json
x-content-type-options: nosniff
date: Wed, 08 Feb 2023 02:33:33 GMT
content-length: 460
x-envoy-upstream-service-time: 0
server: envoy

HTTP/1.1 200 OK
content-type: application/json
x-content-type-options: nosniff
date: Wed, 08 Feb 2023 02:33:33 GMT
content-length: 460
x-envoy-upstream-service-time: 0
server: envoy

```

## Rate Limit All Requests

This example shows you how to rate limit all requests matching the HTTPRoute rule at 3 requests/Hour by leaving the `clientSelectors` field unset.
Expand Down Expand Up @@ -809,7 +853,7 @@ spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: http-ratelimit
name: http-ratelimit
rateLimit:
type: Global
global:
Expand Down Expand Up @@ -858,7 +902,7 @@ spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: http-ratelimit
name: http-ratelimit
rateLimit:
type: Global
global:
Expand Down
221 changes: 221 additions & 0 deletions site/content/en/latest/tasks/traffic/local-rate-limit.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,227 @@ server: envoy

```

## Rate Limit Specific User Unless within Test Org

Here is an example of a rate limit implemented by the application developer to limit a specific user by matching on a custom `x-user-id` header
with a value set to `one`. But the user must not be limited if logging in within Test org, determined by custom header `x-org-id` set to `test`.

{{< tabpane text=true >}}
{{% tab header="Apply from stdin" %}}

```shell
cat <<EOF | kubectl apply -f -
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: policy-httproute
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: http-ratelimit
rateLimit:
type: Local
local:
rules:
- clientSelectors:
- headers:
- name: x-user-id
zhaohuabing marked this conversation as resolved.
Show resolved Hide resolved
value: one
- name: x-org-id
value: test
invert: true
limit:
requests: 3
unit: Hour
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: policy-httproute
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: http-ratelimit
rateLimit:
type: Local
local:
rules:
- clientSelectors:
- headers:
- name: x-user-id
value: one
- name: x-org-id
value: test
invert: true
limit:
requests: 3
unit: Hour
```

{{% /tab %}}
{{< /tabpane >}}

### HTTPRoute

{{< tabpane text=true >}}
{{% tab header="Apply from stdin" %}}

```shell
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-ratelimit
spec:
parentRefs:
- name: eg
hostnames:
- ratelimit.example
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ""
kind: Service
name: backend
port: 3000
EOF
```

{{% /tab %}}
{{% tab header="Apply from file" %}}
Save and apply the following resource to your cluster:

```yaml
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-ratelimit
spec:
parentRefs:
- name: eg
hostnames:
- ratelimit.example
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ""
kind: Service
name: backend
port: 3000
```

{{% /tab %}}
{{< /tabpane >}}

The HTTPRoute status should indicate that it has been accepted and is bound to the example Gateway.

```shell
kubectl get httproute/http-ratelimit -o yaml
```

Get the Gateway's address:

```shell
export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}')
```

Let's query `ratelimit.example/get` 4 times with `x-user-id` set to `one` and `x-org-id` set to `org1`. We should receive a `200` response from the example Gateway for the first 3 requests and the last request should be rate limited.

```shell
for i in {1..4}; do curl -I --header "Host: ratelimit.example" --header "x-user-id: one" --header "x-org-id: org1" http://${GATEWAY_HOST}/get ; sleep 1; done
```

```console
HTTP/1.1 200 OK
content-type: application/json
x-content-type-options: nosniff
date: Wed, 08 Feb 2023 02:33:31 GMT
content-length: 460
x-envoy-upstream-service-time: 4
server: envoy

HTTP/1.1 200 OK
content-type: application/json
x-content-type-options: nosniff
date: Wed, 08 Feb 2023 02:33:32 GMT
content-length: 460
x-envoy-upstream-service-time: 2
server: envoy

HTTP/1.1 200 OK
content-type: application/json
x-content-type-options: nosniff
date: Wed, 08 Feb 2023 02:33:33 GMT
content-length: 460
x-envoy-upstream-service-time: 0
server: envoy

HTTP/1.1 429 Too Many Requests
x-envoy-ratelimited: true
date: Wed, 08 Feb 2023 02:33:34 GMT
server: envoy
transfer-encoding: chunked

```

Let's query `ratelimit.example/get` 4 times with `x-user-id` set to `one` and `x-org-id` set to `test`. We should receive a `200` response from the example Gateway for all the 4 requests, unlike previous example where the last request was rate limited.

```shell
for i in {1..4}; do curl -I --header "Host: ratelimit.example" --header "x-user-id: one" --header "x-org-id: test" http://${GATEWAY_HOST}/get ; sleep 1; done
```

```console
HTTP/1.1 200 OK
content-type: application/json
x-content-type-options: nosniff
date: Wed, 08 Feb 2023 02:33:31 GMT
content-length: 460
x-envoy-upstream-service-time: 4
server: envoy

HTTP/1.1 200 OK
content-type: application/json
x-content-type-options: nosniff
date: Wed, 08 Feb 2023 02:33:32 GMT
content-length: 460
x-envoy-upstream-service-time: 2
server: envoy

HTTP/1.1 200 OK
content-type: application/json
x-content-type-options: nosniff
date: Wed, 08 Feb 2023 02:33:33 GMT
content-length: 460
x-envoy-upstream-service-time: 0
server: envoy

HTTP/1.1 200 OK
content-type: application/json
x-content-type-options: nosniff
date: Wed, 08 Feb 2023 02:33:33 GMT
content-length: 460
x-envoy-upstream-service-time: 0
server: envoy

```

## Rate Limit All Requests

This example shows you how to rate limit all requests matching the HTTPRoute rule at 3 requests/Hour by leaving the `clientSelectors` field unset.
Expand Down
41 changes: 41 additions & 0 deletions test/e2e/testdata/ratelimit-header-invert-match-local.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: ratelimit-specific-user
namespace: gateway-conformance-infra
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: http-ratelimit-specific-user
rateLimit:
type: Local
local:
rules:
- clientSelectors:
- headers:
- name: x-user-id
value: one
- name: x-org-id
value: test
invert: true
limit:
requests: 3
unit: Hour
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-ratelimit-specific-user
namespace: gateway-conformance-infra
spec:
parentRefs:
- name: same-namespace
rules:
- backendRefs:
- name: infra-backend-v1
port: 8080
matches:
- path:
type: Exact
value: /ratelimit-specific-user
Loading