1. 程式人生 > >scheduler的原始碼分析_Kubernetes中文社群

scheduler的原始碼分析_Kubernetes中文社群

很長時間沒有寫文章,一直在啃kubernetes文件,本來立志一定要讀完所有的文件。還有它的最佳實踐openshift的文件。但目前為止,我並沒有讀完kubernetes的文件。當前,我們有需求需要客製化kubernetes的排程函式,所以開始研究kube-scheduler的程式碼。

kube-scheduler的程式碼的風格和邏輯對於Gophers並不陌生。權威的作者這樣評價kubernetes的原始碼:程式碼簡潔,設計巧妙,程式邏輯分解得恰到好處,每個元件各司其職,從而化繁為簡,主體流程清晰直觀,猶如行雲流水,一氣呵成。(雖然v.1.8.1已經和書中v1.3的程式碼發生了不小的改變。)總之,kubernetes的原始碼值得反覆閱讀學習,主要是每個版本程式碼都不一樣,變化一直在進行中。

kubernetes tag v.1.8.1
kube-scheduler的程式碼路徑為:plugin/

入口程式:plugin/cmd/kube-scheduler/scheduler.go main()

  1. 建立NewSchedulerServer和啟動排程服務;
  2. componentconfig.KubeSchedulerConfiguration{}定義了kube-scheduler的引數資訊;

啟動程式:plugin/cmd/kube-scheduler/app/server.go Run()

  1. 建立apiserver客戶端–通過REST方式訪問APIserver提供的API服務,用來watch
    pod和node,並呼叫apiserver bind介面完成node和pod的Bind操作;
  2. 建立eventBroadcaster物件–傳送event到logging函式,傳送event到eventSink,同時EventRecorder記錄event source;
  3. 建立sharedInformerFactory物件,並建立PodInformer物件,PodInformer用於watch/list non-terminal pods並快取;
  4. 建立schedulerConfigurator物件
  5. 建立genericScheduler物件(介面Scheduler) ,genericScheduler物件的建立過程:
    a. 建立schedulerConfigurator物件,它包含ConfigFactory物件(介面Configurator) plugin/cmd/kube-scheduler/app/configurator.gob. 呼叫schedulerConfigurator物件的create()方法建立Scheduler物件;genericScheduler物件是由ConfigFactory物件(Configurator是介面)的createFromProvider()方法建立的plugin/cmd/kube-scheduler/pkg/scheduler/factory/factory.goc. 建立Scheduler需要如下Informer引數:nodeInformer、pvInformer、pvcInformer、rcInformer、rsInformer、statefulsetInformer、serviceInformer ;
  6. 執行http Server–提供必要的效能分析(profiling)和效能指標度量(Metrics),Handler包括/debug/pprof/和/metrics;
  7. 啟動informerFactory.start() ,開始執行Informer,進行快取;
  8. 執行排程程式;
  9. 建立Leaderelection物件,並啟動leaderElector.Run() — 建立resourcelock對一些資源上鎖。同時,值得一提,controller-manager和kube-scheduler兩個元件可以配置跟本機的APIServer通訊,也可以不是。在高可用部署情況下,controller-manager和kube-scheduler兩個元件,存在選舉機制,為了保證選舉成功,需要奇數節點部署元件,而當前工作元件只有一個,用於更新叢集狀態,並與其他節點元件同步資訊。

SharedInformers模式設計同時用在k8s的”Controller”中,下面是一段關於SharedInformers模式設計的英文介紹:(摘自https://github.com/kubernetes/ … rs.md
Use SharedInformers. SharedInformers provide hooks to receive notifications of adds, updates, and deletes for a particular resource. They also provide convenience functions for accessing shared caches and determining when a cache is primed.
SharedInformers提供勾子機制,獲得特定資源的新增、更新、刪除通知。並提供函式更新快取,啟動執行。簡而言之kube-scheduler的”informer”負責:watch/list non-terminal pods, 快取,並從podQueue中獲得NextPod,執行排程;

排程程式:plugin/pkg/scheduler/scheduler.go Run()
1. 等待快取更新完成;
2. 執行排程流程;

排程流程:plugin/pkg/scheduler/scheduler.go scheduleOne()
1.從podQueue快取中獲得一個Pod;
2. 獲得一個suggestedHost,如果獲得失敗將呼叫搶佔邏輯sched.preempt(),記錄演算法延遲的度量metrics.SchedulingAlgorithmLatency;–獲得suggestedHost是同步操作;
3. Pod將標註為assumedPod;此時Pod並沒有被成功排程;
4. 繫結(bind) Pod到suggestedHost,記錄排程延遲的度量metrics.E2eSchedulingLatency;–繫結操作是非同步操作;

排程邏輯:plugin/pkg/scheduler/scheduler.go Schedule()
1. 根據排程策略演算法確定一個suggestedHost;

排程演算法函式
1. 介面類plugin/pkg/scheduler/algorithm/scheduler_interface.go, 預設使用plugin/pkg/scheduler/core/generic_scheduler.go
2. 排程演算法函式支援plugin模式plugin/pkg/scheduler/algorithmprovider/plugins.go,scheduler的commandLine引數AlgorithmProvider可以指定排程演算法函式;預設使用defaultProvider, defaultPredicates(), defaultPriorities() plugin/pkg/scheduler/algorithmprovider/defaults/default.go;同時,scheduler的commandLine引數PolicyConfigFile,可以載入自定義的排程策略檔案。如:openshift中,/etc/origin/master/scheduler.json定義了排程策略檔案。(參考資訊:https://docs.openshift.com/con … .html
3. FitPredicates:k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/predicates
4. PrioritiesFunc:k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/priorities
5. 排程流程plugin/pkg/scheduler/core/generic_scheduler.go schedule(),排程流程圖如下:(摘自kubernetes排程詳解:http://dockone.io/article/2885

512961a5c5b56a1f8650e5ea83690ad0.png!thumbnail_.png

繫結邏輯:plugin/pkg/scheduler/scheduler.go bind()
1. 繫結介面Binder plugin/pkg/scheduler/scheduler.go
2. 更新cache中assumedPod為expired SchedulerCache.FinishBinding(),介面/實現: plugin/pkg/scheduler/schedulercache/interface.go;plugin/pkg/scheduler/schedulercache/cache.go;
3. 記錄繫結延遲的度量metrics.BindingLatency;
4. 記錄繫結事件;

閱讀程式碼的建議
1. 讀文件,k8s的文件寫得非常好,如果文件沒有提及的,讀程式碼;
2. 要帶著問題探索性的閱讀程式碼,比如:error handling是如何處理的?如果pod沒有被正確的排程會發生什麼?

排程的效能
k8s SIG Scale Group對k8s排程服務進行了效能測試,得到的資料:1000 pods跑在1000個節點上,排程延遲為23s,排程程式的吞吐量是51 pods/秒;
https://docs.google.com/presen … _2866