启用速率限制

这部分内容将向您展示如何使用 Istio 去动态限制服务间的流量。

开始之前

Policy enforcement 必须开启。依照启用 Policy Enforcement 确定 policy enforcement 已经开启。

Bookinfo 部署了 3 个版本的 reviews 服务:

  • 版本 v1 不会调用 ratings 服务。
  • 版本 v2 调用 ratings 服务,且为每个评价显示 1 到 5 颗黑色星星。
  • 版本 v3 调用 ratings 服务,且为每个评价显示 1 到 5 颗红色星星。您需要指定其中一个版本为默认路由。否则,当您向 reviews 服务发送请求时,Istio 会随机路由到其中一个服务上,表现为有时显示星星,有时不会。
  • 将所有服务的默认版本设置为 v1。

Zip

  1. $ kubectl apply -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@

速率限制

在这部分,Istio 将以客户端的 IP 地址限制 productpage 的流量。您将会使用 X-Forwarded-For 请求头作为客户端 IP 地址。也将会针对已登录的用户应用有条件的速率限制。

方便起见,配置 memory quota(memquota) 适配器用以启用速率限制。如果在生产系统使用的是 Redis,那么启用 Redis quota(redisquota) 适配器。memquotaredisquota 适配器都支持 quota template,所以他们的配置是一样的。

  • 速率限制的配置分为两部分。

    • 客户端
      • QuotaSpec 定义 quota 名称与客户端请求的数量。
      • QuotaSpecBinding 条件化的关联 QuotaSpec 到一个或多个服务。
    • Mixer 端
      • quota instance 定义 quota 的维度。
      • memquota handler 定义 memquota 适配器的配置。
      • quota rule 定义 quota 实例何时分发到 memquota 适配器。执行如下命令使用 memquota 开启速率限制:

Zip

  1. $ kubectl apply -f @samples/bookinfo/policy/mixer-rule-productpage-ratelimit.yaml@

如果您使用 Istio 1.1.2 或更低版本,使用如下命令代替:

Zip

  1. $ kubectl apply -f @samples/bookinfo/policy/mixer-rule-productpage-ratelimit-crd.yaml@

memquota 处理器定义了 4 个不同的速率限制规则。默认如果没有匹配到优先规则,是 500 个请求量每秒 (1s)。我们也定义了两个优先规则:

  • 第一种是 1 个请求量 (maxAmount 字段) 每 5s (validDuration 字段),如果目标服务reviews
  • 第二种是 500 个请求量每 1s,如果目标服务productpage 且来源于 10.28.11.20
  • 第三种是 2 个请求量每 5s,如果目标服务productpage。当一个请求被处理时,第一个被匹配到的优先规则会被触发(从上到下)。

或者

执行如下命令使用 redisquota 开启流量限制:

Zip

  1. $ kubectl apply -f @samples/bookinfo/policy/mixer-rule-productpage-redis-quota-rolling-window.yaml@

注意: 替换您的配置中 rate_limit_algorithmredis_server_url 的值.

redisquota 处理器定义了 4 个不同的速率限制规则。默认如果没有匹配到优先规则,是 500 个请求量每秒 (1s)。使用了 ROLLING_WINDOW 算法作为 quota 检查且为之定义了 500ms 的 bucketDuration。我们也定义了三个优先规则:

  • 第一种是 1 个请求量 (maxAmount 字段),如果目标服务reviews
  • 第二种是 500,如果目标服务productpage 且来源于 10.28.11.20
  • 第三种是 2,如果目标服务productpage。当一个请求被处理时,第一个被匹配到的优先规则会被触发(从上到下)。
  • 确认 quota 实例已被创建:
  1. $ kubectl -n istio-system get instance requestcountquota -o yaml

quota 模板通过 memquotaredisquota 定义了三个维度以匹配特定的属性的方式设置优先规则。目标服务会被设置为 destination.labels["app"]destination.service.host,或 "unknown" 中的第一个非空值。表达式的更多信息,见 Expression Language

  • 确认 quota rule 已被创建:
  1. $ kubectl -n istio-system get rule quota -o yaml

rule 告诉 Mixer 去调用 memquotaredisquota 处理器(上面创建的)且传递 requestcountquota 构造的对象(也是上面创建的)。这里将 quota 模板与 memquotaredisquota 处理器的维度一一对应。

  • 确认 QuotaSpec 已被创建:
  1. $ kubectl -n istio-system get QuotaSpec request-count -o yaml

