作者:Min Kim(蚂蚁金服)、Mike Spreitzer(IBM)、Daniel Smith(谷歌)
这个博客描述了“API优先级和公平性(API Priority And Fairness)”,这是Kubernetes 1.18中一个新的alpha特性。API优先级和公平性允许集群管理员将控制平面的并发性划分为不同的加权优先级。到达kube-apiserver的每个请求将被归类到一个优先级,并获得其在控制平面的吞吐量中的公平份额。
这解决了什么问题?
今天,apiserver有一个简单的机制来保护自己不受CPU和内存过载的影响:对mutating和readonly请求的max-in-flight限制。除了mutating和readonly之间的区别外,请求之间没有其他区别;因此,可能会出现不希望出现的情况,其中一个请求子集会挤出其他请求。
简而言之,Kubernetes的工作负载很容易意外地使apiservers服务器崩溃,导致其他重要的流量(比如系统控制器或领导人选举)间歇性地失败。在最坏的情况下,一些损坏的节点或控制器可能将一个繁忙的集群推到崩溃边缘,将一个本地问题变成控制平面故障。
我们如何解决这个问题?
新的特性“API优先级和公平性”是关于在每个apiserver中泛化现有的max-in-flight请求处理程序,以使行为更加智能和可配置。总体方法如下。
- 每个请求都由一个流模式(Flow Schema)匹配。流模式声明与之匹配的请求的优先级,并为这些请求分配一个“流标识符(flow identifier)”。流标识符是系统如何确定请求是否来自相同的源。
- 可以将优先级配置为以多种方式运行。每个优先级都有自己的独立并发池。优先级还引入了对不能立即得到服务的请求进行排队的概念。
- 为了防止任何一个用户或命名空间独占一个优先级级别,可以将它们配置为具有多个队列。“洗牌分片(Shuffle Sharding)”用于将每个请求流分配给队列的一个子集。
- 最后,当有处理请求的能力时,使用“公平排队(Fair Queuing)”算法来选择下一个请求。在每个优先级内,队列以公平性进行竞争。
早期的结果非常有希望!看看这个分析。
https://github.com/kubernetes/kubernetes/pull/88177#issuecomment-588945806
我怎么试试这个?
你需要准备以下以尝试这特性:
- 下载并安装大于v1.18.0版本的kubectl
- 在kube-apiservers上使用命令行标志--runtime-config="flowcontrol.apiserver.k8s.io/v1alpha1=true"来启用新的API组
- 在kube-apiservers上使用命令行标志--feature-gates=APIPriorityAndFairness=true打开特性门
成功启动kube-apiservers之后,你将在集群中看到一些默认的FlowSchema和PriorityLevelConfiguration资源。这些默认配置是为集群的一般保护和流量管理而设计的。你可以通过运行常用的工具来检查和定制默认的配置,例如:
- kubectl get flowschemas
- kubectl get prioritylevelconfigurations
这是如何工作的?
在到达处理程序时,请求被精确地分配到一个优先级级和该优先级级中的一个流。因此,理解FlowSchema和PriorityLevelConfiguration如何工作将帮助你管理通过kube-apiserver的请求流量。
- FlowSchema:FlowSchema将识别PriorityLevelConfiguration对象和计算请求的“流标识符”的方法。目前,我们支持根据:发出请求的标识、谓词和目标对象来匹配请求。身份可以在以下方面匹配:用户名、用户组名或ServiceAccount。至于目标对象,我们可以通过apiGroup、resource[/subresource]和namespace进行匹配。
- 流标识符用于洗牌分片,因此,如果请求来自相同的源,那么它们必须具有相同的流标识符。我们喜欢考虑“大象”(发送很多/重请求)和“老鼠”(发送很少/轻请求)的场景:确保大象的请求都得到相同的流标识符是很重要的,否则它们在系统中看起来会像许多不同的老鼠!
- 参见这里的API文档!
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#flowschema-v1alpha1-flowcontrol-apiserver-k8s-io
- PriorityLevelConfiguration:定义一个优先级级别。
- 对于apiserver自身的请求,以及任何可重入(reentrant)的流量(例如,自己发出API请求的admission webhook),可以将优先级标记为“exempt(豁免)”,这意味着不进行任何类型的排队或限制。这是为了防止优先级反转(priority inversion)。
- 每个非豁免优先级都配置了许多“并发份额”,并获得一个要使用的独立并发池。该优先级级别的请求在池未满时在池中运行,而不是在其他任何地方。每个apiserver都配置了一个总并发限制(取mutating和readonly请求的旧限制的总和),然后按其并发份额的比例在各个优先级之间进行分配。
- 非豁免优先级可以选择多个队列来用于洗牌分片。以比一致哈希更好的方式将洗牌分片映射到队列。给定的流可以访问一个小的队列集合,对于每个传入的请求,都选择最短的队列。当优先级具有队列时,它还设置队列长度限制。请求在队列中可以等待的时间也有限制;这是apiserver请求超时的一个固定部分。无法执行且不能(再)排队的请求将被拒绝。
- 或者,非豁免优先级可以选择立即拒绝而不是在队列中等待。
- 有关此特性,请参阅API文档。
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#prioritylevelconfiguration-v1alpha1-flowcontrol-apiserver-k8s-io
有什么是缺失的?什么时候会有beta版?
我们已经在计划一些基于alpha的增强,随着用户向我们的社区发送反馈,将会有更多的增强。以下是他们的清单:
- 用于WATCH和EXEC请求的流量管理
- 调整和改进FlowSchema/PriorityLevelConfiguration的默认设置
- 增强此特性如何工作的可观察性
- 请加入讨论
https://github.com/kubernetes/enhancements/pull/1632
根据对影响大小的估计,可能会对LIST请求进行不同的处理。