最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言開發(fā)kube-scheduler整體架構(gòu)深度剖析

 更新時間:2023年04月23日 11:25:44   作者:俯仰之間  
這篇文章主要為大家介紹了Go語言開發(fā)kube-scheduler整體架構(gòu)深度剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

k8s 的調(diào)度器 kube-scheduler

kube-scheduler 作為 k8s 的調(diào)度器,就好比人的大腦,將行動指定傳遞到手腳等器官,進(jìn)而執(zhí)行對應(yīng)的動作,對于 kube-scheduler 則是將 Pod 分配(調(diào)度)到集群內(nèi)的各個節(jié)點,進(jìn)而創(chuàng)建容器運行進(jìn)程,對于k8s來說至關(guān)重要。

為了深入學(xué)習(xí) kube-scheduler,本系從源碼和實戰(zhàn)角度深度學(xué) 習(xí)kube-scheduler,該系列一共分6篇文章,如下:

  • kube-scheduler 整體架構(gòu)
  • 初始化一個 scheduler
  • 一個 Pod 是如何被調(diào)度的
  • 如何開發(fā)一個屬于自己的scheduler插件
  • 開發(fā)一個 prefilter 擴(kuò)展點的插件
  • 開發(fā)一個 socre 擴(kuò)展點的插件

本篇先熟悉 kube-scheduler 的整體架構(gòu)設(shè)計,看清全局,做到心里有數(shù),在后面的篇章再庖丁解牛,一步步挖掘細(xì)節(jié)。

官方描述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 是一個控制面進(jìn)程,它分配 Pod 到 Nodes。根據(jù)限制和可用資源,scheduler 確定哪些節(jié)點符合調(diào)度隊列里的 Pod。然后對這些符合的節(jié)點進(jìn)行打分,然后把Pod綁定到合適的節(jié)點上。一個集群內(nèi)可以存在多個scheduler,而 kube-scheduler 是一個參考實現(xiàn)。

這段話簡單概括下就是:當(dāng)有 pod 需要 scheduler 調(diào)度的時候, scheduler 會根據(jù)一些列規(guī)則挑選出最符合的節(jié)點,然后將Pod綁定到這個Node。

所以 scheduler 主要要做的事就是根據(jù) Nodes 當(dāng)前狀態(tài)和 pod 對資源的需求,按照順序運行一系列指定的算法來挑選出一個Node。

我們可以通過下圖,對上述說的列算法有一個初步的認(rèn)識,后面我們在展開詳細(xì)說

如圖中所示,圖中每一個綠色箭頭在k8s中叫擴(kuò)展點(extension point),從圖中可以看到一共有10個擴(kuò)展點,我們可以分個類,如下圖

每一個擴(kuò)展點可以運行一個或多個算法,在k8s中把這種算法叫做插件(Plugin)。顧名思義,擴(kuò)展點就是可以擴(kuò)展的,所以用戶可以開發(fā)自己的插件嵌入擴(kuò)展點中,我們既可以將自己開發(fā)的插件和系統(tǒng)默認(rèn)插件同時運行,也可以關(guān)閉系統(tǒng)自帶的插件只運行自己的插件,這部分在后面開發(fā)實踐階段會詳細(xì)介紹。

各個類型擴(kuò)展點

  • sort

sort 類型的擴(kuò)展點只有一個:sort,而且這個擴(kuò)展點下面只能有一個插件可以運行,如果同時 enable 多個 sort 插件,scheduler 會退出。

在 k8s 中,待調(diào)度的 Pod 會放在一個叫 activeQ 隊列中,這個隊列是一個基于堆實現(xiàn)的優(yōu)先隊列(priority queue),為什么是優(yōu)先隊列呢?

因為你可以對 Pod 設(shè)置優(yōu)先級,將你認(rèn)為需要優(yōu)先調(diào)度的 Pod 優(yōu)先級調(diào)大,如果隊列里有多個 Pod 需要調(diào)度,就會出現(xiàn)搶占現(xiàn)象,優(yōu)先級高的 Pod 會移動到隊列頭部,scheduler 會優(yōu)先取出這個 Pod 進(jìn)行調(diào)度。那么這個優(yōu)先級怎么設(shè)置呢?有兩種方法:

  • 如使用 k8s 默認(rèn) sort 插件,則可以給 Pod (deployment等方式) 設(shè)置 PriorityClass(創(chuàng)建 PriorityClass 資源并配置deployment);如果你的所有 Pod 都沒有設(shè)置 PriorityClass,那么會根據(jù) Pod 創(chuàng)建的時間先后順序進(jìn)行調(diào)度。PriorityClass 和 Pod 創(chuàng)建時間是系統(tǒng)默認(rèn)的排序依據(jù)。

  • 實現(xiàn)自己的 sort 插件定制排序算法,根據(jù)該排序算法實現(xiàn)搶占,例如你可以將包含特定標(biāo)簽的 Pod 移到隊頭。后面會詳細(xì)講述如何實現(xiàn)自己的插件來改變系統(tǒng)默認(rèn)行為。

  • filter

