Istio中的全局限流方案

Istio中的全局限流方案

在k8s网格(istio)环境中, 可以通过创建Envfoyfilter的方式来配置限流。

在istio官方文档中,提供了两种限流方式:

  • 本地限流
  • 全局限流

本地限流的细节这里不再赘述, 主要讲解全局限流的配置方式。

基本原理

istio通过向pod中注入sidecar,并通过envoy来代理流量,完成对流量的控制。

sidecar中的envoy, 由polit-agent管理。通过监听k8s中资源的变化,并由XDS协议下发配置到envoy中。

本地限流之所以称之为本地,是因为它只能为单个pod限流。 它通过hash桶算法进行流量分配。优点是可以平滑流量。

全局限流解决的是一个服务有多个pod的情况下,如何进行统一的限流。全局限流是通过sidecar中的envoy调用ratelimit服务来实现的。

全局限流

全局限流通过外部服务ratelimit来进行流量的统一控制。

ratelimit服务是一个独立的服务,它通过gRPC协议提供限流服务。envoy通过gRPC协议调用ratelimit服务,来获取限流的配置。

ratelimit中的配置管理支持configmapXDS两种方式。我们开发了单独的ratelimit-configserver服务,用于管理、下发配置到ratelimit服务中。

这里不赘述ratelimit-configserver的实现, 主要讲解如何在istio中配置全局限流。

使用ConfigMap的架构是这样的

ratelimit服务部署

具体的部署方式以及示例使用, 在istio的官方文档中有详细的介绍。这里不再赘述。文档地址https://istio.io/latest/zh/docs/tasks/policy-enforcement/rate-limit/#global-rate-limit-advanced-case

这里需要提的是, 官方文档中使用的镜像版本较老,不支持XDS的方式获取配置, 建议自行拉取最新代码并打包镜像。

配置说明

配置的方式比较生涩, 难以理解, 这里会着重说明一下。

基础配置说明

  • domain 限流策略的唯一标识,与EnvoyFilter中的domain字段对应
  • descriptors 用于声明详细的规则, 是一个数组, 可以配置多个规则
  • descriptors.key 规则的标识, 可以简单理解为http请求中某个header的代号(这并不准确,暂时先这样理解)
  • descriptors.value 规则的值, 用于匹配请求中的某个header的值。 不指定时则匹配所有请求
  • descriptors.rate_limit.unit 限流的单位, 可以是second, minute, hour, day
  • descriptors.rate_limit.requests_per_unit 每个单位时间内的请求数
yaml 复制代码
domain: ratelimit
    descriptors:
        - key: PATH
        value: "/productpage"
        rate_limit:
            unit: minute
            requests_per_unit: 1
        - key: PATH
        value: "api"
        rate_limit:
            unit: minute
            requests_per_unit: 2
        - key: PATH
        rate_limit:
            unit: minute
            requests_per_unit: 100

上面的配置表示:

对于/productpage路径的请求, 每分钟限流1次; 对于api路径的请求, 每分钟限流2次; 对于其他请求, 每分钟限流100次。

注意: /productpage 和 api 的请求次数会计入到100次的限流中。

官方文档示例中, 除了创建configmap外, 还有两个envoyfilter。 一个是用于配置ratelimit服务的地址(filter-ratelimit), 另一个是用于配置策略与请求之间的关系(filter-ratelimit-svc), 如KeyA对应的是请求头中的哪一个。

filter-ratelimit中我们主要关注typed_config这一项。

yaml 复制代码
# type 声明当前使用的API版本
"@type": type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
# domain与configmap中的配置匹配
domain: ratelimit
# failure_mode_deny 表示当ratelimit服务不可用时,是否拒绝请求。 
# 建议设为false, 这样即使我们的限流服务出现问题也不会影响业务服务的正常运行
failure_mode_deny: true
# timeout 速率限制服务RPC的超时(以毫秒为单位)。如果没有设置,则默认为20毫秒。
# 超时时间建议设的短一些, 这样可以快速失败,不会影响业务服务的正常运行
timeout: 10s
rate_limit_service:
    grpc_service:
        envoy_grpc:
            # 用于设置上游的ratelimit服务的端口号及地址
            # 这里测试时用ip会有问题 
            cluster_name: outbound|8081||ratelimit.default.svc.cluster.local
            # 会设置到authority标头中
            authority: ratelimit.default.svc.cluster.local
        # 用于设置请求携带的metadata
        initial_metadata: {}
    transport_api_version: V3

