mirror of https://github.com/istio/istio.io.git
Update ratelimit docs (#1390)
* update ratelimit docs to include QuotaSpec and QuotaSpecBinding * fix rebase issues * add inline yaml and fix destination wording * fix missing ' * Update syntax for Hugo * Fix spacing and punctuation * Fix spelling
This commit is contained in:
parent
1467145811
commit
cccf5077b6
|
@ -6,17 +6,19 @@ aliases:
|
|||
- /docs/tasks/rate-limiting.html
|
||||
---
|
||||
|
||||
This task shows you how to use Istio to dynamically limit the traffic to a service.
|
||||
This task shows you how to use Istio to dynamically limit the traffic to a
|
||||
service.
|
||||
|
||||
## Before you begin
|
||||
|
||||
* Setup Istio in a Kubernetes cluster by following the quick start instructions in the
|
||||
[Installation guide](/docs/setup/kubernetes/quick-start/).
|
||||
* Setup Istio in a Kubernetes cluster by following the quick start instructions
|
||||
in the [Installation guide](/docs/setup/kubernetes/quick-start/).
|
||||
|
||||
* Deploy the [Bookinfo](/docs/guides/bookinfo/) sample application.
|
||||
|
||||
* Initialize the application version routing to direct `reviews` service requests from
|
||||
test user "jason" to version v2 and requests from any other user to v3.
|
||||
* Initialize the application version routing to direct `reviews` service
|
||||
requests from test user "jason" to version v2 and requests from any other
|
||||
user to v3.
|
||||
|
||||
```command
|
||||
$ istioctl create -f samples/bookinfo/kube/route-rule-reviews-test-v2.yaml
|
||||
|
@ -30,110 +32,189 @@ use `istioctl replace` instead of `istioctl create`.
|
|||
|
||||
Istio enables users to rate limit traffic to a service.
|
||||
|
||||
Consider `ratings` as an external paid service like Rotten Tomatoes® with `1qps` free quota.
|
||||
Using Istio we can ensure that `1qps` is not breached.
|
||||
Consider `ratings` as an external paid service like Rotten Tomatoes® with
|
||||
`1qps` free quota. Using Istio we can ensure that `1qps` is not breached.
|
||||
|
||||
1. Point your browser at the Bookinfo `productpage` (http://$GATEWAY_URL/productpage).
|
||||
1. Point your browser at the Bookinfo `productpage`
|
||||
(http://$GATEWAY_URL/productpage).
|
||||
|
||||
If you log in as user "jason", you should see black ratings stars with each review,
|
||||
indicating that the `ratings` service is being called by the "v2" version of the `reviews` service.
|
||||
If you log in as user "jason", you should see black ratings stars with
|
||||
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 (or logout) 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.
|
||||
If you log in as any other user (or logout) 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 a `memquota` adapter with rate limits.
|
||||
|
||||
Save the following YAML snippet as `ratelimit-handler.yaml`.
|
||||
|
||||
```yaml
|
||||
apiVersion: config.istio.io/v1alpha2
|
||||
kind: memquota
|
||||
metadata:
|
||||
name: handler
|
||||
namespace: istio-system
|
||||
spec:
|
||||
quotas:
|
||||
- name: requestcount.quota.istio-system
|
||||
# default rate limit is 5000qps
|
||||
maxAmount: 5000
|
||||
validDuration: 1s
|
||||
# The first matching override is applied.
|
||||
# A requestcount instance is checked against override dimensions.
|
||||
overrides:
|
||||
# The following override applies to traffic from 'rewiews' version v2,
|
||||
# destined for the ratings service. The destinationVersion dimension is ignored.
|
||||
- dimensions:
|
||||
destination: ratings
|
||||
source: reviews
|
||||
sourceVersion: v2
|
||||
maxAmount: 1
|
||||
validDuration: 1s
|
||||
```
|
||||
|
||||
and then run the following command:
|
||||
1. Configure `memquota`, `quota`, `rule`, `QuotaSpec`, `QuotaSpecBinding` to
|
||||
enable rate limiting.
|
||||
|
||||
```command
|
||||
$ istioctl create -f ratelimit-handler.yaml
|
||||
$ istioctl create -f samples/bookinfo/kube/mixer-rule-ratings-ratelimit.yaml
|
||||
```
|
||||
|
||||
This configuration specifies a default 5000 qps rate limit. Traffic reaching the ratings service via
|
||||
reviews-v2 is subject to a 1qps rate limit. In our example user "jason" is routed via reviews-v2 and is therefore subject
|
||||
to the 1qps rate limit.
|
||||
The file looks like:
|
||||
{{< file_content url="https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/kube/mixer-rule-ratings-ratelimit.yaml" >}}
|
||||
|
||||
1. Configure rate limit instance and rule
|
||||
|
||||
Create a quota instance named `requestcount` that maps incoming attributes to quota dimensions,
|
||||
and create a rule that uses it with the memquota handler.
|
||||
|
||||
```yaml
|
||||
apiVersion: config.istio.io/v1alpha2
|
||||
kind: quota
|
||||
metadata:
|
||||
name: requestcount
|
||||
namespace: istio-system
|
||||
spec:
|
||||
dimensions:
|
||||
source: source.labels["app"] | source.service | "unknown"
|
||||
sourceVersion: source.labels["version"] | "unknown"
|
||||
destination: destination.labels["app"] | destination.service | "unknown"
|
||||
destinationVersion: destination.labels["version"] | "unknown"
|
||||
---
|
||||
apiVersion: config.istio.io/v1alpha2
|
||||
kind: rule
|
||||
metadata:
|
||||
name: quota
|
||||
namespace: istio-system
|
||||
spec:
|
||||
actions:
|
||||
- handler: handler.memquota
|
||||
instances:
|
||||
- requestcount.quota
|
||||
```
|
||||
|
||||
Save the configuration as `ratelimit-rule.yaml` and run the following command:
|
||||
1. Confirm the `memquota` was created:
|
||||
|
||||
```command
|
||||
$ istioctl create -f ratelimit-rule.yaml
|
||||
$ kubectl -n istio-system get memquota handler -o yaml
|
||||
```
|
||||
|
||||
1. Generate load on the `productpage` with the following command:
|
||||
```yaml
|
||||
apiVersion: config.istio.io/v1alpha2
|
||||
kind: memquota
|
||||
metadata:
|
||||
name: handler
|
||||
namespace: istio-system
|
||||
spec:
|
||||
quotas:
|
||||
- name: requestcount.quota.istio-system
|
||||
maxAmount: 5000
|
||||
validDuration: 1s
|
||||
overrides:
|
||||
- dimensions:
|
||||
destination: ratings
|
||||
source: reviews
|
||||
sourceVersion: v3
|
||||
maxAmount: 1
|
||||
validDuration: 5s
|
||||
- dimensions:
|
||||
destination: ratings
|
||||
maxAmount: 5
|
||||
validDuration: 10s
|
||||
```
|
||||
|
||||
The `memquota` defines 3 different rate limit schemes. The default, if no
|
||||
overrides match, is `5000` requests per `1s`. Two overrides are also
|
||||
defined. The first is `1` request every `5s` if the `destination` is
|
||||
`ratings`, the source is `reviews`, and the `sourceVersion` is `v3`. The
|
||||
second is `5` request every `10s` if the `destination` is `ratings`. The
|
||||
first matching override is picked (reading from top to bottom).
|
||||
|
||||
1. Confirm the `quota` was created:
|
||||
|
||||
```command
|
||||
$ while true; do curl -s -o /dev/null http://$GATEWAY_URL/productpage; done
|
||||
$ kubectl -n istio-system get quotas requestcount -o yaml
|
||||
```
|
||||
|
||||
1. Refresh the `productpage` in your browser.
|
||||
```yaml
|
||||
apiVersion: config.istio.io/v1alpha2
|
||||
kind: quota
|
||||
metadata:
|
||||
name: requestcount
|
||||
namespace: istio-system
|
||||
spec:
|
||||
dimensions:
|
||||
source: source.labels["app"] | source.service | "unknown"
|
||||
sourceVersion: source.labels["version"] | "unknown"
|
||||
destination: destination.labels["app"] | destination.service | "unknown"
|
||||
destinationVersion: destination.labels["version"] | "unknown"
|
||||
```
|
||||
|
||||
If you log in as user "jason" while the load generator is running (i.e., generating more than 1 req/s),
|
||||
the traffic generated by your browser will be rate limited to 1qps.
|
||||
The reviews-v2 service is unable to access the ratings service and you stop seeing stars.
|
||||
For all other users the default 5000qps rate limit will apply and you will continue seeing red stars.
|
||||
The `quota` template defines 4 `dimensions` that are used by `memquota` to
|
||||
set overrides on request that match certain attributes. `destination` will
|
||||
be set to the first non-empty value in `destination.labels["app"]`,
|
||||
`destination.service`, or `"unknown"`. More info on expressions can be
|
||||
found
|
||||
[here](/docs/reference/config/policy-and-telemetry/expression-language/).
|
||||
|
||||
1. Confirm the `rule` was created:
|
||||
|
||||
```command
|
||||
$ kubectl -n istio-system get rules quota -o yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: config.istio.io/v1alpha2
|
||||
kind: rule
|
||||
metadata:
|
||||
name: quota
|
||||
namespace: istio-system
|
||||
spec:
|
||||
actions:
|
||||
- handler: handler.memquota
|
||||
instances:
|
||||
- requestcount.quota
|
||||
```
|
||||
|
||||
The `rule` tells mixer to invoke `handler.memquota` handler (created
|
||||
above) and pass it the object constructed using the instance
|
||||
`requestcount.quota` (also created above). This effectively maps the
|
||||
dimensions from the `quota` template to `memquota` handler.
|
||||
|
||||
1. Confirm the `QuotaSpec` was created:
|
||||
|
||||
```command
|
||||
$ kubectl -n istio-system get QuotaSpec request-count -o yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: config.istio.io/v1alpha2
|
||||
kind: QuotaSpec
|
||||
metadata:
|
||||
name: request-count
|
||||
namespace: istio-system
|
||||
spec:
|
||||
rules:
|
||||
- quotas:
|
||||
- charge: "1"
|
||||
quota: requestcount
|
||||
```
|
||||
|
||||
This `QuotaSpec` defines the requestcount `quota` we created above with a
|
||||
charge of `1`.
|
||||
|
||||
1. Confirm the `QuotaSpecBinding` was created:
|
||||
|
||||
```command
|
||||
$ kubectl -n istio-system get QuotaSpecBinding request-count -o yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
kind: QuotaSpecBinding
|
||||
metadata:
|
||||
name: request-count
|
||||
namespace: istio-system
|
||||
spec:
|
||||
quotaSpecs:
|
||||
- name: request-count
|
||||
namespace: istio-system
|
||||
services:
|
||||
- name: ratings
|
||||
namespace: default
|
||||
- name: reviews
|
||||
namespace: default
|
||||
- name: details
|
||||
namespace: default
|
||||
- name: productpage
|
||||
namespace: default
|
||||
```
|
||||
|
||||
This `QuotaSpecBinding` binds the `QuotaSpec` we created above to the
|
||||
services we want to apply it to. Note we have to define the namespace for
|
||||
each service since it is not in the same namespace this `QuotaSpecBinding`
|
||||
resource was deployed into.
|
||||
|
||||
1. Refresh the `productpage` in your browser.
|
||||
|
||||
If you are logged out, reviews-v3 service is rate limited to 1 request
|
||||
every 5 seconds. If you keep refreshing the page the stars should only
|
||||
load around once every 5 seconds.
|
||||
|
||||
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 5000qps rate limit will apply.
|
||||
|
||||
## Conditional rate limits
|
||||
|
||||
In the previous example we applied a rate limit to the `ratings` service without regard
|
||||
to non-dimension attributes. It is possible to conditionally apply rate limits based on arbitrary
|
||||
attributes using a match condition in the quota rule.
|
||||
In the previous example we applied a rate limit to the `ratings` service
|
||||
without regard to non-dimension attributes. It is possible to conditionally
|
||||
apply rate limits based on arbitrary attributes using a match condition in
|
||||
the quota rule.
|
||||
|
||||
For example, consider the following configuration:
|
||||
|
||||
|
@ -151,36 +232,43 @@ spec:
|
|||
- requestcount.quota
|
||||
```
|
||||
|
||||
This configuration applies the quota rule to requests whose source and destination namespaces are different.
|
||||
This configuration applies the quota rule to requests whose source and
|
||||
destination namespaces are different.
|
||||
|
||||
## Understanding rate limits
|
||||
|
||||
In the preceding examples we saw how Mixer applies rate limits to requests that match certain conditions.
|
||||
In the preceding examples we saw how Mixer applies rate limits to requests
|
||||
that match certain conditions.
|
||||
|
||||
Every named quota instance like `requestcount` represents a set of counters.
|
||||
The set is defined by a Cartesian product of all quota dimensions.
|
||||
If the number of requests in the last `expiration` duration exceed `maxAmount`, Mixer returns a `RESOURCE_EXHAUSTED`
|
||||
message to the proxy. The proxy in turn returns status `HTTP 429` to the caller.
|
||||
The set is defined by a Cartesian product of all quota dimensions. If the
|
||||
number of requests in the last `expiration` duration exceed `maxAmount`,
|
||||
Mixer returns a `RESOURCE_EXHAUSTED` message to the proxy. The proxy in turn
|
||||
returns status `HTTP 429` to the caller.
|
||||
|
||||
The `memquota` adapter uses a sliding window of sub second resolution to enforce rate limits.
|
||||
The `memquota` adapter uses a sliding window of sub second resolution to
|
||||
enforce rate limits.
|
||||
|
||||
The `maxAmount` in the adapter configuration sets the default limit for all counters associated with a quota instance.
|
||||
This default limit applies if a quota override does not match the request. Memquota selects the first override that matches a request.
|
||||
An override need not specify all quota dimensions. In the ratelimit-handler.yaml example, the `1qps` override is
|
||||
selected by matching only three out of four quota dimensions.
|
||||
The `maxAmount` in the adapter configuration sets the default limit for all
|
||||
counters associated with a quota instance. This default limit applies if a
|
||||
quota override does not match the request. Memquota selects the first
|
||||
override that matches a request. An override need not specify all quota
|
||||
dimensions. In the example, the `0.2qps` override is selected by matching
|
||||
only three out of four quota dimensions.
|
||||
|
||||
If you would like the above policies enforced for a given namespace instead of the entire Istio mesh, you can replace all occurrences of istio-system with the given namespace.
|
||||
If you would like the above policies enforced for a given namespace instead
|
||||
of the entire Istio mesh, you can replace all occurrences of istio-system
|
||||
with the given namespace.
|
||||
|
||||
## Cleanup
|
||||
|
||||
* Remove the rate limit configuration:
|
||||
* Remove the rate limit configuration:
|
||||
|
||||
```command
|
||||
$ istioctl delete -f ratelimit-handler.yaml
|
||||
$ istioctl delete -f ratelimit-rule.yaml
|
||||
$ istioctl delete -f samples/bookinfo/kube/mixer-rule-ratings-ratelimit.yaml
|
||||
```
|
||||
|
||||
* Remove the application routing rules:
|
||||
* Remove the application routing rules:
|
||||
|
||||
```command
|
||||
$ istioctl delete -f samples/bookinfo/kube/route-rule-reviews-test-v2.yaml
|
||||
|
@ -193,6 +281,8 @@ If you would like the above policies enforced for a given namespace instead of t
|
|||
|
||||
## What's next
|
||||
|
||||
* Learn more about [Mixer](/docs/concepts/policies-and-telemetry/overview/) and [Mixer Config](/docs/concepts/policies-and-telemetry/config/).
|
||||
* Learn more about [Mixer](/docs/concepts/policies-and-telemetry/overview/) and
|
||||
[Mixer Config](/docs/concepts/policies-and-telemetry/config/).
|
||||
|
||||
* Discover the full [Attribute Vocabulary](/docs/reference/config/policy-and-telemetry/attribute-vocabulary/).
|
||||
* Discover the full
|
||||
[Attribute Vocabulary](/docs/reference/config/policy-and-telemetry/attribute-vocabulary/).
|
||||
|
|
Loading…
Reference in New Issue