<p>We are using Istio Envoy based Rate limiting (with Kubernetes &amp; Docker) as specified in <a href="https://istio.io/latest/docs/tasks/policy-enforcement/rate-limit/" rel="nofollow noreferrer">this documentation</a>.</p>
<p>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:</p>
<ol>
<li><p>Rate limit a Service only for POST requests, while GET requests should go through unencumbered.</p>
</li>
<li><p>Rate limit a Service only for a certain time duration (e.g. 9 AM to 5 PM EST) and work normally at other times.</p>
</li>
</ol>
<p>Is the above possible in current Istio functionalities?</p>

<p>I will try to answer both of your questions below.</p>
<h4>1. Rate limit a Service only for a specific request method</h4>
<p>We can use the <a href="https://www.envoyproxy.io/docs/envoy/v1.14.5/api-v2/api/v2/route/route_components.proto#envoy-api-msg-route-ratelimit-action-headervaluematch" rel="nofollow noreferrer">header_value_match</a> rate limit actions.</p>
<p>I created a single <code>rate_limits filter</code> with one <code>action</code> that matches any request with method <strong>GET</strong>:<br />
<strong>NOTE:</strong> For the sake of simplicity, I have only given an important part of the configuration.</p>
<p>Envoy rate_limits filter configuration:</p>
<pre><code>...
        value:
          rate_limits:
            - actions:
              - header_value_match:
                  descriptor_value: get
                  headers:
                  - name: :method
                    prefix_match: GET
...
</code></pre>
<p>Next, I created a <code>ratelimit service configuration</code> that matches descriptors with key <code>header_match</code> and value <code>get</code>. It will provide a limit of 1 request per minute:</p>
<pre><code>...
    descriptors:
      - key: header_match
        rate_limit:
          unit: minute
          requests_per_unit: 1
        value: get
...
</code></pre>
<p>After applying the above configuration, we can check whether it will be possible to use the <strong>GET</strong> method more than once within 1 minute:</p>
<pre><code>$ curl &quot;http://$GATEWAY_URL/productpage&quot; -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 &quot;http://$GATEWAY_URL/productpage&quot; -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
</code></pre>
<p>As we can see, after the second request, we received the HTTP <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429" rel="nofollow noreferrer">429 Too Many Requests</a> 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.</p>
<p>I recommend you to read the <a href="https://www.aboutwayfair.com/tech-innovation/understanding-envoy-rate-limits" rel="nofollow noreferrer">Understanding Envoy Rate Limits</a> article which contains a lot of useful information.</p>
<h4>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.</h4>
<p>Unfortunately, I cannot find any suitable option to configure this behavior. I think that <a href="https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/" rel="nofollow noreferrer">CronJob</a> 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 <code>CronJob</code> Pod.
I have already described a similar use of <code>CronJob</code> <a href="https://stackoverflow.com/a/68406717/14801225">here</a> and believe it can help you.</p>
