首页 > 解决方案 > Kubernetes 挂起的 pod 优先级

问题描述

我的 kubernetes (1.18.3) 集群上有以下 pod:

NAME      READY   STATUS    RESTARTS   AGE
pod1      1/1     Running   0          14m
pod2      1/1     Running   0          14m
pod3      0/1     Pending   0          14m
pod4      0/1     Pending   0          14m

pod3 和 pod4 无法启动,因为该节点只能容纳 2 个 pod。当 pod1 完成并退出时,调度程序会选择 pod3 或 pod4 并启动它。到目前为止,一切都很好。

但是,我也有一个高优先级的 pod (hpod),我想在 pod3 或 pod4 之前启动,当其中一个正在运行的 pod 完成并退出时。

所以我创建了一个priorityclass,可以在kubernetes docs中找到:

kind: PriorityClass
metadata:
  name: high-priority-no-preemption
value: 1000000
preemptionPolicy: Never
globalDefault: false
description: "This priority class should be used for XYZ service pods only."

我创建了以下 pod yaml:

apiVersion: v1
kind: Pod
metadata:
  name: hpod
  labels:
    app: hpod
spec:
  containers:
  - name: hpod
    image: ...
    resources:
      requests:
        cpu: "500m"
        memory: "500Mi"
      limits:
        cpu: "500m"
        memory: "500Mi"
  priorityClassName: high-priority-no-preemption

现在的问题是,当我使用 kubectl apply -f hpod.yaml 启动高优先级 pod 时,调度程序会终止正在运行的 pod 以允许高优先级 pod 启动,尽管我设置了“preemptionPolicy:Never”。

预期的行为是推迟启动 hpod 直到当前运行的 pod 完成。当它发生时,让 hpod 在 pod3 或 pod4 之前启动。

我究竟做错了什么?

标签: kubernetespreemption

解决方案


先决条件:

该解决方案在 Kubernetes v1.18.3、docker 19.03 和 Ubuntu 18 上进行了测试。还需要文本编辑器(即sudo apt-get install vim)。

如何禁用抢占下的 Kubernetes 文档中,您可以找到注意

注意:在 Kubernetes1.15及更高版本中,如果特性NonPreemptingPriorityenabledPriorityClasses则可以选择设置preemptionPolicy: Never。这将防止该 podPriorityClass抢占其他 pod。

同样在Non-preempting PriorityClass下,您还有以下信息:

PreemptionPolicy 字段的使用要求NonPreemptingPriority特征门是enabled.

稍后,如果您检查那些Feature Gates信息,您会发现它NonPreemptingPriorityfalse,因此默认情况下它是禁用的。

使用当前配置输出:

$ kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
nginx-normal     1/1     Running   0          32s
nginx-normal-2   1/1     Running   0          32s
$ kubectl apply -f prio.yaml
pod/nginx-priority created$ kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
nginx-normal-2   1/1     Running   0          48s
nginx-priority   1/1     Running   0          8s

要启用preemptionPolicy: Never您需要申请--feature-gates=NonPreemptingPriority=true3 个文件:

/etc/kubernetes/manifests/kube-apiserver.yaml

/etc/kubernetes/manifests/kube-controller-manager.yaml

/etc/kubernetes/manifests/kube-scheduler.yaml

要检查这feature-gate是否启用,您可以使用以下命令进行检查:

ps aux | grep apiserver | grep feature-gates
ps aux | grep scheduler | grep feature-gates
ps aux | grep controller-manager | grep feature-gates

有关非常详细的信息,为什么你必须编辑这些文件,请查看这个 Github 线程

$ sudo su
# cd /etc/kubernetes/manifests/
# ls
etcd.yaml  kube-apiserver.yaml  kube-controller-manager.yaml  kube-scheduler.yaml

使用您的文本编辑器将功能门添加到这些文件

# vi kube-apiserver.yaml

并在- --feature-gates=NonPreemptingPriority=true下面spec.containers.command的示例中添加:

spec:
  containers:
  - command:
    - kube-apiserver
    - --feature-gates=NonPreemptingPriority=true
    - --advertise-address=10.154.0.31

并对其他 2 个文件执行相同操作。之后,您可以检查是否应用了此标志。

$ ps aux | grep apiserver | grep feature-gates
root     26713 10.4  5.2 565416 402252 ?       Ssl  14:50   0:17 kube-apiserver --feature-gates=NonPreemptingPriority=true --advertise-address=10.154.0.31 

现在您已经重新部署了PriorityClass.

$ kubectl get priorityclass
NAME                          VALUE        GLOBAL-DEFAULT   AGE
high-priority-no-preemption   1000000      false            12m
system-cluster-critical       2000000000   false            23m
system-node-critical          2000001000   false            23m
$ kubectl delete priorityclass high-priority-no-preemption
priorityclass.scheduling.k8s.io "high-priority-no-preemption" deleted
$ kubectl apply -f class.yaml 
priorityclass.scheduling.k8s.io/high-priority-no-preemption created

最后一步是使用这个部署 pod PriorityClass

测试

$ kubectl get po
NAME             READY   STATUS    RESTARTS   AGE
nginx-normal     1/1     Running   0          4m4s
nginx-normal-2   1/1     Running   0          18m
$ kubectl apply -f prio.yaml 
pod/nginx-priority created
$ kubectl get po
NAME             READY   STATUS    RESTARTS   AGE
nginx-normal     1/1     Running   0          5m17s
nginx-normal-2   1/1     Running   0          20m
nginx-priority   0/1     Pending   0          67s
$ kubectl delete po nginx-normal-2
pod "nginx-normal-2" deleted
$ kubectl get po
NAME             READY   STATUS    RESTARTS   AGE
nginx-normal     1/1     Running   0          5m55s
nginx-priority   1/1     Running   0          105s

推荐阅读