Simplify rate limit task (#2042)

This commit is contained in:
mandarjog 2018-07-30 03:50:40 -07:00 committed by istio-bot
parent c9262518ad
commit 2e0fa5dad2
1 changed files with 53 additions and 68 deletions

View File

@ -31,18 +31,11 @@ service.
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@ $ kubectl apply -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@
{{< /text >}} {{< /text >}}
1. Initialize application version routing on the `reviews` service to
direct requests from the test user "jason" to version v2 and requests from any other user to v3.
{{< text bash >}}
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-jason-v2-v3.yaml@
{{< /text >}}
## Rate limits ## Rate limits
In this task, you configure Istio to rate limit traffic to the `ratings` In this task, you configure Istio to rate limit traffic to `productpage` based on the IP address
service. Consider `ratings` as an external paid service like Rotten Tomatoes® of the originating client. You will use `X-Forwarded-For` request header as the client
with 1 qps free quota. Using Istio, you can ensure that 1 qps is not exceeded. IP address. You will also use a conditional rate limit that exempts logged in users.
For convenience, you configure the For convenience, you configure the
[memory quota](/docs/reference/config/policy-and-telemetry/adapters/memquota/) [memory quota](/docs/reference/config/policy-and-telemetry/adapters/memquota/)
@ -53,22 +46,19 @@ quota](/docs/reference/config/policy-and-telemetry/adapters/redisquota/)
the [quota template](/docs/reference/config/policy-and-telemetry/templates/quota/), the [quota template](/docs/reference/config/policy-and-telemetry/templates/quota/),
so the configuration to enable rate limiting on both adapters is the same. so the configuration to enable rate limiting on both adapters is the same.
1. Point your browser at the Bookinfo `productpage` 1. Rate limit configuration is split into 2 parts.
(`http://$GATEWAY_URL/productpage`). * Client Side
* `QuotaSpec` defines quota name and amount that the client should request.
* `QuotaSpecBinding` conditionally associates `QuotaSpec` with one or more services.
* Mixer Side
* `quota instance` defines how quota is dimensioned by Mixer.
* `memquota adapter` defines memquota adapter configuration.
* `quota rule` defines when quota instance is dispatched to the memquota adapter.
* If you log in as user "jason", you should see black ratings stars with Run the following command to enable rate limits.
each review, indicating that the `ratings` service is being called by the
"v2" version of the `reviews` service.
* If you log in as any other user, you should see red ratings
stars with each review, indicating that the `ratings` service is being
called by the "v3" version of the `reviews` service.
1. Configure `memquota`, `quota`, `rule`, `QuotaSpec`, `QuotaSpecBinding` to
enable rate limiting.
{{< text bash >}} {{< text bash >}}
$ kubectl apply -f @samples/bookinfo/policy/mixer-rule-ratings-ratelimit.yaml@ $ kubectl apply -f @samples/bookinfo/policy/mixer-rule-productpage-ratelimit.yaml@
{{< /text >}} {{< /text >}}
1. Confirm the `memquota` handler was created: 1. Confirm the `memquota` handler was created:
@ -83,34 +73,29 @@ so the configuration to enable rate limiting on both adapters is the same.
spec: spec:
quotas: quotas:
- name: requestcount.quota.istio-system - name: requestcount.quota.istio-system
maxAmount: 5000 maxAmount: 500
validDuration: 1s validDuration: 1s
overrides:
- dimensions: - dimensions:
destination: ratings destination: reviews
source: reviews
sourceVersion: v3
maxAmount: 1 maxAmount: 1
validDuration: 5s validDuration: 5s
- dimensions: - dimensions:
destination: ratings destination: productpage
maxAmount: 5 maxAmount: 2
validDuration: 10s validDuration: 5s
{{< /text >}} {{< /text >}}
The `memquota` handler defines 3 different rate limit schemes. The default, The `memquota` handler defines 3 different rate limit schemes. The default,
if no overrides match, is `5000` requests per one second (`1s`). Two if no overrides match, is `500` requests per one second (`1s`). Two
overrides are also defined: overrides are also defined:
* The first is `1` request (the `maxAmount` field) every `5s` (the * The first is `1` request (the `maxAmount` field) every `5s` (the
`validDuration` field), if the `destination` is `ratings`, the `source` is `validDuration` field), if the `destination` is `reviews`.
`reviews`, and the `sourceVersion` is `v3`. * The second is `2` requests every `5s`, if the `destination` is `productpage`.
* The second is `5` requests every `10s`, if the `destination` is `ratings`.
When a request is sent to the `ratings` service, the first matching override When a request is sent to the first matching override is picked (reading from top to bottom).
is picked (reading from top to bottom).
1. Confirm the `quota` was created: 1. Confirm the `quota instance` was created:
{{< text bash yaml >}} {{< text bash yaml >}}
$ kubectl -n istio-system get quotas requestcount -o yaml $ kubectl -n istio-system get quotas requestcount -o yaml
@ -121,20 +106,19 @@ so the configuration to enable rate limiting on both adapters is the same.
namespace: istio-system namespace: istio-system
spec: spec:
dimensions: dimensions:
source: source.labels["app"] | "unknown" source: request.headers["x-forwarded-for"] | "unknown"
sourceVersion: source.labels["version"] | "unknown"
destination: destination.labels["app"] | destination.service.host | "unknown" destination: destination.labels["app"] | destination.service.host | "unknown"
destinationVersion: destination.labels["version"] | "unknown" destinationVersion: destination.labels["version"] | "unknown"
{{< /text >}} {{< /text >}}
The `quota` template defines four dimensions that are used by `memquota` The `quota` template defines three dimensions that are used by `memquota`
to set overrides on requests that match certain attributes. The to set overrides on requests that match certain attributes. The
`destination` will be set to the first non-empty value in `destination` will be set to the first non-empty value in
`destination.labels["app"]`, `destination.service.host`, or `"unknown"`. For `destination.labels["app"]`, `destination.service.host`, or `"unknown"`. For
more information on expressions, see [Expression more information on expressions, see [Expression
Language](/docs/reference/config/policy-and-telemetry/expression-language/). Language](/docs/reference/config/policy-and-telemetry/expression-language/).
1. Confirm the `rule` was created: 1. Confirm the `quota rule` was created:
{{< text bash yaml >}} {{< text bash yaml >}}
$ kubectl -n istio-system get rules quota -o yaml $ kubectl -n istio-system get rules quota -o yaml
@ -187,58 +171,59 @@ so the configuration to enable rate limiting on both adapters is the same.
- name: request-count - name: request-count
namespace: istio-system namespace: istio-system
services: services:
- name: ratings
namespace: default
- name: reviews
namespace: default
- name: details
namespace: default
- name: productpage - name: productpage
namespace: default namespace: default
# - service: '*'
{{< /text >}} {{< /text >}}
This `QuotaSpecBinding` binds the `QuotaSpec` you created above to the This `QuotaSpecBinding` binds the `QuotaSpec` you created above to the
services you want to apply it to. You have to define the namespace for services you want to apply it to. `productpage` is explicitly bound to `request-count`, note
each service since it is not in the same namespace this `QuotaSpecBinding` that you must define the namespace since it differs from the namespace of the `QuotaSpecBinding`.
resource was deployed into. If the last line is uncommented, `service: '*'` binds all services to the `QuotaSpec`
making the first entry redundant.
1. Refresh the product page in your browser. 1. Refresh the product page in your browser.
* If you are logged out, `reviews-v3` service is rate limited to 1 request `request-count` quota applies to `productpage` and it permits 2 requests
every 5 seconds. If you keep refreshing the page, the stars should only every 5 seconds. If you keep refreshing the page you should see
load around once every 5 seconds. `RESOURCE_EXHAUSTED:Quota is exhausted for: requestcount`.
* If you log in as user "jason", `reviews-v2` service is rate limited to 5
requests every 10 seconds. If you keep refreshing the page, the stars
should only load 5 times every 10 seconds.
* For all other services, the default 5000 qps rate limit will apply.
## Conditional rate limits ## Conditional rate limits
In the previous example you applied a rate limit to the `ratings` service In the above example we have effectively rate limited `productpage` at `2 rps` per client IP.
without regard to non-dimension attributes. It is possible to conditionally Consider a scenario where you would like to exempt clients from this rate limit if a user is logged in.
apply rate limits based on arbitrary attributes using a match condition in In the `bookinfo` example, we use cookie `user=<username>` to denote a logged in user.
the quota rule. In a realistic scenario you may use a `jwt` token for this purpose.
For example, consider the following configuration: You can update the `quota rule` by adding a match condition based on the `cookie`.
{{< text yaml >}} {{< text yaml >}}
$ kubectl -n istio-system edit rules quota
apiVersion: config.istio.io/v1alpha2 apiVersion: config.istio.io/v1alpha2
kind: rule kind: rule
metadata: metadata:
name: quota name: quota
namespace: istio-system namespace: istio-system
spec: spec:
match: source.namespace != destination.namespace match: match(request.headers["cookie"], "user=*") == false
actions: actions:
- handler: handler.memquota - handler: handler.memquota
instances: instances:
- requestcount.quota - requestcount.quota
{{< /text >}} {{< /text >}}
This configuration applies the quota rule to requests whose source and `memquota` adapter is now dispatched only if `user=<username>` cookie is absent from the request.
destination namespaces are different. This ensures that a logged in user is not subject to this quota.
1. Verify that rate limit does not apply to a logged in user.
Log in as `jason` and repeatedly refresh the `productpage`. Now you should be able to do this without a problem.
1. Verify that rate limit *does* apply when not logged in.
Logout as `jason` and repeatedly refresh the `productpage`.
You should again see `RESOURCE_EXHAUSTED:Quota is exhausted for: requestcount`.
## Understanding rate limits ## Understanding rate limits