Kubernetes Scheduling Framework 與 Extender對比及詳細介紹

Kubernetes 開始只提供了 Extender ,通過部署一個 Web 服務實現無侵入式擴展 scheduler插件,但其存在以下幾個問題:

  1. Extender 擴展點的數量是有限的:在調度期間只有“Filter”和“Prioritize”擴展點。 “Preempt”擴展點在運行默認搶佔機制後被調用。“Bind”擴展點用於綁定Pod,且 Bind 擴展點只能綁定一個擴展程序,擴展點會替換掉調度器的 bind 操作。Extender 不能在其他點被調用,例如,不能在運行 predicate 函數之前被調用。

  2. 性能問題:對擴展程序的每次調用都涉及 JSON 的編解碼。調用 webhook(HTTP 請求)也比調用原生函數慢。

  3. 調度器無法通知 Extender 已中止 Pod 的調度。例如,如果一個 Extender 提供了一個集羣資源,而調度器聯繫了 Extender 並要求它爲正在調度的 pod 提供資源的實例,然後調度器在調度 pod 時遇到錯誤並決定中止調度,那麼將很難與擴展程序溝通錯誤並要求它撤消資源的配置。

  4. 由於當前的Extender作爲一個單獨的進程運行,因此不能使用調度器的緩存。要麼從 API Server構建自己的緩存,要麼只處理他們從調度器接收到的信息。

Scheduling Framework 調度框架是一組新的“插件”API,通過這些 API 允許將許多調度功能使用插件實現,同時保持調度器“核心”簡單和可維護。調度器插件必須用 Go 編寫,並使用 Kubernetes 調度器代碼編譯,有一定學習成本。

雖然 Extender 簡單,從長遠考慮,儘量選擇Scheduling Framework。下面是基於官方設計文檔對這 2 種擴展方式進行詳細整理。

Extender

Scheduler Extender實際上是一個額外的Web服務,通過註冊外部 webhook 來擴展默認調度器以調整不同階段的調度決策。根據自己的需要實現的Filter方法、Prioritize方法、Bind方法。

優點:

  1. 可以擴展現有調度器的功能,而無需重新編譯二進制文件。

  2. 擴展器可以用任何語言編寫。

  3. 實現後,可用於擴展不同版本的 kube-scheduler。

設計

在調度 pod 時,Extender 允許外部進程過濾節點並確定節點優先級。向 Extender 發出兩個單獨的 http/https 調用,即“filter”和“prioritize”操作。如果 pod 無法被調度,調度器將嘗試從節點搶佔較低優先級的 pod,並將它們發送到Extender的“preempt”接口(如果已配置)。Extender可以將節點子集和新被驅逐者返回給調度器。此外,Extender可以選擇通過實現“bind”操作將 pod 綁定到 apiserver。

Configuration

要使用 Extender,必須創建調度器配置文件。 配置訪問方式是 http 還是 https 以及超時配置等。

