Rate Limiting
IMPORTANT: This guide applies to Ambassador API Gateway, use of this guide on the Ambassador Edge Stack is not fully supported. Use the existing RateLimitService instead.
Ambassador can validate incoming requests before routing them to a backing service. In this tutorial, we'll configure the Ambassador API Gateway to use a simple third party rate limit service. If you don't want to implement your own rate limiting service, the Ambassador Edge Stack integrates a powerful, flexible rate limiting service.
Before You Get Started
This tutorial assumes you have already followed the Ambassador API Gateway 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 Ambassador and the Quote of the Moment service. Let's walk through adding rate limiting to this setup.
1. Deploy the Rate Limit Service
Ambassador 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-ambassador-test-allow: "true"
header; and - marks all other requests as
OVER_LIMIT
;
Here's the YAML we'll start with:
---apiVersion: getambassador.io/v2kind: RateLimitServicemetadata:name: ratelimitspec:service: "example-rate-limit:5000"---apiVersion: v1kind: Servicemetadata:name: example-rate-limitspec:type: ClusterIPselector:app: example-rate-limitports:- port: 5000name: http-example-rate-limittargetPort: http-api---apiVersion: apps/v1kind: Deploymentmetadata:name: example-rate-limitspec:replicas: 1strategy:type: RollingUpdateselector:matchLabels:app: example-rate-limittemplate:metadata:labels:app: example-rate-limitspec:containers:- name: example-rate-limitimage: agervais/ambassador-ratelimit-service:1.0.0imagePullPolicy: Alwaysports:- name: http-apicontainerPort: 5000resources:limits:cpu: "0.1"memory: 100Mi
This configuration tells Ambassador about the rate limit service, notably that it is serving requests at example-rate-limit:5000
.
Ambassador will see the RateLimitService and reconfigure itself within a few seconds. Note that the v2 API is available for the Ambassador.
2. Configure Ambassador Mappings
Ambassador only validates requests on Mappings which set rate limiting descriptors. If Ambassador cannot contact the rate limit service, it will allow the request to be processed as if there were no rate limit service configuration.
v0 API
Ambassador 0.50.0 and later requires the v2
API Version for rate limiting. The v2
API uses the labels
attribute to attach rate limiting descriptors. Review the Rate Limits configuration documentation for more information.
Replace the label that is applied to the service-backend
with:
labels:ambassador:- request_label_group:- x-ambassador-test-allow:header: "x-ambassador-test-allow"omit_if_not_present: true
so the Mapping definition will now look like this:
---apiVersion: getambassador.io/v2kind: Mappingmetadata:name: service-backendspec:prefix: /backend/service: quotelabels:ambassador:- request_label_group:- x-ambassador-test-allow:header: "x-ambassador-test-allow"omit_if_not_present: true
v2 API
Ambassador versions 0.40.2 and earlier use the v2
API version which uses the rate_limits
attribute to set rate limiting descriptors.
---apiVersion: v1kind: Servicemetadata:name: quotespec:ports:- name: uiport: 5000targetPort: 5000- name: backendport: 8080targetPort: 8080selector:app: backend---apiVersion: getambassador.io/v2kind: Mappingmetadata:name: quote-backendspec:prefix: /service: quote:5000---apiVersion: getambassador.io/v2kind: Mappingmetadata:name: quote-backendspec:prefix: /backend/service: quoterate_limits:- descriptor: A test caseheaders:- "x-ambassador-test-allow"
This configuration tells Ambassador about the rate limit rules to apply, notably that it needs the x-ambassador-test-allow
header, and that it should set "A test case" as the generic_key
descriptor when performing the gRPC request.
Note that both descriptor
and headers
are optional. However, if headers
are defined, they must be part of the request in order to be rate limited.
Ambassador would also perform multiple requests to example-rate-limit:5000
if we had defined multiple rate_limits
rules on the mapping.
3. Test Rate Limiting
If we curl
to a rate-limited URL:
$ curl -Lv -H "x-ambassador-test-allow: probably" $AMBASSADORURL/backend/
We get a 429, since we are limited.
HTTP/1.1 429 Too Many Requestscontent-type: text/html; charset=utf-8content-length: 0
If we set the correct header value to the service request, we will get a quote successfully:
$ curl -Lv -H "x-ambassador-test-allow: true" $AMBASSADORURL/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.
Questions?
We’re here to help. If you have questions, join our Slack or contact us.