kube-schedulerソース分析
21017 ワード
kubernetesクラスタの3ステップインストール
kube-schedulerソース分析
ソースコンパイルについて
私は公式に提供されたコンパイルスクリプトが面倒であることを嫌って、k 8 sコードをより簡単で乱暴な方法でコンパイルしました.もちろん、公式スクリプトはすべてのプロジェクトをコンパイルしたり、プラットフォームのコンパイルやrealseを誇張したりするときに役立ちます.
コンテナでコンパイル:
容器の中で環境がきれいであることを保証することができます
bashに入ってからkube-schedulerのホームディレクトリに直接入ってコンパイルすればいいです.
バイナリが生まれました...
ソースコードコンパイルアクセスCI/CD
ハイエンドプレイヤーとして、自動化は必要です.サーバーの性能がもっと良いので、CI/CDでコンパイルするのがもっと速いです.ここで私のいくつかの構成を共有します.コンパイルされたベースミラーにvendorを入れました.vendorが大きく、 を頻繁に更新しないからです.
そしてコードのvendorは削除できます .drone.yml Dockerfile静的コンパイルベースミラーも 節約
kubeadmというバイナリ配信の場合、直接コンパイルしてnexusに転送し、drone deployイベントでkubeadmをコンパイルするかどうかを選択します.
ダイレクトgo buildの大きな穴
buildが完了したkubeadmバイナリは使用できないことがわかりました.buildで選択したベースミラーの問題かもしれません.コードを生成しなかった問題かもしれません.
あとでCDのセットを追加します
このようにschedulerコードをコンパイルするのは約40秒ぐらいで、vendorがソフト接続できるように十数秒節約できます.
スケジューラcache
Cacheステータスマシン Assumeがスケジューリングを試みると、pod requireのCPUメモリがどれだけあるかなどのnode情報がnodeに集約され、nodeに加算され、タイムアウトしたら を再削減する必要がある. AddPodは、そのpodがスケジュールされているかどうかを検出し、期限が切れているかどうかを確認し、期限が切れている場合は が追加されます. Remove pod情報は、ノード上で消去される . cache node関連cacheインタフェースADD updateなどの他のインタフェース .
Cache実装
ここには、基本スケジューリングに必要なすべての情報が格納されています.
AddPodインタフェースを例にとると、本質的には傍受されたpodをcacheのmapに入れることです.
Node Treeノード情報には、次のような構造体が保存されます.
Cache実行時に期限切れのassume podをループクリーンアップ
scheduler
schedulerの中で最も重要な2つのもの:cacheとスケジューリングアルゴリズム
cacheが更新されると、スケジューラはpodをスケジューリングします.
コアロジックが来ました:
bindアクション:
先にbind podに行って、それからcache bindに終わりを教えます
bindプロセス
bind実装
最終的にapiserver bindインタフェースが呼び出されます.
スヶジューリングアルゴリズム
今最も重要なのはノード選択の実装です
つまり、スケジューリングアルゴリズムの実装:
スケジューリングアルゴリズムは、次の2つの方法で生成できます. Providerデフォルト、汎用スケジューラ Policyポリシー方式、特殊スケジューラ 最終的にはschedulerが
このschedulerはScheduleAlgorithmで定義されたインタフェースを実現した.
Scheduleプロセス:
せんたく
主に二つに分けるの予選で、ノードが に合致するかどうかを確認します. extender、カスタムスケジューラ拡張を実行し、HTTP extenderが予選結果をユーザーに送ることを公式に実現し、ユーザーは をフィルタリングする.
podFitOnNode:このノードがこのpodスケジューリングに適しているかどうかを判断する
ここには小さな知識が挿入されています.スケジューラにはEcacheがあります.
Equivalence Classは現在、Kubernetes SchedulerでPredicateを加速させ、Schedulerのスループット性能を向上させるために使用されています.Kubernetes schedulerはEquivalence Cacheのデータをタイムリーに維持しており、場合によってはdelete node、bind podなどのイベントが発生すると、すぐにinvalid関連のEquivalence Cacheのキャッシュデータが必要になります.
1つのEquivalence Classは、同じRequirementsとConstraintsを持つPodsの関連情報のセットを定義するために使用され、SchedulerがPredicateフェーズを行う場合、Equivalence Classの1つのPodに対してPredicateを行い、Predicateの結果をEquivalence Cacheに配置してEquivalence Classの他のPods(Equivalent Podsとなる)結果を再利用します.通常のPredicateプロセスは、Equivalence Cacheに再利用可能なPredicate Resultがない場合にのみ実行されます.
ecacheという後続は深く議論することができ、本稿ではコアアーキテクチャとプロセスに注目する.
すべての予選関数を1回実行するのは簡単です
順序は次のとおりです.
これらの予選関数はmapに存在し、keyはstringであり、valueは予選関数であり、mapを登録する論理を振り返る.
pkg/scheduler/algorithmprovider/defaults/defaults.goには、次のような関数が登録されています.
そしてinit関数で登録ロジックを直接呼び出します
好ましい
PrioritizeNodesは、3つのステップに分けられることが好ましい. Mapは単一ノードを計算し、優先度 Reduce各ノードの結果集約を計算し、全ノードの最終スコア を計算する. Extenderと予選差が少ない 好ましい関数も同様に登録されており,これ以上述べることはない
ここで登録する時に2つ登録して、1つのmap関数1つのreduce関数、もっと良い理解のmapreduceのために、1つの実現を見に行きます
node Affinity map reduce
mapコアロジック、比較的に理解しやすい:
reduce:1つのノードは多くのmapを歩き、各mapはnode affinityが1つ生成され、pod affinityがもう1つ生成されるので、nodeとスコアは1対多の関係です.
reverseの論理を削除(スコアが高いほど優先度が低い)
ここで正規化処理をすると点数が[0,maxPriority]の間になります
ここにresultsがあります.理解にとって重要な2次元配列です.
xxx
node1
node2
node3
nodeaffinity
1点
2点
1点
pod affinity
1点
3点
6点
...
...
...
...
このようにreduceで1行をとると,実際にはすべてのノードの得点を処理する.
reduceが最終的にこのノードの得点を完了すると、このノードの各得点にその重みを乗じた和に等しくなり、最後に最高点(1次元が0緯になる)をソートします.
スケジューリングキューSchedulingQueue
scheduler構成には
プロファイルはここで初期化されます.
キューインタフェース:
優先キューとFIFOの2つのインプリメンテーションが与えられました.
キューの実装は簡単で、深く分析しないで、もっと重要なのはキュー、スケジューラ、cacheの関係に注目することです.
Extender
スケジューラ拡張
カスタマイズスケジューラには3つの方法があります. schedulerコードを変更して再コンパイル- について議論することはありません.スケジューラを書き換え、スケジューリング時にスケジューラを選択-比較的簡単で、問題はデフォルトのスケジューラと共同で を使用できないことです.書き込みスケジューラ拡張(extender)k 8 sのスケジューリングを完了させ、該当するノードをフィルタリングし、最適化します.重点的に議論します.新しいバージョンはいくつかのアップグレードを行い、古い方法では資料が役に立たない可能性があります. ここにスケジューラ拡張事例 があります
現在、3つ目の資料は非常に少なく、多くの詳細はコードの中で答えを見つける必要があり、問題を持ってコードを見ると効果的です.
Extenderインタフェース
このインタフェースはkube-schedulerで実装されています.HTTPextenderの実装について説明します.
HTTPextenderが公式に実現されました.
その予選と好ましい論理を見てください.
HTTPExtender構成パラメータはどこから
scheduler extender構成:
まとめ
スケジューラのコードはよく書けています.kube-proxyよりずっとよくなっています.拡張性もまあまあですが、目測スケジューラは大きな再構築に直面します.現段階では、スケジューラが深く学習したバッチタスクのサポートはよくありません.one by oneスケジューリングのこのような設定はプロジェクト全体のアーキテクチャに関係しています.より優れたスケジューリングを優雅にサポートするには、再構築は逃げられないだろう.
スキャンコード注目sealyun
検討可加QQ群:98488045
kube-schedulerソース分析
ソースコンパイルについて
私は公式に提供されたコンパイルスクリプトが面倒であることを嫌って、k 8 sコードをより簡単で乱暴な方法でコンパイルしました.もちろん、公式スクリプトはすべてのプロジェクトをコンパイルしたり、プラットフォームのコンパイルやrealseを誇張したりするときに役立ちます.
コンテナでコンパイル:
docker run -v /work/src/k8s.io/kubernetes:/go/src/k8s.io/kubernetes golang:1.11.2 bash
容器の中で環境がきれいであることを保証することができます
bashに入ってからkube-schedulerのホームディレクトリに直接入ってコンパイルすればいいです.
cd cmd/kube-scheduler && go build
バイナリが生まれました...
ソースコードコンパイルアクセスCI/CD
ハイエンドプレイヤーとして、自動化は必要です.サーバーの性能がもっと良いので、CI/CDでコンパイルするのがもっと速いです.ここで私のいくつかの構成を共有します.
$ cat Dockerfile-build1.12.2
FROM golang:1.11.2
COPY vendor/ /vendor
そしてコードのvendorは削除できます
workspace:
base: /go/src/k8s.io
path: kubernetes
pipeline:
build:
image: fanux/kubernetes-build:1.12.2-beta.3
commands:
- make all WHAT=cmd/kube-kubescheduler GOFLAGS=-v
publish:
image: plugins/docker
registry: xxx
username: xxx
password: xxx
email: xxx
repo: xxx/container/kube-scheduler
tags: ${DRONE_TAG=latest}
dockerfile: dockerfile/Dockerfile-kube-scheduler
insecure: true
when:
event: [push, tag]
$ cat dockerfile/Dockerfile-kube-scheduler
FROM scratch
COPY _output/local/bin/linux/amd64/kube-scheduler /
CMD ["/kube-scheduler"]
kubeadmというバイナリ配信の場合、直接コンパイルしてnexusに転送し、drone deployイベントでkubeadmをコンパイルするかどうかを選択します.
build_kubeadm:
image: fanux/kubernetes-build:1.12.2-beta.3
commands:
- make all WHAT=cmd/kube-kubeadm GOFLAGS=-v
- curl -v -u container:container --upload-file kubeadm http://172.16.59.153:8081/repository/kubernetes/kubeadm/
when:
event: deployment
enviroment: kubeadm
ダイレクトgo buildの大きな穴
buildが完了したkubeadmバイナリは使用できないことがわかりました.buildで選択したベースミラーの問題かもしれません.コードを生成しなかった問題かもしれません.
[signal SIGSEGV: segmentation violation code=0x1 addr=0x63 pc=0x7f2b7f5f057c]
runtime stack:
runtime.throw(0x17c74a8, 0x2a)
/usr/local/go/src/runtime/panic.go:608 +0x72
runtime.sigpanic()
/usr/local/go/src/runtime/signal_unix.go:374 +0x2f2
あとでCDのセットを追加します
このようにschedulerコードをコンパイルするのは約40秒ぐらいで、vendorがソフト接続できるように十数秒節約できます.
スケジューラcache
Cacheステータスマシン
+-------------------------------------------+ +----+
| Add | | |
| | | | Update
+ Assume Add v v |
Initial +--------> Assumed +------------+---> Added Expired +----> Deleted
Cache実装
type schedulerCache struct {
stop
ここには、基本スケジューリングに必要なすべての情報が格納されています.
AddPodインタフェースを例にとると、本質的には傍受されたpodをcacheのmapに入れることです.
cache.addPod(pod)
ps := &podState{
pod: pod,
}
cache.podStates[key] = ps
Node Treeノード情報には、次のような構造体が保存されます.
type NodeTree struct {
tree map[string]*nodeArray // a map from zone (region-zone) to an array of nodes in the zone.
zones []string // a list of all the zones in the tree (keys)
zoneIndex int
NumNodes int
mu sync.RWMutex
}
Cache実行時に期限切れのassume podをループクリーンアップ
func (cache *schedulerCache) run() {
go wait.Until(cache.cleanupExpiredAssumedPods, cache.period, cache.stop)
}
scheduler
schedulerの中で最も重要な2つのもの:cacheとスケジューリングアルゴリズム
type Scheduler struct {
config *Config -------> SchedulerCache
|
+---> Algorithm
}
cacheが更新されると、スケジューラはpodをスケジューリングします.
func (sched *Scheduler) Run() {
if !sched.config.WaitForCacheSync() {
return
}
go wait.Until(sched.scheduleOne, 0, sched.config.StopEverything)
}
コアロジックが来ました:
+-------------+
| pod |
+-------------+
|
+-----------------------------------------------------------------------------------+
| pod DeletionTimestamp , kubelet pod |
+-----------------------------------------------------------------------------------+
|
+-----------------------------------------+
| suggestedHost, |
+-----------------------------------------+
|_____________ , swarm
|
+--------------------------------------------------------------------------------+
| node , cache pod node , assume pod |
| volumes |
| :err = sched.assume(assumedPod, suggestedHost) pod node |
+--------------------------------------------------------------------------------+
|
+---------------------------+
| bind pod node |
| bind volume |
| bind pod |
+---------------------------+
|
+----------------+
| metric |
+----------------+
bindアクション:
err := sched.bind(assumedPod, &v1.Binding{
ObjectMeta: metav1.ObjectMeta{Namespace: assumedPod.Namespace, Name: assumedPod.Name, UID: assumedPod.UID},
Target: v1.ObjectReference{
Kind: "Node",
Name: suggestedHost,
},
})
先にbind podに行って、それからcache bindに終わりを教えます
err := sched.config.GetBinder(assumed).Bind(b)
if err := sched.config.SchedulerCache.FinishBinding(assumed);
bindプロセス
+----------------+
| GetBinder.Bind
+----------------+
|
+-------------------------------------+
| cache bind FinishBinding
+-------------------------------------+
|
+-----------------------------------------------------+
| ForgetPod, pod BindingRejected
+-----------------------------------------------------+
bind実装
最終的にapiserver bindインタフェースが呼び出されます.
func (b *binder) Bind(binding *v1.Binding) error {
glog.V(3).Infof("Attempting to bind %v to %v", binding.Name, binding.Target.Name)
return b.Client.CoreV1().Pods(binding.Namespace).Bind(binding)
}
スヶジューリングアルゴリズム
▾ algorithm/
▸ predicates/
▸ priorities/
今最も重要なのはノード選択の実装です
suggestedHost, err := sched.schedule(pod)
つまり、スケジューリングアルゴリズムの実装:
type ScheduleAlgorithm interface {
// pod ,
Schedule(*v1.Pod, NodeLister) (selectedMachine string, err error)
//
Preempt(*v1.Pod, NodeLister, error) (selectedNode *v1.Node, preemptedPods []*v1.Pod, cleanupNominatedPods []*v1.Pod, err error)
// ,
Predicates() map[string]FitPredicate
| pod,
+-------type FitPredicate func(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []PredicateFailureReason, error)
// , map reduce
Prioritizers() []PriorityConfig
|____________PriorityMapFunction
|____________PriorityReduceFunction map node
|____________PriorityFunction
}
スケジューリングアルゴリズムは、次の2つの方法で生成できます.
priorityConfigs, err := c.GetPriorityFunctionConfigs(priorityKeys)
priorityMetaProducer, err := c.GetPriorityMetadataProducer()
predicateMetaProducer, err := c.GetPredicateMetadataProducer()
|
algo := core.NewGenericScheduler( |
c.schedulerCache, |
c.equivalencePodCache, V
c.podQueue,
predicateFuncs, ============>
predicateMetaProducer,
priorityConfigs,
priorityMetaProducer,
extenders,
c.volumeBinder,
c.pVCLister,
c.alwaysCheckAllPredicates,
c.disablePreemption,
c.percentageOfNodesToScore,
)
type genericScheduler struct {
cache schedulercache.Cache
equivalenceCache *equivalence.Cache
schedulingQueue SchedulingQueue
predicates map[string]algorithm.FitPredicate
priorityMetaProducer algorithm.PriorityMetadataProducer
predicateMetaProducer algorithm.PredicateMetadataProducer
prioritizers []algorithm.PriorityConfig
extenders []algorithm.SchedulerExtender
lastNodeIndex uint64
alwaysCheckAllPredicates bool
cachedNodeInfoMap map[string]*schedulercache.NodeInfo
volumeBinder *volumebinder.VolumeBinder
pvcLister corelisters.PersistentVolumeClaimLister
disablePreemption bool
percentageOfNodesToScore int32
}
このschedulerはScheduleAlgorithmで定義されたインタフェースを実現した.
Scheduleプロセス:
+------------------------------------+
| trace , pod |
+------------------------------------+
|
+-----------------------------------------------+
| pod , delete timestamp |
+-----------------------------------------------+
|
+----------------------------------------+
| node , cache node info map |
+----------------------------------------+
|
+----------------------------------------------+
| , |
+----------------------------------------------+
|
+----------------------------------------------------------+
| , |
| , , |
| |
+----------------------------------------------------------+
|
+------------------------------------+
| |
+------------------------------------+
せんたく
主に二つに分ける
podFitOnNode:このノードがこのpodスケジューリングに適しているかどうかを判断する
ここには小さな知識が挿入されています.スケジューラにはEcacheがあります.
Equivalence Classは現在、Kubernetes SchedulerでPredicateを加速させ、Schedulerのスループット性能を向上させるために使用されています.Kubernetes schedulerはEquivalence Cacheのデータをタイムリーに維持しており、場合によってはdelete node、bind podなどのイベントが発生すると、すぐにinvalid関連のEquivalence Cacheのキャッシュデータが必要になります.
1つのEquivalence Classは、同じRequirementsとConstraintsを持つPodsの関連情報のセットを定義するために使用され、SchedulerがPredicateフェーズを行う場合、Equivalence Classの1つのPodに対してPredicateを行い、Predicateの結果をEquivalence Cacheに配置してEquivalence Classの他のPods(Equivalent Podsとなる)結果を再利用します.通常のPredicateプロセスは、Equivalence Cacheに再利用可能なPredicate Resultがない場合にのみ実行されます.
ecacheという後続は深く議論することができ、本稿ではコアアーキテクチャとプロセスに注目する.
すべての予選関数を1回実行するのは簡単です
predicates.Ordering()
if predicate, exist := predicateFuncs[predicateKey]; exist {
fit, reasons, err = predicate(pod, metaToUse, nodeInfoToUse)
順序は次のとおりです.
predicatesOrdering = []string{CheckNodeConditionPred, CheckNodeUnschedulablePred,
GeneralPred, HostNamePred, PodFitsHostPortsPred,
MatchNodeSelectorPred, PodFitsResourcesPred, NoDiskConflictPred,
PodToleratesNodeTaintsPred, PodToleratesNodeNoExecuteTaintsPred, CheckNodeLabelPresencePred,
CheckServiceAffinityPred, MaxEBSVolumeCountPred, MaxGCEPDVolumeCountPred, MaxCSIVolumeCountPred,
MaxAzureDiskVolumeCountPred, CheckVolumeBindingPred, NoVolumeZoneConflictPred,
CheckNodeMemoryPressurePred, CheckNodePIDPressurePred, CheckNodeDiskPressurePred, MatchInterPodAffinityPred}
これらの予選関数はmapに存在し、keyはstringであり、valueは予選関数であり、mapを登録する論理を振り返る.
predicateFuncs, err := c.GetPredicates(predicateKeys)
pkg/scheduler/algorithmprovider/defaults/defaults.goには、次のような関数が登録されています.
factory.RegisterFitPredicate(predicates.NoDiskConflictPred, predicates.NoDiskConflict),
factory.RegisterFitPredicate(predicates.GeneralPred, predicates.GeneralPredicates),
factory.RegisterFitPredicate(predicates.CheckNodeMemoryPressurePred, predicates.CheckNodeMemoryPressurePredicate),
factory.RegisterFitPredicate(predicates.CheckNodeDiskPressurePred, predicates.CheckNodeDiskPressurePredicate),
factory.RegisterFitPredicate(predicates.CheckNodePIDPressurePred, predicates.CheckNodePIDPressurePredicate),
そしてinit関数で登録ロジックを直接呼び出します
好ましい
PrioritizeNodesは、3つのステップに分けられることが好ましい.
factory.RegisterPriorityFunction2("LeastRequestedPriority", priorities.LeastRequestedPriorityMap, nil, 1),
// Prioritizes nodes to help achieve balanced resource usage
factory.RegisterPriorityFunction2("BalancedResourceAllocation", priorities.BalancedResourceAllocationMap, nil, 1),
ここで登録する時に2つ登録して、1つのmap関数1つのreduce関数、もっと良い理解のmapreduceのために、1つの実現を見に行きます
factory.RegisterPriorityFunction2("NodeAffinityPriority", priorities.CalculateNodeAffinityPriorityMap, priorities.CalculateNodeAffinityPriorityReduce, 1)
node Affinity map reduce
mapコアロジック、比較的に理解しやすい:
,
count += preferredSchedulingTerm.Weight
return schedulerapi.HostPriority{
Host: node.Name,
Score: int(count), #
}, nil
reduce:1つのノードは多くのmapを歩き、各mapはnode affinityが1つ生成され、pod affinityがもう1つ生成されるので、nodeとスコアは1対多の関係です.
reverseの論理を削除(スコアが高いほど優先度が低い)
var maxCount int
for i := range result {
if result[i].Score > maxCount {
maxCount = result[i].Score #
}
}
for i := range result {
score := result[i].Score
score = maxPriority * score / maxCount # maxPriority = 10, ;
result[i].Score = score
}
ここで正規化処理をすると点数が[0,maxPriority]の間になります
for i := range priorityConfigs {
if priorityConfigs[i].Function != nil {
continue
}
results[i][index], err = priorityConfigs[i].Map(pod, meta, nodeInfo)
if err != nil {
appendError(err)
results[i][index].Host = nodes[index].Name
}
}
err := config.Reduce(pod, meta, nodeNameToInfo, results[index]);
ここにresultsがあります.理解にとって重要な2次元配列です.
xxx
node1
node2
node3
nodeaffinity
1点
2点
1点
pod affinity
1点
3点
6点
...
...
...
...
このようにreduceで1行をとると,実際にはすべてのノードの得点を処理する.
result[i].Score += results[j][i].Score * priorityConfigs[j].Weight ( )
reduceが最終的にこのノードの得点を完了すると、このノードの各得点にその重みを乗じた和に等しくなり、最後に最高点(1次元が0緯になる)をソートします.
スケジューリングキューSchedulingQueue
scheduler構成には
NextPod
メソッドがあり、podを取得し、スケジューリングを行います.pod := sched.config.NextPod()
プロファイルはここで初期化されます.
pkg/scheduler/factory/factory.go
NextPod: func() *v1.Pod {
return c.getNextPod()
},
func (c *configFactory) getNextPod() *v1.Pod {
pod, err := c.podQueue.Pop()
if err == nil {
return pod
}
...
}
キューインタフェース:
type SchedulingQueue interface {
Add(pod *v1.Pod) error
AddIfNotPresent(pod *v1.Pod) error
AddUnschedulableIfNotPresent(pod *v1.Pod) error
Pop() (*v1.Pod, error)
Update(oldPod, newPod *v1.Pod) error
Delete(pod *v1.Pod) error
MoveAllToActiveQueue()
AssignedPodAdded(pod *v1.Pod)
AssignedPodUpdated(pod *v1.Pod)
WaitingPodsForNode(nodeName string) []*v1.Pod
WaitingPods() []*v1.Pod
}
優先キューとFIFOの2つのインプリメンテーションが与えられました.
func NewSchedulingQueue() SchedulingQueue {
if util.PodPriorityEnabled() {
return NewPriorityQueue() # ,
}
return NewFIFO() #
}
キューの実装は簡単で、深く分析しないで、もっと重要なのはキュー、スケジューラ、cacheの関係に注目することです.
AddFunc: c.addPodToCache,
UpdateFunc: c.updatePodInCache,
DeleteFunc: c.deletePodFromCache,
| informer , pod cache
V
if err := c.schedulerCache.AddPod(pod); err != nil {
glog.Errorf("scheduler cache AddPod failed: %v", err)
}
c.podQueue.AssignedPodAdded(pod)
+------------+ ADD +-------------+ POP +-----------+
| informer |------>| sche Queue |------->| scheduler |
+------------+ | +-------------+ +----^------+
+-->+-------------+ |
| sche cache |
Extender
スケジューラ拡張
カスタマイズスケジューラには3つの方法があります.
現在、3つ目の資料は非常に少なく、多くの詳細はコードの中で答えを見つける必要があり、問題を持ってコードを見ると効果的です.
Extenderインタフェース
+----------------------------------+ +----------+
| kube-scheduler -> extender client|------>| extender | ( , )
+----------------------------------+ +----------+
このインタフェースはkube-schedulerで実装されています.HTTPextenderの実装について説明します.
type SchedulerExtender interface {
// , pod ,
Filter(pod *v1.Pod,
nodes []*v1.Node, nodeNameToInfo map[string]*schedulercache.NodeInfo,
) (filteredNodes []*v1.Node, failedNodesMap schedulerapi.FailedNodesMap, err error)
// ,
Prioritize(pod *v1.Pod, nodes []*v1.Node) (hostPriorities *schedulerapi.HostPriorityList, weight int, err error)
// Bind extender
Bind(binding *v1.Binding) error
// IsBinder returns whether this extender is configured for the Bind method.
IsBinder() bool
// pod
IsInterested(pod *v1.Pod) bool
// ProcessPreemption returns nodes with their victim pods processed by extender based on
// given:
// 1. Pod to schedule
// 2. Candidate nodes and victim pods (nodeToVictims) generated by previous scheduling process.
// 3. nodeNameToInfo to restore v1.Node from node name if extender cache is enabled.
// The possible changes made by extender may include:
// 1. Subset of given candidate nodes after preemption phase of extender.
// 2. A different set of victim pod for every given candidate node after preemption phase of extender.
// , TODO
ProcessPreemption(
pod *v1.Pod,
nodeToVictims map[*v1.Node]*schedulerapi.Victims,
nodeNameToInfo map[string]*schedulercache.NodeInfo,
) (map[*v1.Node]*schedulerapi.Victims, error)
// ,
SupportsPreemption() bool
// extender , extender
IsIgnorable() bool
}
HTTPextenderが公式に実現されました.
type HTTPExtender struct {
extenderURL string
preemptVerb string
filterVerb string # RUL
prioritizeVerb string # RUL
bindVerb string
weight int
client *http.Client
nodeCacheCapable bool
managedResources sets.String
ignorable bool
}
その予選と好ましい論理を見てください.
args = &schedulerapi.ExtenderArgs{ # pod, ,
Pod: pod,
Nodes: nodeList,
NodeNames: nodeNames,
}
if err := h.send(h.filterVerb, args, &result); err != nil { # http extender( httpserver),
return nil, nil, err
}
HTTPExtender構成パラメータはどこから
scheduler extender構成:
NamespaceSystem string = "kube-system"
SchedulerDefaultLockObjectNamespace string = metav1.NamespaceSystem
// SchedulerPolicyConfigMapKey defines the key of the element in the
// scheduler's policy ConfigMap that contains scheduler's policy config.
SchedulerPolicyConfigMapKey = "policy.cfg"
まとめ
スケジューラのコードはよく書けています.kube-proxyよりずっとよくなっています.拡張性もまあまあですが、目測スケジューラは大きな再構築に直面します.現段階では、スケジューラが深く学習したバッチタスクのサポートはよくありません.one by oneスケジューリングのこのような設定はプロジェクト全体のアーキテクチャに関係しています.より優れたスケジューリングを優雅にサポートするには、再構築は逃げられないだろう.
スキャンコード注目sealyun
検討可加QQ群:98488045