kube-scheduler排程器排程框架原始碼學習篇1
queueSort擴充套件點
概述
該擴充套件點需要完成的工作為:對兩個pod的排程優先順序進行比較
該擴充套件點有且只有一個外掛實現,預設的實現外掛為下面的PrioritySort外掛。
PrioritySort
pkg/scheduler/framework/plugins/queuesort/priority_sort.go
// Less is the function used by the activeQ heap algorithm to sort pods. // It sorts pods based on their priority. When priorities are equal, it uses // PodQueueInfo.timestamp. func (pl *PrioritySort) Less(pInfo1, pInfo2 *framework.QueuedPodInfo) bool { p1 := corev1helpers.PodPriority(pInfo1.Pod) p2 := corev1helpers.PodPriority(pInfo2.Pod) return (p1 > p2) || (p1 == p2 && pInfo1.Timestamp.Before(pInfo2.Timestamp)) }
-
核心邏輯:通過Less方法比較兩個pod的排程優先順序,如果pod1的優先順序比pod2優先順序高,則返回true
-
比較的依據是先比較podSpec裡的priority,priority越高則優先順序越高;如果priority相等,則時間早的排序靠前
-
podSpec裡的priority欄位在pod到達排程器之前由pod關聯的PriorityClass物件解析而來
-
一個排程器框架中,只有一個queueSort plugin可以被啟用,程式碼中預設啟用了第一個
裝載過程
pkg/scheduler/factory.go
Configurator.create()
資料的流動:config->profile->framework.Framework->QueueSortFunc()->framework.LessFunc
preFilter擴充套件點
概述
對於每一個排程框架下的plugin,處理該擴充套件點的大致套路如下:
- 關鍵輸入:cycleState,pod
- cycleState為各個plugin的共用儲存,其包裝了一個map[string]StateData,可以通過Read、Write方法安全地讀寫
- pod即為v1 api組的Pod結構體,可以從中取得pod的資訊
- 輸出:正常情況返回nil,有錯誤的情況,通過framework.NewStatus()返回類似於Error、Unschedulable等狀態
- 核心操作:每個外掛定義一個獨有的key,以及一個獨有的StateData,按照需求將需要後續使用的資料封裝到StateData中,寫入到cycleState這個map中
以下為不同外掛對該擴充套件點的具體實現
NodeResourcesFit
pkg/scheduler/framework/plugins/noderesources/fit.go
func computePodResourceRequest(pod *v1.Pod) *preFilterState {
result := &preFilterState{}
for _, container := range pod.Spec.Containers {
result.Add(container.Resources.Requests)
}
// take max_resource(sum_pod, any_init_container)
for _, container := range pod.Spec.InitContainers {
result.SetMaxResource(container.Resources.Requests)
}
// If Overhead is being utilized, add to the total requests for the pod
if pod.Spec.Overhead != nil && utilfeature.DefaultFeatureGate.Enabled(features.PodOverhead) {
result.Add(pod.Spec.Overhead)
}
return result
}
-
核心邏輯:對於一個進入排程過程的pod,計算其整體的資源需求量,為後續流程做準備
-
由於init container順序啟動,所以對於它們的同種資源需求取最大值;普通container的同種資源需求累加
-
除了統計一個pod內所有容器的資源需求外,排程器還支援將pod本身除容器以外的額外資源開銷納入排程流程中,詳情見Pod開銷 。因此函式的最後會檢查該特性門控是否開啟,pod是否有overhead欄位,如果滿足條件,會把這類資源消耗也納入統計中
NodePorts
pkg/scheduler/framework/plugins/nodeports/node_ports.go
// getContainerPorts returns the used host ports of Pods: if 'port' was used, a 'port:true' pair
// will be in the result; but it does not resolve port conflict.
func getContainerPorts(pods ...*v1.Pod) []*v1.ContainerPort {
ports := []*v1.ContainerPort{}
for _, pod := range pods {
for j := range pod.Spec.Containers {
container := &pod.Spec.Containers[j]
for k := range container.Ports {
ports = append(ports, &container.Ports[k])
}
}
}
return ports
}
- 核心邏輯:遍歷pod的所有容器的所有埠,將其展平後放入一個slice中
PodTopologySpread
pkg/scheduler/framework/plugins/podtopologyspread/filtering.go
該擴充套件點主要處理pod的拓撲域打散資訊,略
InterPodAffinity
pkg/scheduler/framework/plugins/interpodaffinity/filtering.go
該擴充套件點主要處理pod的affinity和antifinity資訊,略
VolumeBinding
pkg/scheduler/framework/plugins/volumebinding/volume_binding.go
-
核心邏輯:遍歷podSpec的volume,判斷是否用到了pvc,如果沒有用到,則該擴充套件點沒有意義,跳過;如果有pvc,則解析pvc的資訊
-
解析出的PVC狀態分為三類:bound, tobind, unboundImmediate,其中的unboundImmediate狀態屬於非正常狀態,如果存在這類pvc,會直接返回錯誤資訊
pod has unbound immediate PersistentVolumeClaims
,並將pod重新放回排程佇列 -
最後會初始化一個map:podVolumesByNode,在filter擴充套件點階段會用到
NodeAffinity
pkg/scheduler/framework/plugins/nodeaffinity/node_affinity.go
func GetRequiredNodeAffinity(pod *v1.Pod) RequiredNodeAffinity {
var selector labels.Selector
if len(pod.Spec.NodeSelector) > 0 {
selector = labels.SelectorFromSet(pod.Spec.NodeSelector)
}
// Use LazyErrorNodeSelector for backwards compatibility of parsing errors.
var affinity *LazyErrorNodeSelector
if pod.Spec.Affinity != nil &&
pod.Spec.Affinity.NodeAffinity != nil &&
pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution != nil {
affinity = NewLazyErrorNodeSelector(pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution)
}
return RequiredNodeAffinity{labelSelector: selector, nodeSelector: affinity}
}
- 核心邏輯:解析podSpec裡的nodeSelector欄位和nodeAffinity欄位,儲存
- 此處只處理了RequiredDuringSchedulingIgnoredDuringExecution型別的nodeAffinity