備戰(zhàn)CKA每日一題——第5天 | 手動調(diào)度、kube-scheduler調(diào)度器解析、源碼淺析

本活動在微信公眾號【我的小碗湯】上舉行,有送書活動!這里參與答題不能參與到送書活動哦!

昨日考題

通過命令行,使用nginx鏡像創(chuàng)建一個(gè)pod并手動調(diào)度到節(jié)點(diǎn)名為node1121節(jié)點(diǎn)上,Pod的名稱為cka-1121,答題最好附上,所用命令、創(chuàng)建Pod所需最精簡的yaml;如果評論有限制,請把注意點(diǎn)列出,主要需列出手動調(diào)度怎么做?
注意:手動調(diào)度是指不需要經(jīng)過kube-scheduler去調(diào)度。

昨日答案

將名稱為cka-1121的Pod,調(diào)度到節(jié)點(diǎn)node1121:

apiVersion: v1
kind: Pod
metadata:
  name: cka-1121
  labels:
    app: cka-1121
spec:
  containers:
  - name: cka-1121
    image: busybox
    command: ['sh', '-c', 'echo Hello CKA! && sleep 3600']
  nodeName: node1121

昨日解析

官網(wǎng)中調(diào)度器地址:
https://kubernetes.io/docs/concepts/scheduling/kube-scheduler/
調(diào)度器命令行參數(shù):
https://kubernetes.io/docs/reference/command-line-tools-reference/kube-scheduler/

調(diào)度器kube-scheduler分為預(yù)選、優(yōu)選、pod優(yōu)先級搶占、bind階段;

預(yù)選:從podQueue的待調(diào)度隊(duì)列中彈出需要調(diào)度的pod,先進(jìn)入預(yù)選階段,預(yù)選函數(shù)來判斷每個(gè)節(jié)點(diǎn)是否適合被該P(yáng)od調(diào)度。

優(yōu)選:從預(yù)選篩選出的滿足的節(jié)點(diǎn)中選擇出最優(yōu)的節(jié)點(diǎn)。

pod優(yōu)先級搶占:如果預(yù)選和優(yōu)選調(diào)度失敗,則會嘗試將優(yōu)先級低的pod剔除,讓優(yōu)先級高的pod調(diào)度成功。

bind:上述步驟完成后,調(diào)度器會更新本地緩存,但最后需要將綁定結(jié)果提交到etcd中,需要調(diào)用Apiserver的Bind接口完成。

以下k8s源碼版本為1.13.2

我們?nèi)ゲ榭磌ube-scheduler源碼,調(diào)度器通過list-watch機(jī)制,監(jiān)聽集群內(nèi)Pod的新增、更新、刪除事件,調(diào)用回調(diào)函數(shù)。指定nodeName后將不會放入到未調(diào)度的podQueue隊(duì)列中,也就不會走上面這幾個(gè)階段。具體可以來到pkg\scheduler\factory\factory.go源碼中的NewConfigFactory函數(shù)中:


在這里插入圖片描述

其中在構(gòu)建pod資源對象新增、更新、刪除的回調(diào)函數(shù)時(shí),分已被調(diào)度的和未被調(diào)度的回調(diào)。

已被調(diào)度的回調(diào):
已被調(diào)度的pod根據(jù)FilterFunc中定義的邏輯過濾,nodeName不為空,返回true時(shí),將會走Handler中定義的AddFunc、UpdateFunc、DeleteFunc,這個(gè)其實(shí)最終不會加入到podQueue中,但需要加入到本地緩存中,因?yàn)檎{(diào)度器會維護(hù)一份節(jié)點(diǎn)上pod列表的緩存。

// scheduled pod cache 已被調(diào)度的
    args.PodInformer.Informer().AddEventHandler(
        cache.FilteringResourceEventHandler{
            FilterFunc: func(obj interface{}) bool {
                switch t := obj.(type) {
                case *v1.Pod:
                    //nodeName不為空,返回true;且返回true時(shí)將被走AddFunc、UpdateFunc、DeleteFunc,這個(gè)其實(shí)最終不會加入到podQueue中
                    return assignedPod(t)
                case cache.DeletedFinalStateUnknown:
                    if pod, ok := t.Obj.(*v1.Pod); ok {
                        return assignedPod(pod)
                    }
                    runtime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, c))
                    return false
                default:
                    runtime.HandleError(fmt.Errorf("unable to handle object in %T: %T", c, obj))
                    return false
                }
            },
            Handler: cache.ResourceEventHandlerFuncs{
                AddFunc:    c.addPodToCache,
                UpdateFunc: c.updatePodInCache,
                DeleteFunc: c.deletePodFromCache,
            },
        },
    )

