Search code examples
kubernetesistiorate-limiting

Kubernetes Istio Envoy - Rate Limiting by HTTP Method


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:

  1. Rate limit a Service only for POST requests, while GET requests should go through unencumbered.

  2. 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?


Solution

  • I will try to answer both of your questions below.

    1. Rate limit a Service only for a specific request method

    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.

    2. Rate limit a Service only for a certain time duration (e.g. 9 AM to 5 PM EST) and work normally at other times.

    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.