Kubernetes-树叶云kubernetes教程-Pod优先级和抢占 (kubernetes)

教程大全 2025-07-17 12:43:44 浏览

Pod优先级和抢占

FEATURESTATE:KuberNetesv1.14[stable]

Pod可以有优先级。优先级表示一个Pod相对于其他Pod的重要性。如果一个Pod无法被调度,调度程序会尝试抢占(驱逐)较低优先级的Pod,以使悬决Pod可以被调度。

如何使用优先级和抢占

要使用优先级和抢占:

PriorityClass

PriorityClass是一个无名称空间对象,它定义了从优先级类名称到优先级整数值的映射。名称在PriorityClass对象元数据的​​字段中指定。值在必填的​​字段中指定。值越大,优先级越高。PriorityClass对象的名称必须是有效的DNS子域名,并且它不能以​​为前缀。

PriorityClass对象可以设置任何小于或等于10亿的32位整数值。较大的数字是为通常不应被抢占或驱逐的关键的系统Pod所保留的。集群管理员应该为这类映射分别创建独立的PriorityClass对象。

PriorityClass还有两个可选字段:​ gLOBalDefault ​和​ description ​。​ globalDefault ​字段表示这个PriorityClass的值应该用于没有​ priorityClassName ​的Pod。系统中只能存在一个​ globalDefault ​设置为true的PriorityClass。如果不存在设置了​ globalDefault ​的PriorityClass,则没有​ priorityClassName ​的Pod的优先级为零。

description ​字段是一个任意字符串。它用来告诉集群用户何时应该使用此PriorityClass。

关于PodPriority和现有集群的注意事项

PriorityClass示例

apiVersion: scheduling.k8s.io/v1kind: PriorityClassmetadata:name: high-priorityvalue: 1000000globalDefault: falsedescription: "此优先级类应仅用于 XYZ 服务 Pod。"

非抢占式PriorityClass

FEATURESTATE:Kubernetesv1.24[stable]

配置了​ preemptionPolicy:Never ​的Pod将被放置在调度队列中较低优先级Pod之前,但它们不能抢占其他Pod。等待调度的非抢占式Pod将留在调度队列中,直到有足够的可用资源,它才可以被调度。非抢占式Pod,像其他Pod一样,受调度程序回退的影响。这意味着如果调度程序尝试这些Pod并且无法调度它们,它们将以更低的频率被重试,从而允许其他优先级较低的Pod排在它们之前。

非抢占式Pod仍可能被其他高优先级Pod抢占。

preemptionPolicy ​默认为​ PreemptLowerPriority ​,这将允许该PriorityClass的Pod抢占较低优先级的Pod(现有默认行为也是如此)。如果​ preemptionPolicy ​设置为​​,则该PriorityClass中的Pod将是非抢占式的。

数据科学工作负载是一个示例用例。用户可以提交他们希望优先于其他工作负载的作业,但不希望因为抢占运行中的Pod而导致现有工作被丢弃。设置为​ preemptionPolicy:Never ​的高优先级作业将在其他排队的Pod之前被调度,只要足够的集群资源“自然地”变得可用。

非抢占式PriorityClass示例

apiVersion: scheduling.k8s.io/v1kind: PriorityClassmetadata:name: high-priority-nonpreemptingvalue: 1000000preemptionPolicy: NeverglobalDefault: falsedescription: "This priority class will not cause other pods to be preempted."

Pod优先级

在你拥有一个或多个PriorityClass对象之后,你可以创建在其规约中指定这些PriorityClass名称之一的Pod。优先级准入控制器使用​ priorityClassName ​字段并填充优先级的整数值。如果未找到所指定的优先级类,则拒绝Pod。

以下YAML是Pod配置的示例,它使用在前面的示例中创建的PriorityClass。优先级准入控制器检查Pod规约并将其优先级解析为1000000。

apiVersion: v1kind: Podmetadata:name: nginxlabels:env: testspec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentpriorityClassName: high-priority

