Kubernetes 1.8+ 版本中可以指定 Pod 的优先级。优先级指示一个 Pod 相对于其它 Pod 的重要性。当 Pod 无法被调度时,scheduler 会尝试抢占(驱逐)低优先级的 Pod,使得这些 Pending pod 可以被调度
调度节点的时候可以给 pod 指定 Priority,让 pod 有不同的优先级,这样在 scheduler 调度 pod 的时候会优先调度优先级高的 pod
如果发生资源不够的时候会触发抢占式调度(解决的是高优先级 Pod 调度失败时怎么办的问题)
- 在>=1.11版本中默认开启,并且在1.14中变成stable.
- 在<1.11版本需要给kube-scheduler指定--feature-gates=PodPriority=true来开启
PriorityClass
PriorityClass 是不受命名空间约束的对象,定义了优先级类名跟优先级整数值的映射。名称通过 PriorityClass 对象 metadata 中的 name 字段指定。值在必选的 value 字段中指定。值越大,优先级越高。
PriorityClass 对象的值可以是小于或者等于 10 亿的 32 位任意整数值。更大的数值被保留给那些通常不应该取代或者驱逐的关键的系统级 Pod 使用。集群管理员应该为它们想要的每个此类映射创建一个 PriorityClass 对象
PriorityClass 还有两个可选的字段:globalDefault 和 description。globalDefault 表示 PriorityClass 的值应该给那些没有设置 PriorityClassName 的 Pod 使用。整个系统只能存在一个 globalDefault 设置为 true 的 PriorityClass。如果没有任何 globalDefault 为 true 的 PriorityClass 存在,那么,那些没有设置 PriorityClassName 的 Pod 的优先级将为 0。
description 字段的值可以是任意的字符串。
apiVersion: scheduling.k8s.io/v1
description: This priority class should only be used by the pods installed using kubespray.
kind: PriorityClass
metadata:
name: k8s-cluster-critical
value: 1000000000
globalDefault: false
Pod priority
优先级准入控制器通过 priorityClassName 字段查找优先级数值并且填入 Pod 中。如果没有找到相应的 PriorityClass,Pod 将会被拒绝创建。
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
priorityClassName: k8s-cluster-critical
Pod 生成后,会进入一个队列等待调度。scheduler 从队列中选择一个 Pod,然后尝试将其调度到某个节点上。如果没有任何节点能够满足 Pod 指定的所有要求,对于这个挂起的 Pod,抢占逻辑就会被触发。当前假设我们把挂起的 Pod 称之为 P。抢占逻辑会尝试查找一个节点,在该节点上移除一个或多个比 P 优先级低的 Pod 后, P 能够调度到这个节点上。如果节点找到了,部分优先级低的 Pod 就会从该节点删除。Pod 消失后,P 就能被调度到这个节点上了。
代码实现
PriorityQueue实现一个调度队列。 PriorityQueue的头是优先级最高的挂起Pod。 此结构具有三个子队列。
- activeQ: 该子队列包含正在进行调度的Pod。 数据结构实现为堆
- unschedulableQ: 该队列包含已尝试并且确定为不可调度的Pod
- podBackoffQ: 该队列包含从无法调度的队列移出的Pod,并在退避完成后将其移到活动队列
type PriorityQueue struct {
// PodNominator abstracts the operations to maintain nominated Pods.
framework.PodNominator
// activeQ is heap structure that scheduler actively looks at to find pods to
// schedule. Head of heap is the highest priority pod.
activeQ *heap.Heap
// podBackoffQ is a heap ordered by backoff expiry. Pods which have completed backoff
// are popped from this heap before the scheduler looks at activeQ
podBackoffQ *heap.Heap
// unschedulableQ holds pods that have been tried and determined unschedulable.
unschedulableQ *UnschedulablePodsMap
}