写点什么

kube-apiserver 限流机制原理

  • 2024-04-07
    广东
  • 本文字数:3564 字

    阅读完需:约 12 分钟

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的总并发上限
复制代码


两个阶段限流能力对比


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 资源不为空闲表示已达到并发上限


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

发布于: 刚刚阅读数: 4
用户头像

提供全面深入的云计算技术干货 2020-07-14 加入

生于云,长于云,让开发者成为决定性力量

评论

发布
暂无评论
kube-apiserver限流机制原理_Kubernetes_华为云开发者联盟_InfoQ写作社区