Pod优先级对调度顺序的影响

当启用Pod优先级时,调度程序会按优先级对悬决Pod进行排序,并且每个悬决的Pod会被放置在调度队列中其他优先级较低的悬决Pod之前。因此,如果满足调度要求,较高优先级的Pod可能会比具有较低优先级的Pod更早调度。如果无法调度此类Pod,调度程序将继续并尝试调度其他较低优先级的Pod。

抢占

Pod被创建后会进入队列等待调度。调度器从队列中挑选一个Pod并尝试将它调度到某个节点上。如果没有找到满足Pod的所指定的所有要求的节点,则触发对悬决Pod的抢占逻辑。让我们将悬决Pod称为P。抢占逻辑试图找到一个节点,在该节点中删除一个或多个优先级低于P的Pod,则可以将P调度到该节点上。如果找到这样的节点,一个或多个优先级较低的Pod会被从节点中驱逐。被驱逐的Pod消失后,P可以被调度到该节点上。

用户暴露的信息

当PodP抢占节点N上的一个或多个Pod时,PodP状态的​ nominatednodeName ​字段被设置为节点N的名称。该字段帮助调度程序跟踪为PodP保留的资源,并为用户提供有关其集群中抢占的信息。

请注意,PodP不一定会调度到“被提名的节点(NominatedNode)”。调度程序总是在迭代任何其他节点之前尝试“指定节点”。在Pod因抢占而牺牲时,它们将获得体面终止期。如果调度程序正在等待牺牲者Pod终止时另一个节点变得可用,则调度程序可以使用另一个节点来调度PodP。因此,Pod规约中的​ nominatedNodeName ​和​​并不总是相同。此外,如果调度程序抢占节点N上的Pod,但随后比PodP更高优先级的Pod到达,则调度程序可能会将节点N分配给新的更高优先级的Pod。在这种情况下,调度程序会清除PodP的​ nominatedNodeName ​。通过这样做,调度程序使PodP有资格抢占另一个节点上的Pod。

抢占的限制

被抢占牺牲者的体面终止

当Pod被抢占时,牺牲者会得到他们的体面终止期。它们可以在体面终止期内完成工作并退出。如果它们不这样做就会被杀死。这个体面终止期在调度程序抢占Pod的时间点和待处理的Pod(P)可以在节点(N)上调度的时间点之间划分出了一个时间跨度。同时,调度器会继续调度其他待处理的Pod。当牺牲者退出或被终止时,调度程序会尝试在待处理队列中调度Pod。因此,调度器抢占牺牲者的时间点与PodP被调度的时间点之间通常存在时间间隔。为了最小化这个差距,可以将低优先级Pod的体面终止时间设置为零或一个小数字。

支持PodDisruptionBudget,但不保证

PodDisruptionBudget(PDB)允许多副本应用程序的所有者限制因自愿性质的干扰而同时终止的Pod数量。Kubernetes在抢占Pod时支持PDB,但对PDB的支持是基于尽力而为原则的。调度器会尝试寻找不会因被抢占而违反PDB的牺牲者,但如果没有找到这样的牺牲者,抢占仍然会发生,并且即使违反了PDB约束也会删除优先级较低的Pod。

与低优先级Pod之间的Pod间亲和性

只有当这个问题的答案是肯定的时,才考虑在一个节点上执行抢占操作:“如果从此节点上删除优先级低于悬决Pod的所有Pod,悬决Pod是否可以在该节点上调度?”

如果悬决Pod与节点上的一个或多个较低优先级Pod具有Pod间亲和性,则在没有这些较低优先级Pod的情况下,无法满足Pod间亲和性规则。在这种情况下,调度程序不会抢占节点上的任何Pod。相反,它寻找另一个节点。调度程序可能会找到合适的节点,也可能不会。无法保证悬决Pod可以被调度。

我们针对此问题推荐的解决方案是仅针对同等或更高优先级的Pod设置Pod间亲和性。

跨节点抢占

