启用速率限制

这部分内容将向您展示如何使用 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 身份和访问适配器

使用 Istio 实现零代码改动保护多云 Kubernetes 应用。

Mixer 和 SPOF 神话

提高可用,降低延迟。

Mixer 适配器模型

概要说明 Mixer 的插件架构。

Denials 和黑白名单

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

Mixer 配置模型

描述 Istio 策略执行和遥测机制的配置模型。

TLS Egress 监控和策略配置

描述如何在 TLS Egress 上配置 SNI 监控和策略。