filter 類型擴(kuò)展點有3個:prefilter,filter,postfilter。各個擴(kuò)展點有多個插件組成的插件集合根據(jù) Pod 的配置共同過濾 Node,如下圖:

preFilter 擴(kuò)展點主要有兩個作用,一是為后面的擴(kuò)展點計算 Pod 的一些信息,例如 preFilter 階段的 NodeResourcesFit 算法不會去判斷節(jié)點合適與否,而是計算這個Pod需要多少資源,然后存儲這個信息,在 filter 擴(kuò)展點的 NodeResourcesFit 插件中會把之前算出來的資源拿出來做判斷;另外一個作用就是過濾一些明顯不符合要求的節(jié)點,這樣可以減少后續(xù)擴(kuò)展點插件一些無意義的計算。

filter 擴(kuò)展點主要的作用就是根據(jù)各個插件定義的順序依次執(zhí)行,篩選出符合 Pod 的節(jié)點,這些插件會在 preFilter 后留下的每個 Node 上運行,如果能夠通過所有插件的”考驗“,那么這個節(jié)點就留下來了。如果某個插件判斷這個節(jié)點不符合,那么剩余的所有插件都不會對該節(jié)點做計算。

postFilter 擴(kuò)展點只會在filter結(jié)束后沒有任何 Node 符合 Pod 的情況下才會運行,否則這個擴(kuò)展點會被跳過。我們可以看到,這個擴(kuò)展點在系統(tǒng)只有一個默認(rèn)的插件, 這個默認(rèn)插件的作用遍歷這個 Pod 所在的命名空間下面的所有 Pod,查找是否有可以被搶占的 Pod,如果有的話選出一個最合適的 Pod 然后 delete 掉這個Pod,并在待調(diào)度的 Pod 的 status 字段下面配置 nominateNode 為這個被搶占的 Pod。

  • score

這個類型的擴(kuò)展點的作用就是為上面 filter 擴(kuò)展點篩選出來的所有 Node 進(jìn)行打分,挑選出一個得分最高(最合適的),這個 Node 就是 Pod 要被調(diào)度上去的節(jié)點。這個這個類型的擴(kuò)展有 preScore 和 score 兩個,前者是為后者打分做前置準(zhǔn)備的,preScore 的各個插件會計算一些信息供 score使用,這個和 prefilter 比較類似。

  • reserve

reserve 類型擴(kuò)展點系統(tǒng)默認(rèn)只實現(xiàn)了一個插件:VolumeBinding,更新 Pod 聲明的 PVC 和對應(yīng)的 PV緩存信息,表示該 PV 已經(jīng)被 Pod占用。

  • permit

該類型擴(kuò)展點,系統(tǒng)沒有實現(xiàn)默認(rèn)的插件,我們就不說了

  • bind

該類型擴(kuò)展點有三個擴(kuò)展點:preBind、bind和postBind。

preBind 擴(kuò)展點有一個內(nèi)置插件 VolumeBinding,這個插件會調(diào)用 pv controller 完成綁定操作,在前面的 reserve 也有同名插件,這個插件只是更新了本地緩存中的信息,沒有實際做綁定。

bind 擴(kuò)展點也只有一個默認(rèn)的內(nèi)置插件:DefaultBinder,這個插件只做了一件很簡單的事,將 Pod.Spec.nodeName 更新為選出來的那個 node。后面的“故事”就是 kubelet 監(jiān)聽到了 nodeName=Kubelet所在nodename,然后開始創(chuàng)建Pod(容器)。 到了這里,整個調(diào)度流程就結(jié)束了。

從文章開頭的那張圖中我們能夠看到 scheduler 分兩個 cycle: scheduling cycle 和 binding cycle。區(qū)分這兩個 cycle 的原因是為了提升調(diào)度效率。從上面的描述中我們能夠看到,在 bind cycle 中,會有兩次外部 api 調(diào)用:調(diào)用 pv controller 綁定 pv 和調(diào)用 kube-apiserver 綁定 Node,api調(diào)用是耗時的,所以將 bind 擴(kuò)展點拆分出來,另起一個 go 協(xié)程進(jìn)行 bind。而在 scheduling cycle 中為了提升效率的一個重要原則就是 Pod、 Node 等信息從本地緩存中獲取,而具體的實現(xiàn)原理就是先使用 list 獲取所有 Node、Pod 的信息,然后再 watch 他們的變化更新本地緩存。

