本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
API 优先级和公平性 Alpha
这篇博客文章描述了“API 优先级和公平性”,这是 Kubernetes 1.18 中的一个新 alpha 特性。API 优先级和公平性允许集群管理员将控制平面的并发性划分为不同的加权优先级级别。每个到达 kube-apiserver 的请求都将被归类到其中一个优先级级别,并获得其在控制平面吞吐量中的公平份额。
这解决了什么问题?
目前,apiserver 有一个简单的机制来保护自身免受 CPU 和内存过载:对修改和只读请求的最大并发限制。除了修改和只读的区别之外,请求之间没有其他区别;因此,可能会出现不良情况,即某些请求子集会挤占其他请求。
简而言之,Kubernetes 工作负载太容易意外地对 apiserver 进行拒绝服务攻击 (DoS),导致其他重要流量(例如系统控制器或领导者选举)间歇性失败。在最糟糕的情况下,少数损坏的节点或控制器可能会使繁忙的集群陷入崩溃边缘,将局部问题转化为控制平面中断。
我们如何解决这个问题?
新特性“API 优先级和公平性”旨在概括每个 apiserver 中现有的最大并发请求处理程序,使行为更加智能和可配置。总体方法如下:
- 每个请求都由一个 _Flow Schema_ 匹配。Flow Schema 说明了匹配请求的优先级级别,并为这些请求分配一个“流标识符”。流标识符是系统判断请求是否来自同一源的方式。
- 优先级级别可以配置为以多种方式运行。每个优先级级别都有自己的独立并发池。优先级级别还引入了排队无法立即处理的请求的概念。
- 为了防止任何一个用户或命名空间垄断一个优先级级别,可以将其配置为拥有多个队列。使用 “随机分片 (Shuffle Sharding)” 来将每个请求流分配到队列的子集。
- 最后,当有能力处理请求时,使用 “公平排队 (Fair Queuing)” 算法来选择下一个请求。在每个优先级级别内,队列以相同的公平性竞争。
早期结果非常有前景!请查看此 分析。
我该如何试用这个功能?
为了试用此功能,您需要准备以下事项
- 下载并安装 v1.18.0 或更高版本的 kubectl
- 在 kube-apiserver 上使用命令行标志
--runtime-config="flowcontrol.apiserver.k8s.io/v1alpha1=true"
启用新的 API 组 - 在 kube-apiserver 上使用命令行标志
--feature-gates=APIPriorityAndFairness=true
开启特性门控
成功启动 kube-apiservers 后,您将在集群中看到一些默认的 FlowSchema 和 PriorityLevelConfiguration 资源。这些默认配置旨在为您的集群提供通用的保护和流量管理。您可以使用常用工具(例如)检查和自定义默认配置:
kubectl get flowschemas
kubectl get prioritylevelconfigurations
这个功能是如何在底层工作的?
请求到达处理程序后,会被精确地分配到一个优先级级别以及该优先级级别内的一个流。因此,理解 FlowSchema 和 PriorityLevelConfiguration 如何工作将有助于您管理通过 kube-apiservers 的请求流量。
FlowSchema:FlowSchema 将标识一个 PriorityLevelConfiguration 对象以及计算请求“流标识符”的方式。目前我们支持根据请求的发起者身份、动词和目标对象来匹配请求。身份可以根据:用户名、用户组名或 ServiceAccount 进行匹配。至于目标对象,我们可以通过 apiGroup、resource[/subresource] 和 namespace 进行匹配。
- 流标识符用于随机分片,因此如果请求来自同一源,则请求具有相同的流标识符很重要!我们喜欢考虑“大象”(发送许多/大量请求)与“小鼠”(发送少量/轻量请求)的场景:重要的是要确保大象的请求都获得相同的流标识符,否则它们在系统中看起来会像许多不同的小鼠!
- 请参阅 此处 的 API 文档!
PriorityLevelConfiguration:定义一个优先级级别。
- 对于 apiserver 自身请求和任何可重入流量(例如,自身发出 API 请求的准入 webhook),优先级级别可以标记为“exempt”(豁免),这意味着不进行任何类型的排队或限制。这是为了防止优先级反转。
- 每个非豁免优先级级别都配置有一定数量的“并发份额”,并获得一个独立的并发池来使用。该优先级级别的请求在该池未满时在该池中运行,绝不在其他地方运行。每个 apiserver 都配置有总并发限制(视为修改和只读请求的旧限制之和),然后根据优先级级别的并发份额按比例分配给各个优先级级别。
- 一个非豁免的优先级级别可以选择用于随机分片的队列数量和“手牌大小 (hand size)”。随机分片将流映射到队列的方式优于一致性哈希。给定的流可以访问一小部分队列,对于每个传入请求,选择最短的队列。当一个优先级级别有队列时,它也会设置队列长度的限制。还有一个限制是请求可以在其队列中等待多长时间;这等于 apiserver 请求超时的一个固定比例。无法执行且无法(再)排队的请求将被拒绝。
- 或者,非豁免优先级级别可以选择立即拒绝,而不是在队列中等待。
- 请参阅此功能的 API 文档。
还缺少什么?什么时候会有 Beta 版本?
我们已经在根据 alpha 版本规划一些增强功能,随着用户向社区发送反馈,还会增加更多。以下是其中的一些列表:
可能会根据 LIST 请求的结果大小估计值,区别对待它们。
我该如何参与?
一如既往!在 Slack 上联系我们 #sig-api-machinery,或通过 邮件列表。我们有许多令人兴奋的功能需要构建,可以使用各种帮助。
非常感谢为该功能做出贡献的开发者:Aaron Prindle, Daniel Smith, Jonathan Tomer, Mike Spreitzer, Min Kim, Bruce Ma, Yu Liao, Mengyi Zhou!