10 KiB
| title | description | weight | keywords | aliases | |||
|---|---|---|---|---|---|---|---|
| Enabling Rate Limits | This task shows you how to use Istio to dynamically limit the traffic to a service. | 10 |
|
|
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 instructions in the Installation Guide.
-
Deploy the Bookinfo sample application.
The Bookinfo sample deploys 3 versions of the
reviewsservice:- Version v1 doesn’t call the
ratingsservice. - Version v2 calls the
ratingsservice, and displays each rating as 1 to 5 black stars. - Version v3 calls the
ratingsservice, and displays each rating as 1 to 5 red stars.
You need to set a default route to one of the versions. Otherwise, when you send requests to the
reviewsservice, Istio routes requests to all available versions randomly, and sometimes the output contains star ratings and sometimes it doesn't. - Version v1 doesn’t call the
-
Set the default version for all services to v1. If you’ve already created route rules for the sample, use
replacerather thancreatein the following command.{{< text bash >}} $ istioctl create -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@ {{< /text >}}
-
Initialize application version routing on the
reviewsservice to direct requests from the test user "jason" to version v2 and requests from any other user to v3.{{< text bash >}} $ istioctl replace -f @samples/bookinfo/networking/virtual-service-reviews-jason-v2-v3.yaml@ {{< /text >}}
Rate limits
In this task, you configure Istio to rate limit traffic to the ratings
service. Consider ratings as an external paid service like Rotten Tomatoes®
with 1 qps free quota. Using Istio, you can ensure that 1 qps is not exceeded.
For convenience, you configure the
memory quota
(memquota) adapter to enable rate limiting. On a production system, however,
you need Redis, and you configure the Redis
quota
(redisquota) adapter. Both the memquota and redisquota adapters support
the quota template,
so the configuration to enable rate limiting on both adapters is the same.
-
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
ratingsservice is being called by the "v2" version of thereviewsservice. -
If you log in as any other user, you should see red ratings stars with each review, indicating that the
ratingsservice is being called by the "v3" version of thereviewsservice.
-
-
Configure
memquota,quota,rule,QuotaSpec,QuotaSpecBindingto enable rate limiting.{{< text bash >}} $ istioctl create -f @samples/bookinfo/policy/mixer-rule-ratings-ratelimit.yaml@ {{< /text >}}
-
Confirm the
memquotahandler was created:{{< text bash yaml >}} $ kubectl -n istio-system get memquota handler -o 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 {{< /text >}}
The
memquotahandler defines 3 different rate limit schemes. The default, if no overrides match, is5000requests per one second (1s). Two overrides are also defined:- The first is
1request (themaxAmountfield) every5s(thevalidDurationfield), if thedestinationisratings, thesourceisreviews, and thesourceVersionisv3. - The second is
5requests every10s, if thedestinationisratings.
When a request is sent to the
ratingsservice, the first matching override is picked (reading from top to bottom). - name: requestcount.quota.istio-system
maxAmount: 5000
validDuration: 1s
overrides:
-
Confirm the
quotawas created:{{< text bash yaml >}} $ kubectl -n istio-system get quotas requestcount -o yaml apiVersion: config.istio.io/v1alpha2 kind: quota metadata: name: requestcount namespace: istio-system spec: dimensions: source: source.labels["app"] | "unknown" sourceVersion: source.labels["version"] | "unknown" destination: destination.labels["app"] | destination.service.host | "unknown" destinationVersion: destination.labels["version"] | "unknown" {{< /text >}}
The
quotatemplate defines four dimensions that are used bymemquotato set overrides on requests that match certain attributes. Thedestinationwill be set to the first non-empty value indestination.labels["app"],destination.service.host, or"unknown". For more information on expressions, see Expression Language. -
Confirm the
rulewas created:{{< text bash yaml >}} $ kubectl -n istio-system get rules quota -o yaml apiVersion: config.istio.io/v1alpha2 kind: rule metadata: name: quota namespace: istio-system spec: actions:
- handler: handler.memquota
instances:
- requestcount.quota {{< /text >}}
The
ruletells Mixer to invoke thehandler.memquotahandler (created above) and pass it the object constructed using the instancerequestcount.quota(also created above). This maps the dimensions from thequotatemplate tomemquotahandler. - handler: handler.memquota
instances:
-
Confirm the
QuotaSpecwas created:{{< text bash yaml >}} $ kubectl -n istio-system get QuotaSpec request-count -o yaml apiVersion: config.istio.io/v1alpha2 kind: QuotaSpec metadata: name: request-count namespace: istio-system spec: rules:
- quotas:
- charge: "1" quota: requestcount {{< /text >}}
This
QuotaSpecdefines therequestcount quotayou created above with a charge of1. - quotas:
-
Confirm the
QuotaSpecBindingwas created:{{< text bash yaml >}} $ kubectl -n istio-system get QuotaSpecBinding request-count -o 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 {{< /text >}}
This
QuotaSpecBindingbinds theQuotaSpecyou created above to the services you want to apply it to. You have to define the namespace for each service since it is not in the same namespace thisQuotaSpecBindingresource was deployed into. -
Refresh the
productpagein your browser.-
If you are logged out,
reviews-v3service 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-v2service 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
In the previous example you 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:
{{< text yaml >}} apiVersion: config.istio.io/v1alpha2 kind: rule metadata: name: quota namespace: istio-system spec: match: source.namespace != destination.namespace actions:
- handler: handler.memquota
instances:
- requestcount.quota {{< /text >}}
This configuration applies the quota rule to requests whose source and destination namespaces are different.
Understanding rate limits
In the preceding examples you 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 Envoy proxy, and Envoy
returns status HTTP 429 to the caller.
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. The memquota adapter selects the first
override that matches a request. An override need not specify all quota
dimensions. In the example, the 0.2 qps override is selected by matching only
three out of four quota dimensions.
If you want the 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:
{{< text bash >}} $ istioctl delete -f @samples/bookinfo/policy/mixer-rule-ratings-ratelimit.yaml@ {{< /text >}}
-
Remove the application routing rules:
{{< text bash >}} $ istioctl delete -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@ {{< /text >}}
-
If you are not planning to explore any follow-on tasks, refer to the Bookinfo cleanup instructions to shutdown the application.