上面我們主要從擴(kuò)展點和插件方面說明了 scheduler 的架構(gòu)。下面我們從源碼架構(gòu)說說 scheduler 是怎么工作。

kube-scheduler 代碼的主要框架

我們先來看看 kube-scheduler 中的幾個關(guān)鍵組件

  • schedulerCache

schedulerCache 緩存 Pod,Node 等信息,各個擴(kuò)展點的插件在計算時所需要的 Node 和 Pod 信息都是從 schedulerCache 獲取。schedulerCache 具體在內(nèi)部是一個實現(xiàn)了 Cache 接口的 結(jié)構(gòu)體 cacheImpl,我們看下這個結(jié)構(gòu)體:

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
}

說他是緩存,從這個結(jié)構(gòu)體可以看到,實際上就是map,用來存儲 Pod 和 Node 的信息。那么這些數(shù)據(jù)是怎么來的呢?我們來看下一個組件informer

  • informer

informer 是 client-go 提供的能力,他的作用是監(jiān)聽目標(biāo)資源的變化,同步到本地緩存。幾乎,在 k8s 的所有組件包括 controller-manager,kube-proxy,kubelet 等都使用了 informer 來監(jiān)聽 kube-apiserver 來獲取資源的變化。舉個例子,比如你執(zhí)行了 kubectl edit 命令改變了一個 deployment 的鏡像版本,k8s 是怎么感知到這個變化,進(jìn)一步做 Pod 的重建的工作的呢?就是 kube-scheduler 使用了 informer 來監(jiān)聽 Pod 的變化實現(xiàn)的。

具體來說,kube-scheduler 使用 informer 監(jiān)聽了:Node, Pod, CSINode, CSIDriver, CSIStorageCapacity, PersistentVolume, PersistentVolumeClaim, StorageClass。監(jiān)聽 Node,Pod 我們可以理解,那么為什么要監(jiān)聽后面那些資源呢?后面的那些資源都是跟存儲有關(guān),在 preFilter 和 filter 擴(kuò)展點的插件里面有 Volumebinding 這么一個插件,是檢查系統(tǒng)當(dāng)前是否能夠滿足 Pod 聲明的 PVC,如果不能滿足,那么只能把 Pod 放入 unscheduleableQ 里。但是,后續(xù)如果系統(tǒng)如果可以滿足 Pod 對存儲的需要了,這個 Pod 需要第一時間能夠被創(chuàng)建出來,所以系統(tǒng)必須要能夠?qū)崟r感知到系統(tǒng) PVC 等資源的變化及時將 unscheduleableQ 里面調(diào)度失敗的 Pod 進(jìn)行重新調(diào)度。這就是 informer 存在的意義了。具體的 informer 的實現(xiàn)原理可以參考這篇文章。

  • schedulerQueue

schedulerQueue包含三個隊列:activeQ, podBackoffQ,unschedulablePods。

activeQ 是一個優(yōu)先隊列,基于堆實現(xiàn),用于存放待調(diào)度的 Pod,優(yōu)先級高的會放在隊列頭部,優(yōu)先被調(diào)度。該隊列存放的 Pod 可能的情況有:剛創(chuàng)建未被調(diào)度的Pod;backOffPod 隊列中轉(zhuǎn)移過來的Pod;unschedule 隊列里轉(zhuǎn)移過來的 Pod。

podBackoffQ 也是一個優(yōu)先隊列,用于存放那些異常的Pod,這種 Pod 需要等待一定的時間才能夠被再次調(diào)度,會有協(xié)程定期去讀取這個隊列,然后加入到 activeQ 隊列然后重新調(diào)度。

unschedulablePods 嚴(yán)格上來說不屬于隊列,用于存放調(diào)度失敗的 Pod。這個隊列也會有協(xié)程定期(默認(rèn)30s)去讀取,然后判斷當(dāng)前時間距離上次調(diào)度時間的差是否超過5Min,如果超過這個時間則把 Pod 移動到 activeQ 重新調(diào)度。

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)
}

