kube-apiserver限流机制原理

本文分享自华为云社区《kube-apiserver限流机制原理》,作者:可以交个朋友。

背景

apiserver是kubernetes中最重要的组件,一旦遇到恶意刷接口或请求量超过承载范围,apiserver服务可能会崩溃,导致整个kubernetes集群不可用。所以我们需要对apiserver做限流处理来提升kubernetes的健壮性。

k8s-apiserver限流能力发展过程

apiserver限流能力的发展分为两个阶段:
kubernetes 1.18版本之前kube-apiserver只是将请求分成了变更类型(create、update、delete、patch)和非变更类型(get、list、watch),并通过启动参数设置了两种类型的最大并发数。

复制代码
--max-requests-inflight          ## 限制同时运行的非变更类型请求的个数上限,0表示无限制。 
--max-mutating-requests-inflight   ## 限制同时运行的变更类型请求的个数上限。0 表示无限制。

此时的apiserver限流能力较弱,若某个客户端错误的向kube-apiserver发起大量的请求时,必然会阻塞kube-apiserver,影响其他客户端的请求,因此高阶的限流APF就诞生了。
kubernetes1.18版本之后APF( APIPriorityAndFairness )成为kubernetes的默认限流方式。 APF以更细粒度的方式对请求进行分类和隔离,根据优先级和公平性进行处理。

复制代码
--enable-priority-and-fairness   ##  该值作为APF特性开关,默认为true 
--max-requests-inflight、--max-mutating-requests-inflight    ## 当开启APF时,俩值相加确定kube-apiserver的总并发上限

两个阶段限流能力对比

限流能力 1.18版本前 1.18版本后(APF)
颗粒度 仅根据是否变更做分类 可以根据请求对象、请求者身份、命名空间等做分类
隔离性 一个坏用户可能堵塞整个系统 为请求分配固定队列,坏请求只能撑爆其使用的队列
公平性 会出现饿死 用公平性算法从队列中取出请求
优先级 有特权级别,可让重要请求不被限制

APF关键资源介绍

APF通过FlowSchema 和 PriorityLevelConfiguration两个资源配置限流策略。
FlowSchema:解决老版本分类颗粒度粗的问题。根据rules字段匹配请求,匹配规则包含:请求对象、执行操作、请求者身份和命名空间

复制代码
apiVersion: flowcontrol.apiserver.k8s.io/v1beta2 
kind: FlowSchema                 # 一个kubernetes集群中可以定义多个FlowSchema 
metadata: 
  name: myfl 
spec: 
  distinguisherMethod:           # 可选值为:ByNamespace或ByUser,用于把请求分组。属于同组的请求会分配到固定的queue中,如果省略该参数,则该FlowSchema匹配的所有请求都将视为同一个分组。
    type: ByUser 
  matchingPrecedence: 90         # 数字越小代表FlowSchema的匹配顺序越在前,取值范围:1~10000。 
  priorityLevelConfiguration:    # FlowSchema关联的priorityLevelConfiguration 
    name: mypl 
  rules:
  - nonResourceRules:            # 匹配非资源型:匹配接口URL 
    - nonResourceURLs: 
      - '*' 
    resourceRules:               # 匹配资源型:匹配apigroup、namespace、resources、verbs 
    - apiGroups: 
      - '*' 
      namespaces: 
      - '*' 
      resources: 
      - '*' 
      verbs: 
      - get 
      - create 
      - list 
      - update 
    subjects:                   # 匹配请求者主体:可选Group、User、ServiceAccount 
    - group: 
        name: '*' 
      kind: Group 
    - kind: User 
      user: 
        name: '*' 
    - kind: ServiceAccount 
      serviceAccount: 
        name: myserviceaccount 
        namespace: demo 

PriorityLevelConfiguration:解决老版本隔离性差的问题和优先级问题,并定义了限流细节(总队列数、队列长度、是否可排队)。当请求与某个FlowSchema匹配后,该请求会关联FlowSchema中指定的PriorityLevelConfiguration资源,每个PriorityLevelConfiguration相互隔离,且能承受的并发请求数也不一样

复制代码
apiVersion: flowcontrol.apiserver.k8s.io/v1beta2 
kind: PriorityLevelConfiguration          ## 每个PriorityLevelConfiguration有自己独立的限流配置, PriorityLevelConfiguration之间是完全隔离的。 
metadata: 
  name: mypl 
spec: 
  type: Limited                           # 设置是否为特权级别,如果为Exempt则不进行限流,如果为Limited则进行限流 
  limited: 
    assuredConcurrencyShares: 2           # 值越大,PriorityLevelConfiguration的并发上限越高。若当前并发执行数未达到并发上限,则PL处于空闲状态。 
    limitResponse:                        # 定义如何处理当前无法被处理的请求 
      type: Queue                         # 类型,Queue或者Reject,Reject直接返回429并拒绝,Queue将请求加入队列 
      queuing: 
        handSize: 1                       # 根据ByNamespace或ByUser对请求分组,每个分组对应queues的数量, 
        queueLengthLimit: 20              # 此PriorityLevelConfiguration中每个队列的长度 
        queues: 2                         # 此PriorityLevelConfiguration中的队列数

一个FlowSchema只能关联一个priorityLevelConfiguration,多个FlowSchema可以关联同一个priorityLevelConfiguration
PriorityLevelConfiguration并发上限 = assuredConcurrencyShares / 所有assuredConcurrencyShares之和 * apiserver总并发数

