細(xì)讀Kubernetes源碼(scheduler之Pod的綁定)

Kubernetes 的開(kāi)始起源于谷歌,是一個(gè)谷歌花了很多力氣來(lái)為你的工作和服務(wù)創(chuàng)建的新管理工具。它在谷歌系統(tǒng)中有自己的起源: Borg 和 Omega 。無(wú)論是公有云還是私有云甚至混合云,Kubernetes將作為一個(gè)為任何應(yīng)用,任何環(huán)境的容器管理框架無(wú)處不在。正因?yàn)槿绱耍?受到各大巨頭及初創(chuàng)公司的青睞,如IBM,Microsoft、VMWare、Red Hat、CoreOS、Mesos等,紛紛加入給Kubernetes貢獻(xiàn)代碼。Kubernetes毫無(wú)疑問(wèn)坐擁容器編排的霸主地位。

關(guān)于Kubernetes的起源,架構(gòu),原理,組件的介紹網(wǎng)上太多了,感興趣的可以自行g(shù)oogle,但是我發(fā)現(xiàn)關(guān)于源碼的解讀比較少,即使有,也比較泛泛。大多是從某個(gè)函數(shù)入口講起,然后講到包,結(jié)構(gòu)體,屬性,方法結(jié)束,關(guān)于每個(gè)方法的作用要么是略過(guò),要么是一句話(huà)解釋?zhuān)瑢?duì)Kubernetes的一個(gè)組件的解讀盡然一篇文章就寫(xiě)完了,大師的思維太快,跟不上~~~

架構(gòu)是大師們的事情,我們凡夫俗子能做到清楚就很不容易了!我打算在接下來(lái)的文章里,每一篇文章之讀一個(gè)關(guān)鍵方法。細(xì)細(xì)品味大神們的杰作。

我想好多用過(guò)Kubernetes的都有一個(gè)疑問(wèn),Pod是如何通過(guò)層層篩選被綁定到一個(gè)節(jié)點(diǎn)的。接下來(lái)就分析這個(gè)方法實(shí)現(xiàn):scheduleOne()。

關(guān)于scheduler的predicateprioirity設(shè)計(jì)請(qǐng)參考devel/scheduler.md,關(guān)于它的算法請(qǐng)參考devel/scheduler_algorithm.md,讀完之后,你就會(huì)對(duì)Kubernetes Master三大組件之一的scheduler有了一個(gè)基本的印象,甚至感覺(jué)好簡(jiǎn)單啊~~~ 那么,恭喜你,你與大神的差距又縮短了一厘米~~~

好,現(xiàn)在我們從 kubernetes/plugin/pkg/scheduler/scheduler.go
中摘出scheduleOne方法,我會(huì)把解讀放到每一行代碼的前面。

// scheduleOne does the entire scheduling workflow for a single pod.  It is serialized on the scheduling algorithm's host fitting.
func (sched *Scheduler) scheduleOne() {
    // 獲取一個(gè)待調(diào)度的Pod, NextPod()方法是阻塞的
    pod := sched.config.NextPod()
    //首先,判斷這個(gè)Pod是否正在被刪除中,如果是,則返回,跳過(guò)調(diào)度。
    if pod.DeletionTimestamp != nil {
        //記錄發(fā)生的事件,可以通過(guò)kubectl describe pods命令看到此處的事件打印信息
        sched.config.Recorder.Eventf(pod, v1.EventTypeWarning, "FailedScheduling", "skip schedule deleting pod: %v/%v", pod.Namespace, pod.Name)
        glog.V(3).Infof("Skip schedule deleting pod: %v/%v", pod.Namespace, pod.Name)
        return
    }
       // 開(kāi)始嘗試調(diào)度pod,以命名空間和pod名稱(chēng)區(qū)分
    glog.V(3).Infof("Attempting to schedule pod: %v/%v", pod.Namespace, pod.Name)

    // Synchronously attempt to find a fit for the pod.
    start := time.Now()
    // 此處的schedule()方法中,會(huì)調(diào)用注冊(cè)的初選和優(yōu)選的算法,最終返回一個(gè)節(jié)點(diǎn)的名稱(chēng)存放到suggestedHost變量中
    suggestedHost, err := sched.schedule(pod)
    // 此處,會(huì)調(diào)用go的一個(gè)客戶(hù)端,原子地的更新觀(guān)測(cè)總和。關(guān)于它的具體功能,我們下次再細(xì)讀。
    metrics.SchedulingAlgorithmLatency.Observe(metrics.SinceInMicroseconds(start))
    if err != nil {
        return
    }

    // Tell the cache to assume that a pod now is running on a given node, even though it hasn't been bound yet.
    // This allows us to keep scheduling without waiting on binding to occur.

    //即使該pod還未真正綁定到節(jié)點(diǎn)上,我們先假設(shè)這個(gè)pod已經(jīng)在指定的節(jié)點(diǎn)上運(yùn)行了。這是為了更新shcedulerCache, 與綁定操作(需要花費(fèi)一些時(shí)間)以異步方式進(jìn)行。 
    err = sched.assume(pod, suggestedHost)
    if err != nil {
        return
    }

    // bind the pod to its host asynchronously (we can do this b/c of the assumption step above).
    // 創(chuàng)建一個(gè)協(xié)程goruntime,異步地綁定pod。(注意,該shceduleOne方法也是在一個(gè)協(xié)程中)
    go func() {

        // 執(zhí)行綁定方法,把該pod的命名空間,名稱(chēng)和UID綁定到指定的節(jié)點(diǎn)(suggestedHost)上,到此,一個(gè)pod綁定到一個(gè)節(jié)點(diǎn)的過(guò)程就完成了。
        err := sched.bind(pod, &v1.Binding{
            ObjectMeta: metav1.ObjectMeta{Namespace: pod.Namespace, Name: pod.Name, UID: pod.UID},
            Target: v1.ObjectReference{
                Kind: "Node",
                Name: suggestedHost, // 分配的節(jié)點(diǎn)
            },
        })

        // 與上面類(lèi)似,會(huì)在后面單獨(dú)分析,它們的實(shí)現(xiàn)在vendor/github.com/prometheus/client_golang/prometheus/histogram.go,可以自行看一下
        metrics.E2eSchedulingLatency.Observe(metrics.SinceInMicroseconds(start))
        if err != nil {
            glog.Errorf("Internal error binding pod: (%v)", err)
        }
    }()
}

是不是感覺(jué)很簡(jiǎn)單?確實(shí),大神的代碼讓你感覺(jué)邏輯清晰,代碼簡(jiǎn)潔。但是,還有許多問(wèn)題未解決,比如,如果綁定失敗,retrying 是如何觸發(fā)的呢?retrying的篩選邏輯,使用的算法是否和之前一致呢?如果調(diào)度過(guò)程中節(jié)點(diǎn)掛了怎么辦?scheduler是如何拿到各個(gè)節(jié)點(diǎn)的資源信息的?綁定之后,Kubelet是如何接收Pod的?如何添加自己定制的算法?等等。下一篇文章會(huì)分析retrying機(jī)制,敬請(qǐng)期待。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容