优先级和抢占机制,解决的是 Pod 调度失败时该怎么办的问题。
正常情况下,当一个 Pod 调度失败后,它就会被暂时“搁置”起来,直到 Pod 被更新,或者集群状态发生变化,调度器才会对这个 Pod 进行重新调度。
当一个高优先级的 Pod 调度失败后,该 Pod 并不会被“搁置”,而是会“挤走”某个 Node 上的一些低优先级的 Pod 。这样就可以保证这个高优先级 Pod 的调度成功
优先级
提高集群的资源利用率最常见的做法就是采用优先级的方案。
通过给 Pod 设置高优先级,让其比其他 Pod 显得更为重要,通过这种“插队”的方式优先获得调度器的调度
PriorityClass
Kubernetes 在初始化的时候就自带了两个 PriorityClasses
1 | [root@k8s01 ~]# kubectl get priorityclass |
这是两个公共的优先级类,主要用来确保 Kubernetes 系统的关键组件或者关键插件总是能够优先被调度,比如 coredns 等。
我们在定义这样一个 PriorityClass 对象的时候,名字不可以包含 system- 这个前缀。且不能高于这里的 HighestUserDefinablePriority 的, 即 1000000000 (10 亿)。1
2
3
4// HighestUserDefinablePriority is the highest priority for user defined priority classes. Priority values larger than 1 billion are reserved for Kubernetes system use.
HighestUserDefinablePriority = int32(1000000000)
// SystemCriticalPriority is the beginning of the range of priority values for critical system components.
SystemCriticalPriority = 2 * HighestUserDefinablePriority
自定义PriorityClass
high-priority.yaml1
2
3
4
5
6
7apiVersion: scheduling.k8s.io/v1 # 使用的 API 版本是 scheduling.k8s.io/v1。这个对象是个集群级别的定义,并不属于任何 namespace,可以被全局使用
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false # 是否将该 PriorityClass 的数值作为默认值,并将其应用在所有未设置 priorityClassName 的 Pod 上(新增 Pod ,之前的存量pod优先级默认为 0). 整个 Kubernetes 集群中只能存在一个 globalDefault 设为 true 的 PriorityClass 对象。
description: "This priority class should be used for XYZ service pods only."
low-priority.yaml1
2
3
4
5
6apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low-priority
value: 1000
globalDefault: false
应用这两个优先级
1 | [root@k8s01 ~]# kubectl apply -f low-priority.yaml |
nginx-low-priority.yaml
1 | apiVersion: v1 |
nginx-high-priority.yaml
1 | apiVersion: v1 |
应用上面两个 pod
1 | [root@k8s01 ~]# cat /proc/cpuinfo | grep 'model name' | wc -l |
非抢占式
并不希望 Pod 被驱逐掉,只是希望可以优先调度
preemptionPolicy.yaml1
2
3
4
5
6
7
8apiVersion: 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."
kube-scheduler 的抢占能力是通过 disablePreemption 这个参数来控制的,该标志默认为 false ( 不建议使用)
1 | apiVersion: kubescheduler.config.k8s.io/v1alpha1 |
集群管理员可以为特定用户创建特定优先级级别,来防止他们恶意使用高优先级的 PriorityClass。
补
当 Pod 里的每一个 Container 都同时设置了 requests 和 limits,并且 requests 和 limits 值相等的时候(或者只有 limits ),这个 Pod 就属于 Guaranteed 类别
Pod 不满足 Guaranteed 的条件,但至少有一个 Container 设置了 requests。那么这个 Pod 就会被划分到 Burstable 类别
Pod 既没有设置 requests,也没有设置 limits,那么它的 QoS 类别就是 BestEffort
QoS 划分的主要应用场景,是当宿主机资源紧张的时候,kubelet 对 Pod 进行 Eviction(即资源回收)时需要用到的。
默认值1
2
3
4memory.available<100Mi
nodefs.available<10%
nodefs.inodesFree<5%
imagefs.available<15%
可自行配置1
kubelet --eviction-hard=imagefs.available<10%,memory.available<500Mi,nodefs.available<5%,nodefs.inodesFree<5% --eviction-soft=imagefs.available<30%,nodefs.available<10% --eviction-soft-grace-period=imagefs.available=2m,nodefs.available=2m --eviction-max-pod-grace-period=600
建议将 DaemonSet 的 Pod 都设置为 Guaranteed 的 QoS 类型。否则,一旦 DaemonSet 的 Pod 被回收,它又会立即在原宿主机上被重建出来,这就使得前面资源回收的动作,完全没有意义了