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親和性、跨節點搶佔等特性了,那時就完美了。