QuotaSpec 用值 1 定义了您上面创建的 requestcountquota

  • 确认 QuotaSpecBinding 已被创建:
  1. $ kubectl -n istio-system get QuotaSpecBinding request-count -o yaml

QuotaSpecBinding 绑定了您上面创建的 QuotaSpec 与您想要生效的服务。productpage 显式的绑定了 request-count,注意您必须定义与 QuotaSpecBinding 不同的命名空间。如果最后一行注释被打开, service: '*' 将绑定所有服务到 QuotaSpec 使得首个 entry 是冗余的。

  • 在浏览器上刷新 product 页面。

request-count quota 应用于 productpage 且只允许 2 个请求量每 5 秒。如果您持续刷新页面将会看到RESOURCE_EXHAUSTED:Quota is exhausted for: requestcount

条件化的速率限制

在上面的例子我们为每个客户端 IP 地址的 productpage 限制了 2 rps。考虑这样一个场景,如果您想要对已登录的用户放开速率限制。在 bookinfo 的例子中,我们用 cookie session=<sessionid> 去指代一个已登录用户。在现实场景中您可能会用 jwt token 去实现这个目的。

您可以添加基于 cookie 的匹配条件更新 quota rule

  1. $ kubectl -n istio-system edit rules quota
  1. ...
  2. spec:
  3. match: match(request.headers["cookie"], "session=*") == false
  4. actions:
  5. ...

不要启用 chrome preload,它会预加载 cookies 从而导致此任务失败。

memquotaredisquota 适配器现在只有请求中存在 session=<sessionid> cookie 才会被分发。这可以确保已登录的用户不会受限于这个 quota。

  • 确认速率限制没有生效于已登录的用户。

jason 身份登录且反复刷新 productpage 页面。现在这样做不会出现任何问题。

  • 确认速率限制 生效 于未登录的用户。

退出登录且反复刷新 productpage 页面。您将会再次看到 RESOURCE_EXHAUSTED:Quota is exhausted for: requestcount

理解原理

在先前的例子中你已经看到了 Mixer 是怎么通过匹配特定的条件对请求应用速率限制的。

每个具名的 quota 实例比如 requestcount 会提供一组计数器。这组计数器用所有 quota 维度的笛卡尔积来定义。如果最后一个有效期内的请求数超出 maxAmount,Mixer 返回一个 RESOURCE_EXHAUSTED 消息给 Envoy 代理,然后 Envoy 返回状态码 HTTP 429 给调用者。

memquota 适配器使用一个亚秒级的滑动窗口来执行速率限制。

redisquota 适配器可以配置使用ROLLING_WINDOWFIXED_WINDOW算法之一来执行速率限制。

适配器配置内的 maxAmount 为所有关联到 quota 实例的计数器设置了默认限制。这个默认限制应用在其他优先规则没有被匹配到的时候。memquota/redisquota 适配器会选择第一个与请求相匹配的优先规则。一个优先规则不能指明所有的 quota 维度。在这个例子里,0.2 qps 的规则被选择到通过只匹配了四分之三的 quota 维度。

如果您想要策略在给定的命名空间上执行而非整个 Istio 网格,可以把前面所有出现的 istio-system 替换为您想要的命名空间。

清理

  • 如果使用 memquota,移除 memquota 速率限制配置:

Zip

  1. $ kubectl delete -f @samples/bookinfo/policy/mixer-rule-productpage-ratelimit.yaml@

如果您使用 Istio 1.1.2 或更低:

Zip

  1. $ kubectl delete -f @samples/bookinfo/policy/mixer-rule-productpage-ratelimit-crd.yaml@

如果使用 redisquota,移除 redisquota 速率限制配置:

Zip

  1. $ kubectl delete -f @samples/bookinfo/policy/mixer-rule-productpage-redis-quota-rolling-window.yaml@
  • 移除应用路由规则:

Zip

  1. $ kubectl delete -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@
  • 如果您不准备探索更多的任务,参考 Bookinfo cleanup 关闭整个应用。

相关内容

App Identity and Access Adapter

Using Istio to secure multi-cloud Kubernetes applications with zero code changes.

Mixer and the SPOF Myth

Improving availability and reducing latency.

Mixer Adapter Model

Provides an overview of Mixer's plug-in architecture.

Control Headers and Routing

Shows how to modify request headers and routing using policy adapters.

Denials 和黑白名单

描述如何使用简单的 denials 或黑白名单来控制对服务的访问。

Enabling Policy Enforcement

This task shows you how to enable Istio policy enforcement.