Skip to content
This repository has been archived by the owner on Dec 16, 2024. It is now read-only.

Commit

Permalink
Merge pull request #612 from jasonmadigan/14-rlp-ap-guides
Browse files Browse the repository at this point in the history
RateLimitPolicy guide to follow after gateway walkthrough
  • Loading branch information
openshift-ci[bot] authored Oct 16, 2023
2 parents 5194972 + d1380f2 commit 6965b6a
Show file tree
Hide file tree
Showing 2 changed files with 179 additions and 15 deletions.
24 changes: 9 additions & 15 deletions docs/how-to/multicluster-gateways-walkthrough.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,7 @@ We will start with a single cluster and move to multiple clusters to illustrate

## Initial Setup

In this walkthrough, we'll deploy test echo services across multiple clusters. Before starting, set up a `MGC_SUB_DOMAIN` variable to simplify templating. This variable will represent the host for each service.

If you followed the [Getting Started Guide](https://docs.kuadrant.io/getting-started/), you would have already set up a `MGC_ZONE_ROOT_DOMAIN` environment variable when creating a `ManagedZone`. For this tutorial, we'll derive a host from this domain.

```bash
export MGC_SUB_DOMAIN=myapp.$MGC_ZONE_ROOT_DOMAIN
```
In this walkthrough, we'll deploy test echo services across multiple clusters. If you followed the [Getting Started Guide](https://docs.kuadrant.io/getting-started/), you would have already set up a `MGC_ZONE_ROOT_DOMAIN` environment variable. For this tutorial, we'll derive a host from this domain for these echo services.

### Create a gateway

Expand Down Expand Up @@ -56,7 +50,7 @@ You are now ready to begin creating a gateway! :tada:
namespaces:
from: All
name: api
hostname: $MGC_SUB_DOMAIN
hostname: "*.$MGC_ZONE_ROOT_DOMAIN"
port: 443
protocol: HTTPS
tls:
Expand Down Expand Up @@ -174,7 +168,7 @@ So what about DNS how do we bring traffic to these gateways?
name: prod-web
namespace: kuadrant-multi-cluster-gateways
hostnames:
- "$MGC_SUB_DOMAIN"
- "echo.$MGC_ZONE_ROOT_DOMAIN"
rules:
- backendRefs:
- name: echo
Expand Down Expand Up @@ -257,12 +251,12 @@ So what about DNS how do we bring traffic to these gateways?
4. Give DNS a minute or two to update. You should then be able to execute the following and get back the correct A record.
```bash
dig $MGC_SUB_DOMAIN
dig echo.$MGC_ZONE_ROOT_DOMAIN
```
5. You should also be able to curl that endpoint
```bash
curl -k https://$MGC_SUB_DOMAIN
curl -k https://echo.$MGC_ZONE_ROOT_DOMAIN
# Request served by echo-XXX-XXX
```
Expand Down Expand Up @@ -297,7 +291,6 @@ So now we have a working gateway with DNS and TLS configured. Let place this gat
So now we have second ingress cluster configured with the same Gateway.
4. Let's create the HTTPRoute in the second gateway cluster:
```bash
kubectl --context kind-mgc-workload-1 apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
Expand All @@ -310,7 +303,7 @@ So now we have a working gateway with DNS and TLS configured. Let place this gat
name: prod-web
namespace: kuadrant-multi-cluster-gateways
hostnames:
- "$MGC_SUB_DOMAIN"
- "echo.$MGC_ZONE_ROOT_DOMAIN"
rules:
- backendRefs:
- name: echo
Expand Down Expand Up @@ -361,9 +354,10 @@ So now we have a working gateway with DNS and TLS configured. Let place this gat
```
## Watching DNS changes
If you want you can use ```watch dig $MGC_SUB_DOMAIN``` to see the DNS switching between the two addresses
If you want you can use ```watch dig echo.$MGC_ZONE_ROOT_DOMAIN``` to see the DNS switching between the two addresses
## Follow-on Walkthroughs
Some good follow-on walkthroughs that build on this walkthrough
Here are some good, follow-on guides that build on this walkthrough:
* [Simple RateLimitPolicy for App Developers](./simple-ratelimitpolicy-for-app-developers.md)
* [Deploying/Configuring Metrics.](../how-to/metrics-walkthrough.md)
170 changes: 170 additions & 0 deletions docs/how-to/simple-ratelimitpolicy-for-app-developers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# 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.

## Requirements

- Complete the [Multicluster Gateways Walkthrough](./multicluster-gateways-walkthrough.md), and you'll have an environment configured with a Gateway that we'll use in this guide.

## Overview

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.$MGC_ZONE_ROOT_DOMAIN`, 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").

### ① Deploy the Toy Store API

#### Create the Deployment

> **Note:** You can skip this step and proceed to [Create the HTTPRoute](#create-the-httproute) if you've already deployed the Toy Store API as part of [the AuthPolicy for App Developers guide](./simple-authpolicy-for-app-developers.md#-deploy-the-toy-store-api).
Create the deployments for both clusters we've created previously (`kind-mgc-control-plane` & `kind-mgc-workload-1`):

```bash
for context in kind-mgc-control-plane kind-mgc-workload-1; do kubectl --context $context apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: toystore
labels:
app: toystore
spec:
selector:
matchLabels:
app: toystore
template:
metadata:
labels:
app: toystore
spec:
containers:
- name: toystore
image: quay.io/3scale/authorino:echo-api
env:
- name: PORT
value: "3000"
ports:
- containerPort: 3000
name: http
replicas: 1
---
apiVersion: v1
kind: Service
metadata:
name: toystore
spec:
selector:
app: toystore
ports:
- name: http
port: 80
protocol: TCP
targetPort: 3000
EOF
done
```

Create a HTTPRoute to route traffic to the services via the Gateways:

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

```sh
for context in kind-mgc-control-plane kind-mgc-workload-1; do kubectl --context $context apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: toystore
spec:
parentRefs:
- kind: Gateway
name: prod-web
namespace: kuadrant-multi-cluster-gateways
hostnames:
- toystore.$MGC_ZONE_ROOT_DOMAIN
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
done
```

Verify the routes work:

```sh
curl -ik https://toystore.$MGC_ZONE_ROOT_DOMAIN/toys
# HTTP/1.1 200 OK
```

Given the two clusters, and our previously created `DNSPolicy`, traffic with load balance between these clusters round-robin style. Load balancing here will be determined in part by DNS TTLs, so it can take a minute or two for requests to flow to both services.

### ② 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
for context in kind-mgc-control-plane kind-mgc-workload-1; do kubectl --context $context 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
done
```

> **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 -k --output /dev/null https://toystore.$MGC_ZONE_ROOT_DOMAIN/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 -k --output /dev/null https://toystore.$MGC_ZONE_ROOT_DOMAIN/toys | egrep --color "\b(429)\b|$"; sleep 1; done
```

## Next Steps

Here are some good, follow-on guides that build on this walkthrough:

* [Simple AuthPolicy for App Developers](./simple-authpolicy-for-app-developers.md)
* [Deploying/Configuring Metrics.](../how-to/metrics-walkthrough.md)

0 comments on commit 6965b6a

Please sign in to comment.