Pod Priority
在Kubernetes集群环境中,可以设置Pod的优先级,优先级的高低代表Pod之间的重要性可以相互比较,如果一个Pod无法被调度器调度时,或者集群资源缺乏时,调度器会抢占与之优先级较低的Pod的资源
PriorityClass
在Kubernetes集群平台中,存在二个系统级别的PriorityClass(system-cluster-critical 和 system-node-critical)后者优先级在整个集群中最高级别
PriorityClass不受namespace所管,命名规则不能以system- 为前缀,优先级的值范围(10亿的32位整数)
PriorityClass 还有两个可选字段:globalDefault 和 description。 globalDefault 值为true功能是指当创建的Pod没有指定priorityClassName时会生成一个默认的Priority的值, 系统中只能存在一个 globalDefault 设置为 true 的 PriorityClass。 如果集群不存在globalDefault 的 PriorityClass, 则创建时Pod没有指定priorityClassName则Pod的优先级为0
Priority的注意事项
- 新增一个globaldefault设置为true的 PriorityClass 不会改变现有 Pod 的优先级,但是会影响之后合建的Pod优先级
- 如果删现有的PriorityClass时,并不影响已经生效的Pod的优先级,只是不能新建而已
- 具体参考配置,如下
apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: gloabletruepriority globalDefault: true value: 1 description: "globaldefaultpriority"
非抢占 PriorityClass
配置了 PreemptionPolicy: Never 的 Pod 不能抢占其他 Pod的资源(虽然会被放在优先等级低的Pod之前),直到Kubernetes集群中有足够的可用资源,调度器才会调度此类Pod。非抢占式 Pod也会受到调度器回退操作,意思就是当调度器无法调度时,会以更低的频率重复调度,取而代之的是比之优先等级低的Pod排在非抢占式前面
PreemptionPolicy 默认为 PreemptLowerPriority, 允许PriorityClass 的 Pod 可以抢占较低优先级的 Pod;但如果 PreemptionPolicy 设置为 Never,则该 PriorityClass 中的 Pod 将是非抢占式的
- 参考示例
apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority-nonpreempting value: 1000000 preemptionPolicy: Never globalDefault: false description: "This priority class will not cause other pods to be preempted."
Pod优先级配置
- 参考配置
apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent priorityClassName: high-priority
- Pod的优先对调度器的影响
当Pod启用优先级时,Kubernetes针对pending Pod进行排序,按优先级进行排序高在前低在后分级进行调度,如果高级别的优先级高度失败或由于其它原因无法调度时,则调度器依次执行调度队列中优先级别低的Pod
抢占
Pod创建后被列入到调度队列中,调度器从队列中应该依照优先级进行排序首先选择一个等级高的Pod进行调度到Kubernetes节点上,由于客观原因比如资源缺乏等,则触发 pending Pod 的抢占逻辑,调度器会删除一个或者多个低于pending Pod优先级的Pod并等待删除完成后,将其pending Pod调度到该节点上
抢占限制
- 被抢占的Pod优雅停止
当 Pod 被抢占时,Kubernetes会给予一个优雅停机宽限时间(terminationGracePeriodSeconds),如果没有宽限期那么直接kill掉
- 支持PDB,但不保证
PodDisruptionBudget (PDB) Kubernetes 在抢占 Pod 时支持 PDB,但对 PDB 的支持是基于尽力而为原则,调度器在Kubernetes集群尝删除优先等级低的Pod,如果并没有找到相关的Pod,则即使违反了 PDB 约束条件也会删除优先级较低的 Pod
- 与低优先级Pod之间的亲和性
如果从此节点上删除优先级低于pending Pod 的所有 Pod,pending Pod 是否可以在该节点上调度?答案是肯定的,如果不调度则就不会执行抢占
抢占并不一定会删除所有较低优先级的 Pod,清除pending Pod需要的资源即可,不需要清除所有低于pending Pod的优先级的Pod
如果pending Pod 与节点上的一个或多个较低优先级 Pod 具有 Pod 间亲和性, 但是在Kubernetes集群其它节点不满足低优先级Pod亲和性约束, 在这种情况下,调度器不会抢占节点上的任何 Pod;相反调度器可能会找到其它合适的节点, 也可能不会,无法保证pending Pod 可以被调度
- 跨节点抢占
- pending Pod执行调度至节点1
- Pod A 运行位于node1同区域的另一个节点2上
- pending Pod与Pod A 具有 Zone 维度的反亲和(topologyKey:topology.kubernetes.io/zone)
- pending Pod 与同zone中的其它Pod之间没有反亲和性设置
- 为了在节点1上调度 Pod P,可以抢占 PodA,但调度器不会进行跨节点抢占。 因此,pending Pod 将被视为在节点 1 上不可调度
常见故障
- Pod被抢占,但是没有被调度
在pending Pod等待被删除Pod后,恰好在这个时间节点出现一个更高优先级的 Pod 调度,在这种情况下,调度器将调度优先级更高的 Pod 而不是pending Pod
- 优先级高的Pod被优先级低的Pod前抢占
当有多个节点提供执行抢占,调度器会尝试选择具有一组优先级最低的 Pod 的节点,但是如果此类 Pod 具有 PodDisruptionBudget,当它们被抢占时, 则会违反 PodDisruptionBudget,那么调度器可能会选择另一个具有更高优先级 Pod 的节点
Pod优先级与Qos的相关关系
Pod 优先级和 QoS 是两个垂直特征,交互很少,并且对基于 QoS 设置 Pod 的优先级没有默认限制。 调度器的抢占逻辑在选择抢占目标时不考虑 QoS。 抢占会考虑 Pod 优先级并尝试选择一组优先级最低的目标。 仅当移除优先级最低的 Pod 不足以让调度器调度抢占式 Pod, 或者最低优先级的 Pod 受 PodDisruptionBudget 保护时,才会考虑优先级较高的 Pod
kubelet 使用优先级来确定节点压力驱逐 Pod 的顺序。 你可以使用 QoS评估Pod 最有可能被驱逐的顺序,kubelet 根据以下因素对 Pod 进行驱逐排名
- 对紧缺资源的使用是否超过requests
- Pod 优先级
- 相对于请求的资源使用量
当某 Pod 的资源用量未超过其请求时,kubelet 节点压力驱逐不会驱逐该 Pod。 如果优先级较低的 Pod 没有超过其请求,则不会被驱逐。 另一个优先级高于其请求的 Pod 可能会被驱逐
因此具体的驱逐顺序,如下
- 首先考虑 BestEffort 或 Burstable Pod资源使用量超过requests的值, 这些 Pod 会根据它们的优先级以及它们的资源使用级别超过其请求的程度被逐出
- 资源使用量少于请求量的 Guaranteed Pod 和 Burstable Pod 根据其优先级被最后驱逐
kubelet 不使用 Pod 的 QoS 来确定驱逐顺序。 在回收内存等资源时,你可以使用 QoS 评估最有可能的 Pod 驱逐顺序。 QoS 不适用于临时存储(EphemeralStorage)请求, 因此如果节点在 DiskPressure 下,则上述场景将不适用
- 当 kubelet 因 inode 或 PID 不足而驱逐 pod 时, 它使用优先级来确定驱逐顺序,因为 inode 和 PID 没有请求。
- kubelet 根据节点是否具有专用的 imagefs 文件系统对 Pod 进行不同的排序