未被調(diào)度的回調(diào):
未被調(diào)度的pod根據(jù)FilterFunc中定義的邏輯過濾,nodeName為空且pod的SchedulerName和該調(diào)度器的名稱一致時(shí)返回true;返回true時(shí),將會走Handler中定義的AddFunc、UpdateFunc、DeleteFunc,這個(gè)最終會加入到podQueue中。

    // unscheduled pod queue 沒有被調(diào)度的
    args.PodInformer.Informer().AddEventHandler(
        cache.FilteringResourceEventHandler{
            FilterFunc: func(obj interface{}) bool {
                switch t := obj.(type) {
                case *v1.Pod:
                    //nodeName為空且pod的SchedulerName和該調(diào)度器的名稱一致時(shí)返回true;且返回true時(shí)將被加入到pod queue
                    return !assignedPod(t) && responsibleForPod(t, args.SchedulerName)
                case cache.DeletedFinalStateUnknown:
                    if pod, ok := t.Obj.(*v1.Pod); ok {
                        return !assignedPod(pod) && responsibleForPod(pod, args.SchedulerName)
                    }
                    runtime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, c))
                    return false
                default:
                    runtime.HandleError(fmt.Errorf("unable to handle object in %T: %T", c, obj))
                    return false
                }
            },
            Handler: cache.ResourceEventHandlerFuncs{
                AddFunc:    c.addPodToSchedulingQueue,
                UpdateFunc: c.updatePodInSchedulingQueue,
                DeleteFunc: c.deletePodFromSchedulingQueue,
            },
        },
    )

手動調(diào)度適用場景:

  • 調(diào)度器不工作時(shí),可設(shè)置nodeName臨時(shí)救急 ;
  • 可以封裝成自己的調(diào)度器;

擴(kuò)展點(diǎn):

  • 過去幾個(gè)版本的Daemonset都是由controller直接指定pod的運(yùn)行節(jié)點(diǎn),不經(jīng)過調(diào)度器。
  • 直到1.11版本,DaemonSet的pod由scheduler調(diào)度才作為alpha特性引入

昨天的留言中,有人提到static Pod,這種其實(shí)也屬于節(jié)點(diǎn)固定,但這種Pod局限很大,比如:不能掛載configmaps和secrets等,這個(gè)由Admission Controllers控制。

下面簡單說一下靜態(tài)Pod:

靜態(tài)Pod官網(wǎng)說明:
https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/

靜態(tài) pod指在特定的節(jié)點(diǎn)上直接通過 kubelet守護(hù)進(jìn)程進(jìn)行管理,APIServer無法管理。它沒有跟任何的控制器進(jìn)行關(guān)聯(lián),kubelet 守護(hù)進(jìn)程對它進(jìn)行監(jiān)控,如果崩潰了,kubelet 守護(hù)進(jìn)程會重啟它。Kubelet 通過APIServer為每個(gè)靜態(tài) pod 創(chuàng)建 鏡像 pod,這些鏡像 pod 對于 APIServer是可見的(即kubectl可以查詢到這些Pod),但是不受APIServer控制。

具體static pod yaml文件放到哪里,需要在kubelet配置中指定,先找到kubelet配置文件:

systemctl status kubelet
在這里插入圖片描述

找到config.yaml文件:


在這里插入圖片描述

里面指定了staticPodPath:


在這里插入圖片描述

kubeadm安裝的集群,master節(jié)點(diǎn)上的kube-apiserver、kube-scheduler、kube-controller-manager、etcd就是通過static Pod方式部署的:
在這里插入圖片描述

今日考題

通過命令行,創(chuàng)建兩個(gè)deployment。

  • 需要集群中有2個(gè)節(jié)點(diǎn) ;
  • 第1個(gè)deployment名稱為cka-1122-01,使用nginx鏡像,有2個(gè)pod,并配置該deployment自身的pod之間在節(jié)點(diǎn)級別反親和;
  • 第2個(gè)deployment名稱為cka-1122-02,使用nginx鏡像,有2個(gè)pod,并配置該deployment的pod與第1個(gè)deployment的pod在節(jié)點(diǎn)級別親和;

最好提交最精簡的deployment yaml,如果評論被限制,請?zhí)峤环从H和性配置塊yaml,也可多次評論提交

作者簡介

作者:小碗湯,一位熱愛、認(rèn)真寫作的小伙,目前維護(hù)原創(chuàng)公眾號:『我的小碗湯』,專注于寫golang、docker、kubernetes等知識等提升硬實(shí)力的文章,期待你的關(guān)注。轉(zhuǎn)載說明:務(wù)必注明來源(注明:來源于公眾號:我的小碗湯, 作者:小碗湯)

作者簡潔

作者:小碗湯,一位熱愛、認(rèn)真寫作的小伙,目前維護(hù)原創(chuàng)公眾號:『我的小碗湯』,專注于寫go語言、docker、kubernetes、java等開發(fā)、運(yùn)維知識等提升硬實(shí)力的文章,期待你的關(guān)注。轉(zhuǎn)載說明:務(wù)必注明來源(注明:來源于公眾號:我的小碗湯,作者:小碗湯)

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

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

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