Author: xidianwangtao@gmail.comnode
什么是抢占式调度?
在Kubernetes 1.8版本以前,当集群资源不足时,用户提交新的Pod建立请求后,该Pod会处于Pending状态,直到集群中有某个Node有足够Available Resources时才会调度成功。 从Kubernetes 1.8版本开始,这种状况下scheduler会根据Pod's Priority进行调度,调度时会选择最合适的Node并把该Node上lower Priority的Pods进行Premmption(Eviction)以释放资源供该higher Priority Pod使用。这种调度时考虑Pod Priority的方式就是Kubernetes中的抢占式调度,简称为Preemption。nginx
在后续的版本中,Pod Priority还会用于节点的out-of-resource Eviction,关于kubelet eviction的工做机制和源码分析,请参考个人对应博客:api
在Kubernetes 1.8中,Pod Priority和Preemption做为Alpha特性,默认是disable的,若是你要使用该特性,须要给apiserver和scheduler添加以下参数并重启:源码分析
反过来,把上面的参数删除并重启,便可disable。spa
有个问题:若是我开启了这个特性,而且建立了一些PriorityClass,而后还给某些Pod使用了,这个时候我再disable掉这个特性,会不会有问题?.net
答案是否认的!disable后,那些以前设置的Pod Priority field还会继续存在,可是并没什么用处了,Preemption是关闭的。固然,你也不能给新的Pods引用PriorityClass了。code
Enable后,接下来就是建立PriorityClass了:server
apiVersion: scheduling.k8s.io/v1alpha1 kind: PriorityClass metadata: name: high-priority value: 1000000 globalDefault: false description: "This priority class should be used for XYZ service pods only."
注意:PriorityClass是非namespace隔离的,是global的。所以metadata下面是不能设置namespace field的。blog
注意:ip
PriorityClass只会影响那些还没建立的Pod,一旦Pod建立完成,那么admission Controller就已经将Pod Spec中应用的PriorityClassName对应的PriorityClass的value设置到Pod的Priority field了。意味着你再修改PriorityClass的任何field,包括globalDefault,也不会影响已经建立完成的Pod。
若是你删除某个PriorityClass,那么不会影响已经引用它的Pod Priority,但你不能用它来建立新的Pod了。这实际上是显而易见的。
接下来,就是建立对应Priority的Pod了:
apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent priorityClassName: high-priority
若是Pod.spec. priorityClassName中指定的PriorityClass不存在,则Pod会建立失败;
前面也提到,建立Pod的时候Priority Admission Controller会根据PriorityClassName找到对应的PriorityClass,并将其value设置给Pod.spec.priority。
在Kubernetes 1.8以前,Node Condition是会直接干预调度的,逻辑是是这样的,而且是没法改变的:
Node Condition | Scheduler Behavior |
---|---|
MemoryPressure | No new BestEffort pods are scheduled to the node. |
DiskPressure | No new pods are scheduled to the node. |
- 当Node Condition包含Memory Pressure时,再也不容许BestEffort QoS Pods调度到该节点; - 当Node Condition包含DiskPressure时,不容许任何pods调度到该节点。
从Kubernetes 1.6开始,kubelet和Node Controller支持自动根据Node Condition给Node打上相应的内置Taints,当时这些Taints只是会影响kubelet eviction,而不会影响调度。这有啥不一样呢?区别就是,给Node打上Taints对调度来讲是软限制,能够经过给pods加上对应的Tolerations就可能强制调度到那个节点。而在1.8以前,Node Condition影响调度是硬限制。
Node Condition和Taints的Map关系以下:
ConditionType | Condition Status | Effect | Key |
---|---|---|---|
Ready | True | - | |
False | NoExecute | node.kubernetes.io/notReady | |
Unknown | NoExecute | node.kubernetes.io/unreachable | |
OutOfDisk | True | NoSchedule | node.kubernetes.io/outOfDisk |
False | - | ||
Unknown | - | ||
MemoryPressure | True | NoSchedule | node.kubernetes.io/memoryPressure |
False | - | ||
Unknown | - | ||
DiskPressure | True | NoSchedule | node.kubernetes.io/diskPressure |
False | - | ||
Unknown | - | ||
NetworkUnavailable | True | NoSchedule | node.kubernetes.io/networkUnavailable |
False | - | ||
Unknown | - |
Kubernetes 1.8中基于Pod优先级进行抢占式调度的特性都是Alpha,请谨慎在生产中使用,尤为是要注意本文中“Preemption当前还存在的问题”小节中提到的不足。
相信很快就能支持好抢占式调度时支持Pod亲和性、跨节点抢占等特性了,那时就完美了。