APF处理过程

请求与集群中的FlowSchema列表按照顺序依次匹配,每个FlowSchema的matchingPrecedence字段决定其在列表中的顺序,matchingPrecedence字段值越小,越靠前,越先进行匹配请求。

根据FlowSchema资源中的rules规则进行匹配,匹配方式可以是 "请求的资源类型"、"请求的动作类型"、"请求者的身份"、"请求的命名空间" 等多个维度。

若请求与某个FlowSchema成功匹配,匹配就会结束。FlowSchema关联着一个PriorityLevelConfiguration,每个PriorityLevelConfiguration中包含许多queue,根据FlowSchema.spec.Distinguisher字段将请求进行"分组",根据分组来分配queue,分配queue数量由PriorityLevelConfiguration资源的handSize字段决定,如果省略该参数,则该FlowSchema匹配的所有请求都将视为同一个"分组"。

每个PriorityLevelConfiguration资源都有独立的并发上限,assuredConcurrencyShares字段为apiserver总并发数的权重占比,值越大分配的并发上限就越高,当PriorityLevelConfiguration达到并发上限后,请求会根据所属的"分组"写入固定的queue中,请求被阻塞等待。请求与queue的固定关联可以让恶意用户只影响其使用的queue,而不会影响同PriorityLevelConfiguration中的其他queue。

当PriorityLevelConfiguration未达到并发上限时,fair queuing算法从所有queue中选择一个合适的queue取出请求,解除请求的阻塞,执行这个请求。fair queuing算法能保证同一个 PriorityLevelConfiguration 中的所有queue被处理机会平等。

APF实战

kubernetes原生自带了一些FlowSchema和PriorityLevelConfiguration规则,我们选择一个查看,如下图:

下面我们创建新的APF规则:当请求对象是apf命名空间中的deployment,则进行"apfpl"限流规则。

复制代码
apiVersion: flowcontrol.apiserver.k8s.io/v1beta2 
kind: FlowSchema 
metadata: 
  name: apffl 
spec: 
  matchingPrecedence:  150 
  priorityLevelConfiguration: 
    name: apfpl                           ## 关联名为apfpl的PriorityLevelConfiguration 
  rules: 
    - resourceRules: 
      - apiGroups: 
          - apps 
        clusterScope: true 
        namespaces: 
          - apf                           ## 匹配apf命名空间 
        resources: 
          - deployments                   ## 匹配操作deployment的请求 
        verbs: 
          - '*'                           ## 匹配任意操作类型 
      subjects: 
        - kind: Group 
          group: 
            name: '*'                     ## 匹配任意组身份  
--- 
apiVersion: flowcontrol.apiserver.k8s.io/v1beta2 
kind: PriorityLevelConfiguration 
metadata: 
  name: apfpl 
spec: 
  limited: 
    assuredConcurrencyShares: 2             
    limitResponse:                         ## 设置限流处理细节 
      queuing: 
        handSize: 1  
        queueLengthLimit: 20                 
        queues: 2  
      type: Queue 
  type: Limited                             ## 对请求做限流处理

接着在apf命名空间和default命名空间分别创建deployment进行测试。apf_fs为请求被分类到的 FlowSchema 的名称,apf_pl为该请求的优先级名称。查看apiserver日志信息,见下图:

循环操作deployment,我们可以使用命令查看是否触发限流等待

复制代码
kubectl get --raw /debug/api_priority_and_fairness/dump_priority_levels

返回waitingRequests非0,则代表触发最大并发数,有请求被限流进入等待队列。PriorityLevelConfiguration资源不为空闲表示已达到并发上限

点击关注,第一时间了解华为云新鲜技术~

相关推荐
华为云开发者联盟3 个月前
最佳实践:解读GaussDB(DWS) 统计信息自动收集方案
大数据·华为云开发者联盟·gaussdb(dws)·gaussdb(dws)·实时查询·统计信息
华为云开发者联盟3 个月前
深度解读KubeEdge架构设计与边缘AI实践探索
ai·边缘计算·kubeedge·华为云开发者联盟·sedna
华为云开发者联盟3 个月前
仓颉编程语言技术指南:嵌套函数、Lambda 表达式、闭包
鸿蒙·编程语言·华为云开发者联盟·仓颉
华为云开发者联盟3 个月前
深度解读GaussDB(for MySQL)与MySQL的COUNT查询并行优化策略
mysql·华为云开发者联盟
华为云开发者联盟3 个月前
Kmesh v0.4发布!迈向大规模 Sidecarless 服务网格
容器·华为云开发者联盟
华为云开发者联盟4 个月前
解读GaussDB(for MySQL)灵活多维的二级分区表策略
mysql·华为云开发者联盟
华为云开发者联盟4 个月前
从基础到高级应用,详解用Python实现容器化和微服务架构
python·docker·微服务·容器·华为云开发者联盟
华为云开发者联盟4 个月前
基于MindSpore实现BERT对话情绪识别
昇腾·华为云开发者联盟
华为云开发者联盟4 个月前
解读MySQL 8.0数据字典缓存管理机制
mysql·缓存·数据字典·元数据·华为云开发者联盟
华为云开发者联盟4 个月前
深度解读昇腾CANN模型下沉技术,提升模型调度性能
大模型·昇腾·cann·华为云开发者联盟