Rate Limiting Tutorial
Emissary can validate incoming requests before routing them to a backing service. In this tutorial, we’ll configure Emissary to use a simple third party rate limit service. (If you don’t want to implement your own rate limiting service, Ambassador Edge Stack integrates a powerful, flexible rate limiting service.)
Before you get started
This tutorial assumes you have already followed the Emissary Installation and Quickstart Tutorial guides. If you haven’t done that already, you should do so now.
Once completed, you’ll have a Kubernetes cluster running Emissary and the Quote service. Let’s walk through adding rate limiting to this setup.
1. Deploy the rate limit service
Emissary delegates the actual rate limit logic to a third party service. We’ve written a simple rate limit service that:
- listens for requests on port 5000;
- handles gRPC
shouldRateLimit
requests; - allows requests with the
x-emissary-test-allow: "true"
header; and - marks all other requests as
OVER_LIMIT
;
Here’s the YAML we’ll start with:
---
apiVersion: getambassador.io/v3alpha1
kind: RateLimitService
metadata:
name: ratelimit
namespace: default
spec:
service: "ratelimit-example.default:5000"
protocol_version: v3
domain: emissary
failure_mode_deny: true
---
apiVersion: v1
kind: Service
metadata:
name: ratelimit-example
spec:
selector:
app: ratelimit-example
ports:
- name: http
port: 5000
targetPort: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ratelimit-example
spec:
replicas: 1
selector:
matchLabels:
app: ratelimit-example
template:
metadata:
labels:
app: ratelimit-example
spec:
containers:
- name: ratelimit-example
image: docker.io/emissaryingress/ratelimit-example:v3
imagePullPolicy: Always
ports:
- name: http
containerPort: 5000
resources:
limits:
memory: "64Mi"
cpu: "100m"
Once this configuration is applied Kubernetes will startup the example ratelimit service and Emissary will be configured to use the rate limit service. The RateLimitService
configuration tells Emissary to:
- Send
ShouldRateLimit
check request toratelimit-example.default:5000
- Configure Envoy to talk with the example ratelimit service using transport protocol
v3
(only supported version) - Set the labels
domain
toemissary
(labels discussed below)
RateLimitService
above we toggled it via the failure_mode_deny: true
setting.
2. Configure Emissary Mappings
Emissary only validates requests on Mapping
s which set labels to use for rate limiting, so you’ll need to apply labels
to your Mapping
s to enable rate limiting. For more information
on the labelling process, see the Rate Limits configuration documentation.
labels
require Mapping
resources with apiVersion
getambassador.io/v2
or newer — if you're updating an old installation, check the
apiVersion
!
Labels are added to a Mapping
using the labels
field and domain
configured in the RateLimitService
. For example:
labels:
emissary:
- request_label_group:
- x-emissary-test-allow:
request_headers:
key: "x-emissary-test-allow"
header_name: "x-emissary-test-allow"
If we were to apply it the Mapping
definition for the quote-backend
service outlined in the quick-start then it would look like this:
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: quote-backend
spec:
hostname: "*"
prefix: /backend/
service: quote
labels:
emissary:
- request_label_group:
- x-emissary-test-allow:
request_headers:
key: "x-emissary-test-allow"
header_name: "x-emissary-test-allow"
Note that the key
could be anything you like, but our example rate limiting service expects it to match the name of the header. Also note that since our RateLimitService
expects to use labels in the
emissary
domain, our Mapping
must match.
2. Test rate limiting
If we curl
to a rate-limited URL:
curl -i -H "x-emissary-test-allow: probably" http://$LB_ENDPOINT/backend/
We get a 429
status code, since we are being rate limited.
HTTP/1.1 429 Too Many Requests
content-type: text/html; charset=utf-8
content-length: 0
If we set the correct header value to the service request, we will get a quote successfully:
$ curl -i -H "x-emissary-test-allow: true" http://$LB_ENDPOINT/backend/
TCP_NODELAY set
* Connected to 35.196.173.175 (35.196.173.175) port 80 (#0)
> GET /backed HTTP/1.1
> Host: 35.196.173.175
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: application/json
< date: Thu, 23 May 2019 15:25:06 GMT
< content-length: 172
< x-envoy-upstream-service-time: 0
< server: envoy
<
{
"server": "humble-blueberry-o2v493st",
"quote": "Nihilism gambles with lives, happiness, and even destiny itself!",
"time": "2019-05-23T15:25:06.544417902Z"
* Connection #0 to host 54.165.128.189 left intact
}
More
For more details about configuring the external rate limit service, read the rate limit documentation.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.