filter-ratelimit-svc中我们主要关注rate_limits这一项。

yaml 复制代码
rate_limits:
- actions: 
    - request_headers:
        // 这里说明PATH这个key,会从:path这个header中读取数据匹配value
        header_name: ":path"
        descriptor_key: "PATH"
    - request_headers:
        // 可以有多个, 也可通过其他方式匹配请求。如参数、正则等,具体查看istio文档
        header_name: "x-header-key"
        descriptor_key: "KeyA"
// action也可以有多个

高级配置

着重于ratelimit中的配置, 参考ratelimit官方文档

  1. 对database为user和database为default的请求分别限制

    yaml 复制代码
    domain: mongo_cps
     descriptors:
     - key: database
         value: users
         rate_limit:
         unit: second
         requests_per_unit: 500
    
     - key: database
         value: default
         rate_limit:
         unit: second
         requests_per_unit: 500
  2. 每个号码每天只允许100条信息; 且对message_type为marketing的信息, 每天每个号码只允许5条(算上5条,共在100条)

yaml 复制代码
domain: messaging
descriptors:
  - key: message_type
    value: marketing
    descriptors:
      - key: to_number
        rate_limit:
          unit: day
          requests_per_unit: 5
  - key: to_number
    rate_limit:
      unit: day
      requests_per_unit: 100
  1. 每个原地址(客户)允许10qps,"50.0.0.5"加入黑名单拒绝访问
yaml 复制代码
domain: edge_proxy_per_ip
descriptors:
  - key: remote_address
    rate_limit:
      unit: second
      requests_per_unit: 10
  - key: remote_address
    value: 50.0.0.5
    rate_limit:
      unit: second
      requests_per_unit: 0

总之, descriptors字段中, 多个规则平级为and关系, 多个规则嵌套为or关系

相关推荐
maomao大哥闯天下5 分钟前
K8s对象deployment、job、service应用详解
java·容器·kubernetes
IT策士28 分钟前
第 20 篇 搭建 Kubernetes 实验环境:Minikube 与 kubectl
云原生·容器·kubernetes
JackSparrow4141 小时前
使用Ansible批量管理+更新产品环境服务器配置
运维·服务器·ci/cd·kubernetes·自动化·ansible·sre
ai产品老杨2 小时前
基于 Docker 容器化与异构计算的智能安防架构:解耦 GB28181/RTSP 协议与多芯片适配,源码交付如何助力集成商节省 95% 开发成本?
docker·容器·架构
Plastic garden2 小时前
Docker(2)网络模式
运维·docker·容器
Elastic 中国社区官方博客2 小时前
Kibana 仪表板即代码:在 Elastic 9.4 中用于 Kibana 仪表板的 GitOps、漂移检测与 Terraform
大数据·人工智能·elasticsearch·搜索引擎·云原生·kibana·terraform
小哈里3 小时前
【K8S】云原生时代的GitOps最佳实践 —— ArgoCD
云原生·kubernetes·云计算·argocd·基础设施
张忠琳3 小时前
【kubernetes v1.21】(kube-apiserver 1)kube-apiserver 核心架构与启动流程超深度分析
云原生·架构·kubernetes
IT策士4 小时前
第 24 篇 k8s之健康检查:探针机制详解
云原生·容器·kubernetes
牛奶咖啡134 小时前
k8s容器编排技术实践——K8s对象deployment应用详解
kubernetes·deployment·deployment是什么·deployment有啥用·deployment优缺点·deployment状态解析·k8s创建资源的方式