說完這幾個組件,我們再來看看,當(dāng)一個新的 Pod 創(chuàng)建出來后,這個流程是怎么走的

  • informer 監(jiān)聽到了有新建 Pod,根據(jù) Pod 的優(yōu)先級把 Pod 加入到 activeQ 中適當(dāng)位置(即執(zhí)行sort插件);
  • scheduler 從 activeQ 隊頭取一個Pod(如果隊列沒有Pod可取,則會一直阻塞;此時假設(shè)就是上述說的新建的 Pod),開始調(diào)度;
  • 執(zhí)行 filter 類型擴(kuò)展點(包括preFilter,filter,postFilter)插件,選出所有符合 Pod 的 Node,如果無法找到符合的 Node, 則把 Pod 加入 unscheduleableQ 中,此次調(diào)度結(jié)束;
  • 執(zhí)行 score 擴(kuò)展點插件,找出最符合 Pod 的 那個Node;
  • assume Pod。這一步就是樂觀假設(shè) Pod 已經(jīng)調(diào)度成功,更新緩存中 Node 和 PodStats 信息,到了這里scheduling cycle就已經(jīng)結(jié)束了,然后會開啟新的一輪調(diào)度。至于真正的綁定,則會新起一個協(xié)程。
  • 執(zhí)行 reserve 插件;
  • 啟動協(xié)程綁定 Pod 到 Node上。實際上就是修改 Pod.spec.nodeName: 選定的node名字,然后調(diào)用 kube-apiserver 接口寫入 etcd。如果綁定失敗了,那么移除緩存中此前加入的信息,然后把 Pod 放入activeQ 中,后續(xù)重新調(diào)度。
  • 執(zhí)行 postBinding,該步?jīng)]有實現(xiàn)的插件沒所以沒有做任何事。

以上就是 kube-scheduler 的基本原理。

在后面的文章中,我們會繼續(xù)聊聊 kube-scheduler 是怎么初始化出來的,要想開發(fā)一個自己的插件要做哪些事,更多關(guān)于Go kube-scheduler架構(gòu)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • gtoken替換jwt實現(xiàn)sso登錄的排雷避坑

    gtoken替換jwt實現(xiàn)sso登錄的排雷避坑

    這篇文章主要為大家介紹了gtoken替換jwt實現(xiàn)sso登錄的排雷避坑,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Go Resiliency庫中timeout實現(xiàn)原理及源碼解析

    Go Resiliency庫中timeout實現(xiàn)原理及源碼解析

    Go-Resiliency庫中的timeout是一種基于協(xié)程的超時機(jī)制,通過創(chuàng)建協(xié)程來執(zhí)行任務(wù)并設(shè)置超時時間,若任務(wù)執(zhí)行時間超時則中止協(xié)程并返回錯誤,需要詳細(xì)了解可以參考下文
    2023-05-05
  • Go語言實現(xiàn)AzDG可逆加密算法實例

    Go語言實現(xiàn)AzDG可逆加密算法實例

    這篇文章主要介紹了Go語言實現(xiàn)AzDG可逆加密算法,實例分析了AzDG可逆加密算法的實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • 淺談go中cgo的幾種使用方式

    淺談go中cgo的幾種使用方式

    本文主要介紹了淺談go中cgo的幾種使用方式,文中根據(jù)實例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • golang實現(xiàn)一個簡單的websocket聊天室功能

    golang實現(xiàn)一個簡單的websocket聊天室功能

    這篇文章主要介紹了golang實現(xiàn)一個簡單的websocket聊天室功能,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • go 熔斷原理分析與源碼解讀

    go 熔斷原理分析與源碼解讀

    這篇文章主要為大家介紹了go 熔斷原理分析與源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Golang處理內(nèi)存溢出方式

    Golang處理內(nèi)存溢出方式

    本文介紹了Golang中分析內(nèi)存溢出問題的三種工具:pprof、GoMemstats和程序crash時自動創(chuàng)建dump文件,通過這些工具,可以對程序的內(nèi)存使用情況進(jìn)行詳細(xì)分析,從而找出內(nèi)存溢出的原因
    2024-12-12
  • 詳解Go語言中的監(jiān)視器模式與配置熱更新

    詳解Go語言中的監(jiān)視器模式與配置熱更新

    這篇文章主要為大家詳細(xì)介紹了Go語言中的監(jiān)視器模式與配置熱更新的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03
  • Go語言map字典用法實例分析

    Go語言map字典用法實例分析

    這篇文章主要介紹了Go語言map字典用法,實例分析了map字典的使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • GO中?分組聲明與array,?slice,?map函數(shù)

    GO中?分組聲明與array,?slice,?map函數(shù)

    這篇文章主要介紹了GO中?分組聲明與array,slice,map函數(shù),Go語言中,同時聲明多個常量、變量,或者導(dǎo)入多個包時,可采用分組的方式進(jìn)行聲明,下面詳細(xì)介紹需要的小伙伴可以參考一下
    2022-03-03

最新評論

靖江市| 宣汉县| 繁峙县| 宁波市| 彰武县| 蓬莱市| 温州市| 馆陶县| 开平市| 万载县| 龙江县| 若羌县| 临湘市| 定襄县| 宝丰县| 兴隆县| 安义县| 若羌县| 崇礼县| 义马市| 千阳县| 大连市| 确山县| 峨眉山市| 邵阳市| 特克斯县| 柘城县| 达州市| 焉耆| 水城县| 永平县| 大石桥市| 柘城县| 旌德县| 珠海市| 垦利县| 九龙坡区| 藁城市| 财经| 抚松县| 通渭县|