假设正在考虑在一个节点N上执行抢占,以便可以在N上调度待处理的PodP。只有当另一个节点上的Pod被抢占时,P才可能在N上变得可行。下面是一个例子:

如果将PodQ从所在节点中移除,则不会违反Pod间反亲和性约束,并且PodP可能会被调度到节点N上。

如果有足够的需求,并且如果我们找到性能合理的算法,我们可能会考虑在未来版本中添加跨节点抢占。

故障排除

Pod优先级和抢占可能会产生不必要的副作用。以下是一些潜在问题的示例以及处理这些问题的方法。

Pod被不必要地抢占

抢占在资源压​​力较大时从集群中删除现有Pod,为更高优先级的悬决Pod腾出空间。如果你错误地为某些Pod设置了高优先级,这些无意的高优先级Pod可能会导致集群中出现抢占行为。Pod优先级是通过设置Pod规约中的​ priorityClassName ​字段来指定的。优先级的整数值然后被解析并填充到​​的​​字段。

为了解决这个问题,你可以将这些Pod的​ priorityClassName ​更改为使用较低优先级的类,或者将该字段留空。默认情况下,空的​ priorityClassName ​解析为零。

当Pod被抢占时,集群会为被抢占的Pod记录事件。只有当集群没有足够的资源用于Pod时,才会发生抢占。在这种情况下,只有当悬决Pod(抢占者)的优先级高于受害Pod时才会发生抢占。当没有悬决Pod,或者悬决Pod的优先级等于或低于牺牲者时,不得发生抢占。如果在这种情况下发生抢占,请提出问题。

有Pod被抢占,但抢占者并没有被调度

当Pod被抢占时,它们会收到请求的体面终止期,默认为30秒。如果受害Pod在此期限内没有终止,它们将被强制终止。一旦所有牺牲者都离开,就可以调度抢占者Pod。

在抢占者Pod等待牺牲者离开的同时,可能某个适合同一个节点的更高优先级的Pod被创建。在这种情况下,调度器将调度优先级更高的Pod而不是抢占者。

这是预期的行为:具有较高优先级的Pod应该取代具有较低优先级的Pod。

Pod优先级和抢占

优先级较高的Pod在优先级较低的Pod之前被抢占

调度程序尝试查找可以运行悬决Pod的节点。如果没有找到这样的节点,调度程序会尝试从任意节点中删除优先级较低的Pod,以便为悬决Pod腾出空间。如果具有低优先级Pod的节点无法运行悬决Pod,调度器可能会选择另一个具有更高优先级Pod的节点(与其他节点上的Pod相比)进行抢占。牺牲者的优先级必须仍然低于抢占者Pod。

当有多个节点可供执行抢占操作时,调度器会尝试选择具有一组优先级最低的Pod的节点。但是,如果此类Pod具有PodDisruptionBudget,当它们被抢占时,则会违反PodDisruptionBudget,那么调度程序可能会选择另一个具有更高优先级Pod的节点。

当存在多个节点抢占且上述场景均不适用时,调度器会选择优先级最低的节点。

Pod优先级和服务质量之间的相互作用

Pod优先级和QoS类是两个正交特征,交互很少,并且对基于QoS类设置Pod的优先级没有默认限制。调度器的抢占逻辑在选择抢占目标时不考虑QoS。抢占会考虑Pod优先级并尝试选择一组优先级最低的目标。仅当移除优先级最低的Pod不足以让调度程序调度抢占式Pod,或者最低优先级的Pod受PodDisruptionBudget保护时,才会考虑优先级较高的Pod。

kubelet使用优先级来确定节点压力驱逐Pod的顺序。你可以使用QoS类来估计Pod最有可能被驱逐的顺序。kubelet根据以下因素对Pod进行驱逐排名:

当某Pod的资源用量未超过其请求时,kubelet节点压力驱逐不会驱逐该Pod。如果优先级较低的Pod没有超过其请求,则不会被驱逐。另一个优先级高于其请求的Pod可能会被驱逐。

本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