// Holds the parameters used to communicate with the extender. If a verb is unspecified/empty,
// it is assumed that the extender chose not to provide that extension.
type ExtenderConfig struct {
	// URLPrefix at which the extender is available
	URLPrefix string `json:"urlPrefix"`
	// Verb for the filter call, empty if not supported. This verb is appended to the URLPrefix when issuing the filter call to extender.
	FilterVerb string `json:"filterVerb,omitempty"`
	// Verb for the preempt call, empty if not supported. This verb is appended to the URLPrefix when issuing the preempt call to extender.
	PreemptVerb string `json:"preemptVerb,omitempty"`
	// Verb for the prioritize call, empty if not supported. This verb is appended to the URLPrefix when issuing the prioritize call to extender.
	PrioritizeVerb string `json:"prioritizeVerb,omitempty"`
	// Verb for the bind call, empty if not supported. This verb is appended to the URLPrefix when issuing the bind call to extender.
	// If this method is implemented by the extender, it is the extender's responsibility to bind the pod to apiserver.
	BindVerb string `json:"bindVerb,omitempty"`
	// The numeric multiplier for the node scores that the prioritize call generates.
	// The weight should be a positive integer
	Weight int `json:"weight,omitempty"`
	// EnableHttps specifies whether https should be used to communicate with the extender
	EnableHttps bool `json:"enableHttps,omitempty"`
	// TLSConfig specifies the transport layer security config
	TLSConfig *ExtenderTLSConfig `json:"tlsConfig,omitempty"`
	// HTTPTimeout specifies the timeout duration for a call to the extender. Filter timeout fails the scheduling of the pod. Prioritize
	// timeout is ignored, k8s/other extenders priorities are used to select the node.
	HTTPTimeout time.Duration `json:"httpTimeout,omitempty"`
	// NodeCacheCapable specifies that the extender is capable of caching node information,
	// so the scheduler should only send minimal information about the eligible nodes
	// assuming that the extender already cached full details of all nodes in the cluster
	NodeCacheCapable bool `json:"nodeCacheCapable,omitempty"`
	// ManagedResources is a list of extended resources that are managed by
	// this extender.
	// - A pod will be sent to the extender on the Filter, Prioritize and Bind
	//   (if the extender is the binder) phases iff the pod requests at least
	//   one of the extended resources in this list. If empty or unspecified,
	//   all pods will be sent to this extender.
	// - If IgnoredByScheduler is set to true for a resource, kube-scheduler
	//   will skip checking the resource in filter plugins.
	// +optional
	ManagedResources []ExtenderManagedResource `json:"managedResources,omitempty"`
	// Ignorable specifies if the extender is ignorable, i.e. scheduling should not
	// fail when the extender returns an error or is not reachable.
	Ignorable bool `json:"ignorable,omitempty"
}

配置文件示例:

apiVersion: kubescheduler.config.k8s.io/v1beta1
kind: KubeSchedulerConfiguration
extenders:
- urlPrefix: "http://127.0.0.1:12345/api/scheduler"
  filterVerb: "filter"
  preemptVerb: "preempt"
  prioritizeVerb: "prioritize"
  bindVerb: "bind"
  enableHttps: false
  nodeCacheCapable: false
  managedResources:
  - name: opaqueFooResource
    ignoredByScheduler: true
  ignorable: false

可以配置多個 Extender,調度器會按順序調用。

Interface

Extender Web模塊可以根據需要實現以下4個接口,每個接口都有對應的request和response。

Filter

Request

// ExtenderArgs represents the arguments needed by the extender to filter/prioritize
// nodes for a pod.
type ExtenderArgs struct {
	// Pod being scheduled
	Pod   api.Pod      `json:"pod"`
	// List of candidate nodes where the pod can be scheduled
	Nodes api.NodeList `json:"nodes"`
	// List of candidate node names where the pod can be scheduled; to be
	// populated only if Extender.NodeCacheCapable == true
	NodeNames *[]string
}

Response

// FailedNodesMap represents the filtered out nodes, with node names and failure messages
type FailedNodesMap map[string]string

// ExtenderFilterResult represents the results of a filter call to an extender
type ExtenderFilterResult struct {
	// Filtered set of nodes where the pod can be scheduled; to be populated
	// only if Extender.NodeCacheCapable == false
	Nodes *v1.NodeList
	// Filtered set of nodes where the pod can be scheduled; to be populated
	// only if Extender.NodeCacheCapable == true
	NodeNames *[]string
	// Filtered out nodes where the pod can't be scheduled and the failure messages
	FailedNodes FailedNodesMap
	// Filtered out nodes where the pod can't be scheduled and preemption would
	// not change anything. The value is the failure message same as FailedNodes.
	// Nodes specified here takes precedence over FailedNodes.
	FailedAndUnresolvableNodes FailedNodesMap
	// Error message indicating failure
	Error string
}

Prioritize

Request

同 Filter Request

Response

// HostPriority represents the priority of scheduling to a particular host, higher priority is better.
type HostPriority struct {
	// Name of the host
	Host string
	// Score associated with the host
	Score int64
}

// HostPriorityList declares a []HostPriority type.
type HostPriorityList []HostPriority

Bind

Request

// ExtenderBindingArgs represents the arguments to an extender for binding a pod to a node.
type ExtenderBindingArgs struct {
	// PodName is the name of the pod being bound
	PodName string
	// PodNamespace is the namespace of the pod being bound
	PodNamespace string
	// PodUID is the UID of the pod being bound
	PodUID types.UID
	// Node selected by the scheduler
	Node string
}

Response

// ExtenderBindingResult represents the result of binding of a pod to a node from an extender.
type ExtenderBindingResult struct {
	// Error message indicating failure
	Error string
}

Preempt

Request

// ExtenderPreemptionArgs represents the arguments needed by the extender to preempt pods on nodes.
type ExtenderPreemptionArgs struct {
	// Pod being scheduled
	Pod *v1.Pod
	// Victims map generated by scheduler preemption phase
	// Only set NodeNameToMetaVictims if Extender.NodeCacheCapable == true. Otherwise, only set NodeNameToVictims.
	NodeNameToVictims     map[string]*Victims
	NodeNameToMetaVictims map[string]*MetaVictims
}

Response

// ExtenderPreemptionResult represents the result returned by preemption phase of extender.
type ExtenderPreemptionResult struct {
	NodeNameToMetaVictims map[string]*MetaVictims
}

Scheduling Framework

調度框架是一組被添加到現有的 Kubernetes 調度器中新的“插件” API。這些 API 允許將許多調度功能實現爲插件,並編譯到調度器中,同時保持調度“核心”簡單和可維護。

隨着越來越多功能添加到 Kubernetes 調度器中。這些新功能不斷地使代碼量更大,邏輯更復雜。從而導致調度器更難維護,錯誤更難發現和修復,並且那些運行自定義調度器的用戶很難趕上和集成新的變化。雖然當前的 Kubernetes 調度器提供了 webhook 來擴展其功能。但是,這些在以下幾個方面受到限制:

  1. Extender 擴展點的數量是有限的:在調度期間只有“Filter”和“Prioritize”擴展點。 “Preempt”擴展點在運行默認搶佔機制後被調用。“Bind”擴展點用於綁定Pod,且 Bind 擴展點只能綁定一個擴展程序,擴展點會替換掉調度器的 bind 操作。Extender 不能在其他點被調用,例如,不能在運行 predicate 函數之前被調用。

  2. 性能問題:對擴展程序的每次調用都涉及 JSON 的編解碼。調用 webhook(HTTP 請求)也比調用原生函數慢。

  3. 調度器無法通知 Extender 已中止 Pod 的調度。例如,如果一個 Extender 提供了一個集羣資源,而調度器聯繫了 Extender 並要求它爲正在調度的 pod 提供資源的實例,然後調度器在調度 pod 時遇到錯誤並決定中止調度,那麼將很難與擴展程序溝通錯誤並要求它撤消資源的配置。

  4. 由於當前的 Extender 作爲一個單獨的進程運行,因此不能使用調度器的緩存。要麼從 API Server構建自己的緩存,要麼只處理他們從調度器接收到的信息。

上述限制阻礙了構建高性能和更多功能的調度器。理想情況下,希望有一個足夠快的擴展機制,以允許將現有功能轉換爲插件,例如predicate和priority函數。 此類插件將被編譯到調度器二進制文件中。此外,自定義調度器的作者可以使用(未修改的)調度器代碼和他們自己的插件來編譯自定義調度器。

設計目標

  1. 使調度器更具可擴展性。

  2. 通過將調度器核心的一些功能移至插件,使調度器核心更簡單。

  3. 在框架中提出擴展點。

  4. 提出一種機制來接收插件結果並根據收到的結果繼續或中止。

  5. 提出一種機制來處理錯誤並與插件進行通信。

調度框架在 Kubernetes 調度器中定義了新的擴展點和 Go API,以供“plugins”使用。 插件將調度行爲添加到調度器,並在編譯時包含進來。調度器的ComponentConfig 將允許啓用、禁用和重新排序插件。自定義調度器可以“out-of-tree”編寫他們的插件,並編譯一個包含他們自己的插件的調度器二進制文件。

調度週期和綁定週期

每次調度一個 pod 的都分爲兩個階段:調度週期和綁定週期。 調度週期爲 pod 選擇一個節點,綁定週期將該調度結果應用於集羣。調度週期和綁定週期一起被稱爲“調度上下文”。 調度週期串行運行,而綁定週期可能併發運行。

如果確定 pod 不可調度或存在內部錯誤,則可以中止調度週期或綁定週期。 pod 將返回隊列並重試。 如果綁定循環被中止,它將觸發 Reserve 插件中的 Unreserve 方法。

擴展點

下圖展示了 Pod 的調度上下文和調度框架暴露的擴展點。在這張圖中,“Filter”相當於 Extender 的“Predicate”,“Scoring”相當於“Priority”。插件註冊爲在這些擴展點中的一個或多個處調用。 在以下部分中,我們按照調用它們的相同順序描述每個擴展點。

Queue sort

這些插件用於對調度隊列中的 pod 進行排序。其本質上將提供less(pod1, pod2)功能。一次只能啓用一個隊列排序插件。

PreFilter

PreFilter 在每個調度週期中調用一次。這些插件用於預處理有關 pod 的信息,或檢查集羣、pod 必須滿足的某些條件。一個前置過濾器插件應該實現一個PreFilter 接口,如果前置過濾器返回一個錯誤,則調度週期被中止。

Pre-filter 插件可以實現可選的 PreFilterExtensions 接口,該接口定義 AddPod 和 RemovePod 方法以增量修改其預處理信息。框架保證這些函數只會在 PreFilter 之後調用,在克隆的 CycleState 上,並且在調用特定節點上的 Filter 之前可能會多次調用這些函數。

Filter

用於過濾掉無法運行 Pod 的節點。對於每個節點,調度器將按照配置的順序調用filter插件。如果任何filter插件將該節點標記爲不可行,則不會爲該節點調用其餘插件。節點可能會被併發地評估,並且可以在同一調度週期中多次調用filter。

PostFilter

在Filter階段之後被調用,僅在沒有爲 pod 找到可行節點時調用。插件按其配置的順序調用。如果任何 PostFilter 插件將該節點標記爲可調度,則不會調用其餘插件。一個典型的 PostFilter 實現是搶佔,試圖通過搶佔其他 Pod 來使 Pod可調度。

PreScore

用於執行PreScore的信息擴展點。將使用過濾階段的節點列表調用插件 插件可以使用這些數據來更新內部狀態或生成logs/metrics。

Scoring

這裏的插件有兩個階段:

第一階段稱爲“score”,用於對已通過過濾階段的節點進行排名。調度器將爲每個節點調用每個評分插件的 Score函數。

第二階段是“normalize scoring”,用於在調度器計算節點的最終排名之前修改分數,並且每個評分插件在“normalize scoring”階段接收同一插件給所有節點的分數。在“score”階段之後,每個調度週期每個插件都會調用 NormalizeScore 一次。NormalizeScore 是可選的,可以通過實現 ScoreExtensions 接口來提供。

score插件的輸出必須是 [MinNodeScore, MaxNodeScore] 範圍內的整數。如果不是,則調度週期被中止。這是運行插件的可選 NormalizeScore 函數後的輸出。如果未提供 NormalizeScore,則 Score 的輸出必須在此範圍內。在可選的 NormalizeScore 之後,調度器將根據配置的插件權重組合來自所有插件的節點分數。

例如,假設插件 BlinkingLightScorer 根據節點的閃爍燈數對節點進行排名。

func (*BlinkingLightScorer) Score(state *CycleState, _ *v1.Pod, nodeName string) (int, *Status) {
   return getBlinkingLightCount(nodeName)
}

但是,與 MaxNodeScore 相比,閃爍燈的最大計數可能很小。 爲了解決這個問題,BlinkingLightScorer 還應該實現 NormalizeScore。

func (*BlinkingLightScorer) NormalizeScore(state *CycleState, _ *v1.Pod, nodeScores NodeScoreList) *Status {
   highest := 0
   for _, nodeScore := range nodeScores {
      highest = max(highest, nodeScore.Score)
   }
   for i, nodeScore := range nodeScores {
      nodeScores[i].Score = nodeScore.Score*MaxNodeScore/highest
   }
   return nil
}

如果 Score 或 NormalizeScore 返回錯誤,則調度週期中止。

Reserve

實現 Reserve 擴展的插件有兩種方法,即 Reserve 和 Unreserve,它們分別支持兩個信息調度階段,分別稱爲 Reserve 和 Unreserve。維護運行時狀態的插件(又名“stateful plugins”)應該使用這些階段來通知調度器何時節點上的資源正在爲給定 Pod Reserve 和Unreserve。

Reserve 階段發生在調度器實際將 Pod 綁定到其指定節點之前。它的存在是爲了防止調度器等待綁定成功時出現競爭條件。每個 Reserve 插件的 Reserve 方法可能成功或失敗; 如果一個 Reserve 方法調用失敗,則不會執行後續插件,並且 Reserve 階段被視爲失敗。 如果所有插件的 Reserve 方法都成功,則認爲 Reserve 階段成功,並執行剩餘的調度週期和綁定週期。

如果 Reserve 階段或後續階段失敗,則會觸發 Unreserve 階段。發生這種情況時,所有 Reserve 插件的 Unreserve 方法將按照 Reserve 方法調用的相反順序執行。 此階段的存在是爲了清理與保留 Pod 關聯的狀態。

注意:Reserve 插件中 Unreserve 方法的實現必須是冪等的,不能失敗。

Permit

這些插件用於阻止或延遲 Pod 的綁定。 Permit插件可以做三件事之一。

  1. approve 批准

一旦所有 Permit 插件都批准了一個 pod,它就會被髮送以進行綁定。

  1. deny 否定

如果任何 Permit 插件拒絕了一個 pod,它會被返回到調度隊列。 這將觸發 Reserve 插件中的 Unreserve 方法。

  1. wait等待(超時)

如果許可插件返回“wait”,則 pod 將保持在Permit階段,直到插件批准它爲止。 如果超時,wait 變爲deny ,pod 會返回調度隊列,在 Reserve 階段觸發 unreserve 方法。

Permit插件作爲調度週期的最後一步執行,但是在Permit階段的等待發生在綁定週期的開始,在 PreBind 插件執行之前。

批准 pod 綁定

雖然任何插件都可以從緩存中接收保留 Pod 的列表並批准它們(請參閱 FrameworkHandle),但我們希望只有許可插件批准綁定處於“waiting”狀態的reserved Pod。 一旦 Pod 被批准,它就會被髮送到預綁定階段。

PreBind

用於在綁定 pod 之前執行所需的任何工作。例如,預綁定插件可能會提供一個網絡卷並將其掛載到目標節點上,然後才允許 pod 運行。

如果任何 PreBind 插件返回錯誤,則該 pod 將被拒絕並返回到調度隊列。

Bind

用於將 pod 綁定到節點。在所有 PreBind 插件完成之前,不會調用綁定插件。每個綁定插件都按配置的順序調用。綁定插件可以選擇是否處理給定的 Pod。如果綁定插件選擇處理 Pod,則跳過剩餘的綁定插件。

PostBind

這是一個信息擴展點。PostBind 插件在 Pod 成功綁定後調用。這時綁定週期的結束,可用於清理相關資源。

Plugin API

插件 API 有兩個步驟。 1. 註冊和配置,2. 使用擴展點接口。擴展點接口有以下形式。

type Plugin interface {
   Name() string
}

type QueueSortPlugin interface {
   Plugin
   Less(*PodInfo, *PodInfo) bool
}

type PreFilterPlugin interface {
   Plugin
   PreFilter(CycleState, *v1.Pod) *Status
}

// ... 

CycleState

大多數插件函數(除了隊列排序插件)將使用 CycleState 參數調用。CycleState 表示當前調度上下文。

CycleState 將提供用於訪問範圍爲當前調度上下文的數據的 API。 因爲綁定循環可能併發執行,插件可以使用 CycleState 來確保它們處理正確的請求。

CycleState 還提供了一個類似於 context.WithValue 的 API,可用於在不同擴展點的插件之間傳遞數據。多個插件可以通過這種機制共享狀態或通信。該狀態僅在單個調度上下文期間保留。注意,插件被假定爲受信任的。調度器不會阻止一個插件訪問或修改另一個插件的狀態。

警告:通過 CycleState 引用的數據在調度上下文結束後無效,並且插件不應持有對該數據的引用超過必要的時間。

FrameworkHandle

CycleState 提供與單個調度上下文相關的 API,而 FrameworkHandle 提供與插件生命週期相關的 API。這就是插件如何獲取客戶端(kubernetes.Interface)和 SharedInformerFactory,或者從調度器的集羣狀態緩存中讀取數據的方式。該句柄還將提供 API 來列出和批准/拒絕等待的 pod。

警告:FrameworkHandle 提供對 kubernetes API Server和調度器內部緩存的訪問。但兩者不能保證同步,因此在編寫使用來自它們兩者的數據的插件時應格外小心。

提供對 API 服務器的插件訪問對於實現有用的功能是必要的,尤其是當這些功能使用調度器通常不考慮的對象類型時。提供 SharedInformerFactory 允許插件安全地共享緩存。

Plugin Registration

每個插件都必須定義一個構造函數並將其添加到硬編碼註冊表中。有關構造函數參數的更多信息,請參閱可選參數

type PluginFactory = func(runtime.Unknown, FrameworkHandle) (Plugin, error)

type Registry map[string]PluginFactory

func NewRegistry() Registry {
   return Registry{
      fooplugin.Name: fooplugin.New,
      barplugin.Name: barplugin.New,
      // New plugins are registered here.
   }
}

也可以將插件添加到註冊表對象並將其注入調度器。 請參閱自定義調度器插件

Plugin Lifecycle

Initialization

插件初始化有兩個步驟。 首先,註冊插件。 其次,調度器使用其配置來決定要實例化哪些插件。如果一個插件註冊了多個擴展點,它只會被實例化一次。

當一個插件被實例化時,它會被傳遞 config args 和一個 FrameworkHandle。

Concurrency

插件編寫者應該考慮兩種類型的併發。在評估多個節點時,一個插件可能會同時被調用多次,並且一個插件可能會從不同的調度上下文中被同時調用。

注意:在一個調度上下文中,每個擴展點都被串行評估。

在調度器的主線程中,一次只處理一個調度週期。直到幷包括 permit 在內的任何擴展點都將在下一個調度週期開始之前完成(隊列排序擴展點是一個特例。 它不是調度上下文的一部分,並且可以爲許多 pod 對同時調用)。在 permit 擴展點之後,異步執行綁定週期。這意味着插件可能會被兩個不同的調度上下文同時調用。有狀態的插件應該注意處理這些情況。

最後,可以從主線程或綁定線程調用 Reserve 插件中的 Unreserve 方法,具體取決於 pod 被拒絕的方式。

Configuring Plugins

調度器的組件配置將允許啓用、禁用或以其他方式配置插件。插件配置分爲兩部分。

  1. 每個擴展點的啓用插件列表(以及它們應該運行的順序)。 如果省略這些列表之一,將使用默認列表。

  2. 每個插件都有一組可選的自定義參數。省略插件的參數等同於使用該插件的默認配置。

插件配置由擴展點組織。每個列表中必須包含註冊多個點的插件。

type KubeSchedulerConfiguration struct {
    // ... other fields
    Plugins      Plugins
    PluginConfig []PluginConfig
}

type Plugins struct {
    QueueSort      []Plugin
    PreFilter      []Plugin
    Filter         []Plugin
    PostFilter     []Plugin
    PreScore       []Plugin
    Score          []Plugin
    Reserve        []Plugin
    Permit         []Plugin
    PreBind        []Plugin
    Bind           []Plugin
    PostBind       []Plugin
}

type Plugin struct {
    Name   string
    Weight int // Only valid for Score plugins
}

type PluginConfig struct {
    Name string
    Args runtime.Unknown
}

Example:

{
  "plugins": {
    "preFilter": [
      {
        "name": "PluginA"
      },
      {
        "name": "PluginB"
      },
      {
        "name": "PluginC"
      }
    ],
    "score": [
      {
        "name": "PluginA",
        "weight": 30
      },
      {
        "name": "PluginX",
        "weight": 50
      },
      {
        "name": "PluginY",
        "weight": 10
      }
    ]
  },
  "pluginConfig": [
    {
      "name": "PluginX",
      "args": {
        "favorite_color": "#326CE5",
        "favorite_number": 7,
        "thanks_to": "thockin"
      }
    }
  ]
}

Enable/Disable

配置則爲指定擴展點的插件列表是唯一啓用的。如果某個擴展點省略配置,則該擴展點使用默認插件集。

Change Evaluation Order

插件執行順序由插件在配置中出現的順序決定。註冊多個擴展點的插件可以在每個擴展點有不同的順序。

Optional Args

插件可以從其配置中接收具有任意結構的參數。因爲一個插件可能出現在多個擴展點中,所以配置位於 PluginConfig 的單獨列表中。

例如

{
   "name": "ServiceAffinity",
   "args": {
      "LabelName": "app",
      "LabelValue": "mysql"
   }
}
func NewServiceAffinity(args *runtime.Unknown, h FrameworkHandle) (Plugin, error) {
    if args == nil {
        return nil, errors.Errorf("cannot find service affinity plugin config")
    }
    if args.ContentType != "application/json" {
        return nil, errors.Errorf("cannot parse content type: %v", args.ContentType)
    }
    var config struct {
        LabelName, LabelValue string
    }
    if err := json.Unmarshal(args.Raw, &config); err != nil {
        return nil, errors.Wrap(err, "could not parse args")
    }
    //...
}

向後兼容性

當前的 KubeSchedulerConfiguration 類型有 apiVersion:kubescheduler.config.k8s.io/v1alpha1。 這種新的配置格式是 v1alpha2v1beta1。 較新版本的調度器解析 v1alpha1 時,“policy”部分將用於構造等效的插件配置。

與Cluster Autoscaler的交互

Cluster Autoscaler 必須運行Filter plugins而不是predicates。 這可以通過創建一個Framework實例並調用 RunFilterPlugins 來完成。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章