We are using Istio Envoy based Rate limiting (with Kubernetes & Docker) as specified in this documentation.
Although I was able to set it up for local and global rate limiting in the Kubernetes cluster, I am unable to achieve the following:
Rate limit a Service only for POST requests, while GET requests should go through unencumbered.
Rate limit a Service only for a certain time duration (e.g. 9 AM to 5 PM EST) and work normally at other times.
Is the above possible in current Istio functionalities?
I will try to answer both of your questions below.
We can use the header_value_match rate limit actions.
I created a single rate_limits filter
with one action
that matches any request with method GET:
NOTE: For the sake of simplicity, I have only given an important part of the configuration.
Envoy rate_limits filter configuration:
...
value:
rate_limits:
- actions:
- header_value_match:
descriptor_value: get
headers:
- name: :method
prefix_match: GET
...
Next, I created a ratelimit service configuration
that matches descriptors with key header_match
and value get
. It will provide a limit of 1 request per minute:
...
descriptors:
- key: header_match
rate_limit:
unit: minute
requests_per_unit: 1
value: get
...
After applying the above configuration, we can check whether it will be possible to use the GET method more than once within 1 minute:
$ curl "http://$GATEWAY_URL/productpage" -I -X GET
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 5179
server: istio-envoy
date: Tue, 11 Jan 2022 09:57:33 GMT
x-envoy-upstream-service-time: 120
$ curl "http://$GATEWAY_URL/productpage" -I -X GET
HTTP/1.1 429 Too Many Requests
x-envoy-ratelimited: true
date: Tue, 11 Jan 2022 09:57:35 GMT
server: istio-envoy
content-length: 0
As we can see, after the second request, we received the HTTP 429 Too Many Requests response status code which indicates that the user has sent too many requests in a given amount of time. It means that everything works as expected.
I recommend you to read the Understanding Envoy Rate Limits article which contains a lot of useful information.
Unfortunately, I cannot find any suitable option to configure this behavior. I think that CronJob can be used as a workaround, which will run periodically on a given schedule and will create/delete the appropriate configuration responsible for rate-limiting. In short, you can use a Bash script that creates/deletes a configuration responsible for rate-limiting and then you can mount that script in a volume to the CronJob
Pod.
I have already described a similar use of CronJob
here and believe it can help you.