Skip to content

Commit

Permalink
docs: Simple Rate Limiting for Application Developers
Browse files Browse the repository at this point in the history
  • Loading branch information
guicassolato committed Aug 28, 2023
1 parent f24dea3 commit 45afe3d
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 138 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ EOF

The user guides section of the docs gathers several use-cases as well as the instructions to implement them using kuadrant.

* [Simple rate limiting for API owners](doc/user-guides/simple-rl-for-api-owners.md)
* [Simple Rate Limiting for Application Developers](doc/user-guides/simple-rl-for-app-developers.md)
* [Authenticated Rate Limiting for Application Developers](doc/user-guides/authenticated-rl-for-app-developers.md)
* [Gateway rate limiting for cluster operators](doc/user-guides/gateway-rl-for-cluster-operators.md)
* [Authenticated rate limiting with JWTs and Kubernetes authnz](doc/user-guides/authenticated-rl-with-jwt-and-k8s-authnz.md)
Expand Down
137 changes: 0 additions & 137 deletions doc/user-guides/simple-rl-for-api-owners.md

This file was deleted.

157 changes: 157 additions & 0 deletions doc/user-guides/simple-rl-for-app-developers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Simple Rate Limiting for Application Developers

This user guide walks you through an example of how to configure rate limiting for an endpoint of an application using Kuadrant.

<br/>

In this guide, we will rate limit a sample REST API called **Toy Store**. In reality, this API is just an echo service that echoes back to the user whatever attributes it gets in the request. The API listens to requests at the hostname `api.toystore.com`, where it exposes the endpoints `GET /toys*` and `POST /toys`, respectively, to mimic a operations of reading and writing toy records.

We will rate limit the `POST /toys` endpoint to a maximum of 5rp10s ("5 requests every 10 seconds").

<br/>

## Run the steps ① → ③

### ① Setup

This step uses tooling from the Kuadrant Operator component to create a containerized Kubernetes server locally using [Kind](https://kind.sigs.k8s.io),
where it installs Istio, Kubernetes Gateway API and Kuadrant itself.

> **Note:** In production environment, these steps are usually performed by a cluster operator with administrator privileges over the Kubernetes cluster.
Clone the project:

```sh
git clone https://github.com/Kuadrant/kuadrant-operator && cd kuadrant-operator
```

Setup the environment:

```sh
make local-setup
```

Request an instance of Kuadrant:

```sh
kubectl -n kuadrant-system apply -f - <<EOF
apiVersion: kuadrant.io/v1beta1
kind: Kuadrant
metadata:
name: kuadrant
spec: {}
EOF
```

### ② Deploy the Toy Store API

Create the deployment:

```sh
kubectl apply -f examples/toystore/toystore.yaml
```

Create a HTTPRoute to route traffic to the service via Istio Ingress Gateway:

![](https://i.imgur.com/rdN8lo3.png)

```sh
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: toystore
spec:
parentRefs:
- name: istio-ingressgateway
namespace: istio-system
hostnames:
- api.toystore.com
rules:
- matches:
- method: GET
path:
type: PathPrefix
value: "/toys"
backendRefs:
- name: toystore
port: 80
- matches: # it has to be a separate HTTPRouteRule so we do not rate limit other endpoints
- method: POST
path:
type: Exact
value: "/toys"
backendRefs:
- name: toystore
port: 80
EOF
```

Verify the route works:

```sh
curl -H 'Host: api.toystore.com' http://localhost:9080/toys -i
# HTTP/1.1 200 OK
```

> **Note**: If the command above fails to hit the Toy Store API on your environment, try forwarding requests to the service:
>
> ```sh
> kubectl port-forward -n istio-system service/istio-ingressgateway 9080:80 2>&1 >/dev/null &
> ```
### ③ Enforce rate limiting on requests to the Toy Store API
Create a Kuadrant `RateLimitPolicy` to configure rate limiting:
![](https://i.imgur.com/2A9sXXs.png)
```sh
kubectl apply -f - <<EOF
apiVersion: kuadrant.io/v1beta2
kind: RateLimitPolicy
metadata:
name: toystore
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: toystore
limits:
"create-toy":
rates:
- limit: 5
duration: 10
unit: second
routeSelectors:
- matches: # selects the 2nd HTTPRouteRule of the targeted route
- method: POST
path:
type: Exact
value: "/toys"
EOF
```
> **Note:** It may take a couple of minutes for the RateLimitPolicy to be applied depending on your cluster.
<br/>

Verify the rate limiting works by sending requests in a loop.

Up to 5 successful (`200 OK`) requests every 10 seconds to `POST /toys`, then `429 Too Many Requests`:

```sh
while :; do curl --write-out '%{http_code}' --silent --output /dev/null -H 'Host: api.toystore.com' http://localhost:9080/toys -X POST | egrep --color "\b(429)\b|$"; sleep 1; done
```

Unlimited successful (`200 OK`) to `GET /toys`:

```sh
while :; do curl --write-out '%{http_code}' --silent --output /dev/null -H 'Host: api.toystore.com' http://localhost:9080/toys | egrep --color "\b(429)\b|$"; sleep 1; done
```

## Cleanup

```sh
make local-cleanup
```

0 comments on commit 45afe3d

Please sign in to comment.