<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
kube-scheduler 作為 k8s 的排程器,就好比人的大腦,將行動指定傳遞到手腳等器官,進而執行對應的動作,對於 kube-scheduler 則是將 Pod 分配(排程)到叢集內的各個節點,進而建立容器執行程序,對於k8s來說至關重要。
為了深入學習 kube-scheduler,本系從原始碼和實戰角度深度學 習kube-scheduler,該系列一共分6篇文章,如下:
本篇先熟悉 kube-scheduler 的整體架構設計,看清全域性,做到心裡有數,在後面的篇章再庖丁解牛,一步步挖掘細節。
我們先看看官方是怎麼描述 scheduler 的
The Kubernetes scheduler is a control plane process which assigns Pods to Nodes. The scheduler determines which Nodes are valid placements for each Pod in the scheduling queue according to constraints and available resources. The scheduler then ranks each valid Node and binds the Pod to a suitable Node. Multiple different schedulers may be used within a cluster; kube-scheduler is the reference implementation.
k8s scheduler 是一個控制面程序,它分配 Pod 到 Nodes。根據限制和可用資源,scheduler 確定哪些節點符合排程佇列裡的 Pod。然後對這些符合的節點進行打分,然後把Pod繫結到合適的節點上。一個叢集內可以存在多個scheduler,而 kube-scheduler 是一個參考實現。
這段話簡單概括下就是:當有 pod 需要 scheduler 排程的時候, scheduler 會根據一些列規則挑選出最符合的節點,然後將Pod繫結到這個Node。
所以 scheduler 主要要做的事就是根據 Nodes 當前狀態和 pod 對資源的需求,按照順序執行一系列指定的演演算法來挑選出一個Node。
我們可以通過下圖,對上述說的列演演算法有一個初步的認識,後面我們在展開詳細說
如圖中所示,圖中每一個綠色箭頭在k8s中叫擴充套件點(extension point),從圖中可以看到一共有10個擴充套件點,我們可以分個類,如下圖
每一個擴充套件點可以執行一個或多個演演算法,在k8s中把這種演演算法叫做外掛(Plugin)。顧名思義,擴充套件點就是可以擴充套件的,所以使用者可以開發自己的外掛嵌入擴充套件點中,我們既可以將自己開發的外掛和系統預設外掛同時執行,也可以關閉系統自帶的外掛只執行自己的外掛,這部分在後面開發實踐階段會詳細介紹。
sort 型別的擴充套件點只有一個:sort,而且這個擴充套件點下面只能有一個外掛可以執行,如果同時 enable 多個 sort 外掛,scheduler 會退出。
在 k8s 中,待排程的 Pod 會放在一個叫 activeQ 佇列中,這個佇列是一個基於堆實現的優先佇列(priority queue),為什麼是優先佇列呢?
因為你可以對 Pod 設定優先順序,將你認為需要優先排程的 Pod 優先順序調大,如果佇列裡有多個 Pod 需要排程,就會出現搶佔現象,優先順序高的 Pod 會移動到佇列頭部,scheduler 會優先取出這個 Pod 進行排程。那麼這個優先順序怎麼設定呢?有兩種方法:
如使用 k8s 預設 sort 外掛,則可以給 Pod (deployment等方式) 設定 PriorityClass(建立 PriorityClass 資源並設定deployment);如果你的所有 Pod 都沒有設定 PriorityClass,那麼會根據 Pod 建立的時間先後順序進行排程。PriorityClass 和 Pod 建立時間是系統預設的排序依據。
實現自己的 sort 外掛客製化排序演演算法,根據該排序演演算法實現搶佔,例如你可以將包含特定標籤的 Pod 移到隊頭。後面會詳細講述如何實現自己的外掛來改變系統預設行為。
filter 型別擴充套件點有3個:prefilter,filter,postfilter。各個擴充套件點有多個外掛組成的外掛集合根據 Pod 的設定共同過濾 Node,如下圖:
preFilter 擴充套件點主要有兩個作用,一是為後面的擴充套件點計算 Pod 的一些資訊,例如 preFilter 階段的 NodeResourcesFit 演演算法不會去判斷節點合適與否,而是計算這個Pod需要多少資源,然後儲存這個資訊,在 filter 擴充套件點的 NodeResourcesFit 外掛中會把之前算出來的資源拿出來做判斷;另外一個作用就是過濾一些明顯不符合要求的節點,這樣可以減少後續擴充套件點外掛一些無意義的計算。
filter 擴充套件點主要的作用就是根據各個外掛定義的順序依次執行,篩選出符合 Pod 的節點,這些外掛會在 preFilter 後留下的每個 Node 上執行,如果能夠通過所有外掛的”考驗“,那麼這個節點就留下來了。如果某個外掛判斷這個節點不符合,那麼剩餘的所有外掛都不會對該節點做計算。
postFilter 擴充套件點只會在filter結束後沒有任何 Node 符合 Pod 的情況下才會執行,否則這個擴充套件點會被跳過。我們可以看到,這個擴充套件點在系統只有一個預設的外掛, 這個預設外掛的作用遍歷這個 Pod 所在的名稱空間下面的所有 Pod,查詢是否有可以被搶佔的 Pod,如果有的話選出一個最合適的 Pod 然後 delete 掉這個Pod,並在待排程的 Pod 的 status 欄位下面設定 nominateNode 為這個被搶佔的 Pod。
這個型別的擴充套件點的作用就是為上面 filter 擴充套件點篩選出來的所有 Node 進行打分,挑選出一個得分最高(最合適的),這個 Node 就是 Pod 要被排程上去的節點。這個這個型別的擴充套件有 preScore 和 score 兩個,前者是為後者打分做前置準備的,preScore 的各個外掛會計算一些資訊供 score使用,這個和 prefilter 比較類似。
reserve 型別擴充套件點系統預設只實現了一個外掛:VolumeBinding,更新 Pod 宣告的 PVC 和對應的 PV快取資訊,表示該 PV 已經被 Pod佔用。
該型別擴充套件點,系統沒有實現預設的外掛,我們就不說了
該型別擴充套件點有三個擴充套件點:preBind、bind和postBind。
preBind 擴充套件點有一個內建外掛 VolumeBinding,這個外掛會呼叫 pv controller 完成繫結操作,在前面的 reserve 也有同名外掛,這個外掛只是更新了本地快取中的資訊,沒有實際做繫結。
bind 擴充套件點也只有一個預設的內建外掛:DefaultBinder,這個外掛只做了一件很簡單的事,將 Pod.Spec.nodeName 更新為選出來的那個 node。後面的“故事”就是 kubelet 監聽到了 nodeName=Kubelet所在nodename,然後開始建立Pod(容器)。 到了這裡,整個排程流程就結束了。
從文章開頭的那張圖中我們能夠看到 scheduler 分兩個 cycle: scheduling cycle 和 binding cycle。區分這兩個 cycle 的原因是為了提升排程效率。從上面的描述中我們能夠看到,在 bind cycle 中,會有兩次外部 api 呼叫:呼叫 pv controller 繫結 pv 和呼叫 kube-apiserver 繫結 Node,api呼叫是耗時的,所以將 bind 擴充套件點拆分出來,另起一個 go 協程進行 bind。而在 scheduling cycle 中為了提升效率的一個重要原則就是 Pod、 Node 等資訊從本地快取中獲取,而具體的實現原理就是先使用 list 獲取所有 Node、Pod 的資訊,然後再 watch 他們的變化更新本地快取。
上面我們主要從擴充套件點和外掛方面說明了 scheduler 的架構。下面我們從原始碼架構說說 scheduler 是怎麼工作。
我們先來看看 kube-scheduler 中的幾個關鍵元件
schedulerCache 快取 Pod,Node 等資訊,各個擴充套件點的外掛在計算時所需要的 Node 和 Pod 資訊都是從 schedulerCache 獲取。schedulerCache 具體在內部是一個實現了 Cache 介面的 結構體 cacheImpl,我們看下這個結構體:
type cacheImpl struct { stop <-chan struct{} ttl time.Duration period time.Duration // This mutex guards all fields within this cache struct. mu sync.RWMutex // a set of assumed pod keys. // The key could further be used to get an entry in podStates. assumedPods sets.String // a map from pod key to podState. podStates map[string]*podState nodes map[string]*nodeInfoListItem // headNode points to the most recently updated NodeInfo in "nodes". It is the // head of the linked list. headNode *nodeInfoListItem nodeTree *nodeTree // A map from image name to its imageState. imageStates map[string]*imageState }
說他是快取,從這個結構體可以看到,實際上就是map,用來儲存 Pod 和 Node 的資訊。那麼這些資料是怎麼來的呢?我們來看下一個元件informer
informer 是 client-go 提供的能力,他的作用是監聽目標資源的變化,同步到本地快取。幾乎,在 k8s 的所有元件包括 controller-manager,kube-proxy,kubelet 等都使用了 informer 來監聽 kube-apiserver 來獲取資源的變化。舉個例子,比如你執行了 kubectl edit 命令改變了一個 deployment 的映象版本,k8s 是怎麼感知到這個變化,進一步做 Pod 的重建的工作的呢?就是 kube-scheduler 使用了 informer 來監聽 Pod 的變化實現的。
具體來說,kube-scheduler 使用 informer 監聽了:Node, Pod, CSINode, CSIDriver, CSIStorageCapacity, PersistentVolume, PersistentVolumeClaim, StorageClass。監聽 Node,Pod 我們可以理解,那麼為什麼要監聽後面那些資源呢?後面的那些資源都是跟儲存有關,在 preFilter 和 filter 擴充套件點的外掛裡面有 Volumebinding 這麼一個外掛,是檢查系統當前是否能夠滿足 Pod 宣告的 PVC,如果不能滿足,那麼只能把 Pod 放入 unscheduleableQ 裡。但是,後續如果系統如果可以滿足 Pod 對儲存的需要了,這個 Pod 需要第一時間能夠被建立出來,所以系統必須要能夠實時感知到系統 PVC 等資源的變化及時將 unscheduleableQ 裡面排程失敗的 Pod 進行重新排程。這就是 informer 存在的意義了。具體的 informer 的實現原理可以參考這篇文章。
schedulerQueue包含三個佇列:activeQ, podBackoffQ,unschedulablePods。
activeQ 是一個優先佇列,基於堆實現,用於存放待排程的 Pod,優先順序高的會放在佇列頭部,優先被排程。該佇列存放的 Pod 可能的情況有:剛建立未被排程的Pod;backOffPod 佇列中轉移過來的Pod;unschedule 佇列裡轉移過來的 Pod。
podBackoffQ 也是一個優先佇列,用於存放那些異常的Pod,這種 Pod 需要等待一定的時間才能夠被再次排程,會有協程定期去讀取這個佇列,然後加入到 activeQ 佇列然後重新排程。
unschedulablePods 嚴格上來說不屬於佇列,用於存放排程失敗的 Pod。這個佇列也會有協程定期(預設30s)去讀取,然後判斷當前時間距離上次排程時間的差是否超過5Min,如果超過這個時間則把 Pod 移動到 activeQ 重新排程。
func (p *PriorityQueue) Run() { go wait.Until(p.flushBackoffQCompleted, 1.0*time.Second, p.stop) go wait.Until(p.flushUnschedulablePodsLeftover, 30*time.Second, p.stop) }
說完這幾個元件,我們再來看看,當一個新的 Pod 建立出來後,這個流程是怎麼走的
以上就是 kube-scheduler 的基本原理。
在後面的文章中,我們會繼續聊聊 kube-scheduler 是怎麼初始化出來的,要想開發一個自己的外掛要做哪些事,更多關於Go kube-scheduler架構的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45