Pod可以具有优先级。优先级表示Pod相对于其他Pod的重要性。如果无法调度Pod,则调度程序会尝试抢占(逐出)较低优先级的Pod,以便可以调度待处理的Pod。

@[TOC]

在Kubernetes 1.9及更高版本中,优先级(Priority)还会影响Pod的调度顺序和节点上的资源抢占驱逐。

自Kubernetes 1.11以来,Pod优先级和抢占已移至beta版,并且在此版本及更高版本中默认启用。

在Kubernetes版本中,Pod优先级和抢占仍然是alpha级别的功能,您需要明确启用它。要在旧版本的Kubernetes中使用这些功能,请按照Kubernetes版本的文档中的说明进行操作,方法是转到Kubernetes版本的文档存档版本。

如何使用优先级和抢占

要在Kubernetes 1.11及更高版本中使用优先级和抢占,请按照下列步骤操作:

添加一个或多个PriorityClasses

创建Pod,添加priorityClassName并将其设置为添加的PriorityClasses之一。当然,您不需要直接创建Pod; 通常,您将添加priorityClassName到集合对象的Pod模板,如Deployment

如果您尝试该功能然后决定禁用它,则必须删除PodPriority命令行标志或将其设置为false,然后重新启动API服务器和调度程序。禁用此功能后,现有Pod将保留其优先级字段,但禁用抢占,并忽略优先级字段。如果禁用该功能,则priorityClassName无法在新Pod中设置。

如何禁用抢占

注意:在Kubernetes 1.11中,关键的容器(DaemonSet容器除外,它们仍由DaemonSet控制器调度)依赖于在群集处于资源压力下时调度程序抢占。因此,如果您决定禁用抢占,则需要运行旧版本的Rescheduler。下面提供了更多相关信息。

在Kubernetes 1.11及更高版本中,抢占机制由kube-scheduler标志控制disablePreemption,该标志默认设置为false

此选项仅在组件配置中可用,并且在旧式命令行选项中不可用。以下是禁用抢占的示例组件配置:

1
2
3
4
5
6
7
8
apiVersion: componentconfig/v1alpha1
kind: KubeSchedulerConfiguration
algorithmSource:
provider: DefaultProvider

...

disablePreemption: true

PriorityClass 介绍

PriorityClass是一个非命名空间的对象,它定义从优先级类名到优先级的整数值的映射。该名称namePriorityClass对象的元数据字段中指定。该值在必填value字段中指定。==值越高,优先级越高。==

PriorityClass对象可以具有小于或等于10亿的任何32位整数值。较大的数字保留给通常不会被抢占或驱逐的关键系统Pod。集群管理员应为他们想要的每个这样的映射创建一个PriorityClass对象。

PriorityClass还有两个可选字段:globalDefaultdescription。该globalDefault字段表示此PriorityClass的值应该用于没有 priorityClassNamePod。系统中只能存在一个globalDefault设置为truePriorityClass 。如果没有globalDefault设置的PriorityClass ,则具有noPod的优先级 priorityClassName为零。

description字段是任意字符串。它旨在告诉用户何时应该使用此PriorityClass

有关PodPriority和现有集群的说明

  • 如果升级现有群集并启用此功能,则现有Pod的优先级实际上为零。

  • 添加globalDefault设置为的PriorityClass true不会更改现有Pod的优先级。此类PriorityClass的值仅用于添加PriorityClass后创建的Pod

  • 如果删除PriorityClass,则使用已删除的PriorityClass名称的现有Pod保持不变,但您无法创建使用已删除的PriorityClass名称的Pod

示例PriorityClass

1
2
3
4
5
6
7
apiVersion: scheduling.k8s.io/v1beta1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for XYZ service pods only."

Pod优先级配置

拥有一个或多个PriorityClasses之后,您可以创建在其规范中指定其中一个PriorityClass名称的Pod。优先级许可控制器使用该priorityClassName字段并填充优先级的整数值。如果未找到PriorityClasses,则拒绝创建Pod

以下YAML是使用在前面的示例中创建的PriorityClassPod配置的示例。优先级许可控制器检查规范并将Pod的优先级解析为1000000

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
priorityClassName: high-priority

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

在Kubernetes 1.9及更高版本中,当启用Pod优先级时,调度程序按其优先级对挂起的Pod进行排序,并将挂起的Pod置于调度队列中优先级较低的其他挂起的Pod之前。因此,如果满足其调度要求,则可以比具有较低优先级的Pod更早地调度更高优先级的Pod。如果无法安排此类Pod,则调度程序将继续并尝试安排其他较低优先级的Pod。

抢占

创建Pod时,它们会进入队列并等待安排。调度程序从队列中选择一个Pod并尝试在节点上安排它。如果未找到满足Pod的所有指定要求的节点,则会为挂起的Pod触发抢占逻辑。假设待处理的Pod为 P,抢占逻辑尝试找到一个节点,其中删除一个或多个优先级低于P的Pod将使得能够在该节点上调度P. 如果找到这样的节点,则从节点中删除一个或多个较低优先级的Pod。在Pod消失后,可以在节点上安排P.

用户暴露的信息

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

请注意,Pod P不一定安排到“指定节点”。在受害者Pod被抢先后,他们将获得优雅的终止期。如果在调度正在等待受害的pod终止而另一个节点可用时,调度程序将使用其它节点来安排Pod P.结果 nominatedNodeNamenodeName Pod规范的并不总是相同的。此外,如果调度程序在节点N上抢占Pod,但是然后比Pod P更高优先级的Pod到达,则调度程序可以将节点N提供给新的更高优先级Pod。在这种情况下,调度程序清除nominatedNodeNamePod P.通过执行此操作,调度程序使Pod P有资格抢占另一个节点上的Pod。

Pod优先级和QoS的交互

Pod优先级和 QoS 是两个正交特征,几乎没有交互,也没有基于其QoS类设置Pod优先级的默认限制。调度程序的抢占逻辑在选择抢占目标时会考虑QoS。Preemption考虑Pod优先级并尝试选择具有最低优先级的一组目标。只有在删除最低优先级Pod不足以允许调度程序调度preemptor Pod或者最低优先级Pod受到保护时,才会考虑优先级较高的Pod进行抢占 PodDisruptionBudget。

考虑QoS和Pod优先级的唯一组件是 Kubelet资源外驱逐。kubelet首先根据他们对饥饿资源的使用是否超过请求,然后按优先级,然后通过消耗饥饿计算资源相对于Pods的调度请求来排除Pods。Kubelet资源外驱逐不会驱逐使用不超过其请求的Pod。如果优先级较低的Pod未超过其请求,则不会被驱逐。另一个优先级高于其请求的Pod可能被驱逐。

参考

  1. https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/