优先级与抢占式调度

当集群资源(CPU、磁盘、内存等)不足时,如果用户提交了新Pod的创建请求,则这个Pod会一直处于Pending状态,直到某个节点有足够的资源才会调度成功。默认情况下,除了系统级Pod之外,所有Pod的优先级都是相同的。

在这种情况下,如果调高Pod的优先级,调度器在调度时会选择最合适的节点,将节点上低优先级的Pod驱逐并释放,以腾出空间给高优先级的Pod使用。这种调度方式称为抢占式(preemption)调度。

在使用抢占式调度前,需要先创建PriorityClass,设置资源优先级,后续在创建控制器或Pod时可以引用这个优先级。

创建examplehighpriority.yml文件

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: examplehighpriority
value: 1000000
globalDefault: false
description: "This priority class should be used for importent service pods only."

该模板定义了PriorityClass,value属性表示优先级,值越大代表优先级越高,本例中为1000000。如果Pod没有引用PriorityClass,默认优先级为0。

globalDefault表示是否将其定义为全局性PriorityClass,所有未明确指定PriorityClass的Pod都会使用该优先级作为默认优先级。

注意,只能有一个PriorityClass的globalDefault字段为true,在本例中我们设置为false。description表示关于PriorityClass的一段自定义的说明。

接下来,执行以下命令,创建PriorityClass。

$ kubectl apply -f examplehighpriority.yml

接下来,通过以下命令,可以查看已经创建的PriorityClass。

$ kubectl get priorityclass
NAME                      VALUE        GLOBAL-DEFAULT   AGE
examplehighpriority       1000000      false            5s
system-cluster-critical   2000000000   false            175d
system-node-critical      2000001000   false            175d

查询结果如下图所示,除本例中创建的 examplehighpriority 外,还有两个前缀为“system-”的PriorityClass。这是Kubernetes在安装时自动创建的系统级Pod的PriorityClass,可以看到这两个应用的优先级都设置为非常高的数值。

PriorityClass创建后,就可以创建引用它的Pod了。通过spec.priorityClassName属性指定要引用的PriorityClass,具体模板的定义如 下所示。

该Pod将具有先前PriorityClass示例中定义的优先级(1000000)。

apiVersion: v1
kind: Pod
metadata:
  name: exampleforpriority
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    priorityClassName: examplehighpriority

注意:请慎用该功能。通过设置Pod优先级进行抢占式调度是一种不公平行为,在资源紧缺时,这会增加维护复杂度,带来不稳定因素。如果资源不足,首先应该考虑的是扩容。优先级设置应该仅用于最重要的少部分Pod,如果经常使用,可能会有用户恶意调高Pod优先级,导致普通用户在资源紧缺时无法调度Pod。