本文已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已变得不正确。

API 优先级和公平性 Alpha 版

本博客介绍了 Kubernetes 1.18 中的一项新 alpha 功能“API 优先级和公平性”。API 优先级和公平性允许集群管理员将控制平面的并发性划分为不同的加权优先级级别。到达 kube-apiserver 的每个请求都将被分类到一个优先级级别,并获得控制平面吞吐量的公平份额。

这解决了什么问题?

今天,apiserver 有一种简单的机制来保护自己免受 CPU 和内存过载的影响:用于修改请求和只读请求的最大并行数限制。除了修改和只读之间的区别之外,请求之间没有其他区别;因此,可能会出现不希望出现的情况,即一个请求子集排挤其他请求。

简而言之,Kubernetes 工作负载很容易意外地对 apiserver 进行 DoS 攻击,导致其他重要流量(如系统控制器或领导者选举)间歇性地失败。在最坏的情况下,一些损坏的节点或控制器可能会将繁忙的集群推向崩溃的边缘,将局部问题转变为控制平面中断。

我们如何解决这个问题?

新功能“API 优先级和公平性”旨在概括每个 apiserver 中现有的最大并行请求处理程序,以使行为更智能、可配置。总体方法如下。

  1. 每个请求都与一个 *Flow Schema* 匹配。Flow Schema 说明了匹配请求的优先级级别,并为这些请求分配一个“流标识符”。流标识符是系统确定请求是否来自同一来源的方式。
  2. 可以配置优先级级别的行为方式。每个优先级级别都有其自己的独立并发池。优先级级别还引入了对无法立即处理的请求进行排队的概念。
  3. 为了防止任何一个用户或命名空间垄断优先级级别,可以将其配置为具有多个队列。“洗牌分片”用于将每个请求流分配到队列的子集。
  4. 最后,当有能力处理请求时,使用 “公平排队”算法来选择下一个请求。在每个优先级级别内,队列以均匀的公平性竞争。

早期结果非常令人鼓舞!请看此分析

我如何尝试?

您需要准备以下内容才能试用该功能

  • 下载并安装大于 v1.18.0 版本的 kubectl
  • 在 kube-apiserver 上使用命令行标志 --runtime-config="flowcontrol.apiserver.k8s.io/v1alpha1=true" 启用新的 API 组
  • 在 kube-apiserver 上使用命令行标志 --feature-gates=APIPriorityAndFairness=true 启用功能门控

成功启动 kube-apiserver 后,您将在集群中看到一些默认的 FlowSchema 和 PriorityLevelConfiguration 资源。这些默认配置旨在为您的集群提供一般的保护和流量管理。您可以使用常用工具(例如)检查和自定义默认配置。

  • kubectl get flowschemas
  • kubectl get prioritylevelconfigurations

这在底层是如何工作的?

到达处理程序时,请求会被分配给一个优先级级别和该优先级级别中的一个流。因此,了解 FlowSchema 和 PriorityLevelConfiguration 的工作方式将帮助您管理通过 kube-apiserver 的请求流量。

  • FlowSchema:FlowSchema 将识别 PriorityLevelConfiguration 对象以及计算请求“流标识符”的方式。目前,我们支持根据以下内容匹配请求:发出请求的身份、动词和目标对象。身份可以根据以下内容匹配:用户名、用户组名称或 ServiceAccount。对于目标对象,我们可以通过 apiGroup、资源[/子资源]和命名空间进行匹配。

    • 流标识符用于洗牌分片,因此如果请求来自同一来源,则这些请求具有相同的流标识符非常重要!我们喜欢考虑“大象”(发送许多/繁重的请求)与“老鼠”(发送少量/轻量级的请求)的场景:重要的是确保大象的所有请求都获得相同的流标识符,否则它们看起来像系统中的许多不同的老鼠!
    • 请在此处查看 API 文档:这里
  • PriorityLevelConfiguration:定义优先级级别。

    • 对于 apiserver 自我请求和任何重入流量(例如,本身发出 API 请求的 admission webhooks),优先级级别可以标记为“豁免”,这意味着不进行任何类型的排队或限制。这是为了防止优先级反转。
    • 每个非豁免优先级级别都配置有多个“并发份额”,并获得一个独立的并发池来使用。该优先级级别的请求在该池未满时在该池中运行,而绝不会在其他地方运行。每个 apiserver 都配置有总并发限制(被视为修改和只读请求的旧限制的总和),然后该限制按并发份额的比例在优先级级别之间分配。
    • 非豁免优先级级别可以选择多个队列和一个用于洗牌分片的“手牌大小”。洗牌分片以优于一致哈希的方式将流映射到队列。给定流可以访问少量队列,并且对于每个传入请求,将选择最短的队列。当优先级级别具有队列时,它还会设置队列长度限制。还限制了请求在其队列中可以等待的时间;这是 apiserver 请求超时时间的固定分数。无法执行且无法(更长)排队的请求将被拒绝。
    • 或者,非豁免优先级级别可以选择立即拒绝,而不是在队列中等待。
    • 请参阅此功能的 API 文档

缺少什么?何时会有 beta 版?

我们已经在基于 alpha 计划一些增强功能,并且随着用户向我们的社区发送反馈,还将会有更多增强功能。这是它们的列表

  • WATCH 和 EXEC 请求的流量管理
  • 调整和改进默认的 FlowSchema/PriorityLevelConfiguration 集
  • 增强对该功能如何工作的可观察性
  • 请在此处加入讨论:这里

可能会根据对其结果大小的估计来不同地处理 LIST 请求。

我如何参与?

一如既往!请在 Slack 上联系我们:#sig-api-machinery,或通过邮件列表联系我们。我们有很多激动人心的功能要构建,并且可以使用各种帮助。

非常感谢为该功能做出贡献的贡献者:Aaron Prindle、Daniel Smith、Jonathan Tomer、Mike Spreitzer、Min Kim、Bruce Ma、Yu Liao、Mengyi Zhou!