溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Kubernetes調(diào)度器的使用方法

發(fā)布時(shí)間:2021-06-26 09:47:26 來(lái)源:億速云 閱讀:203 作者:chen 欄目:大數(shù)據(jù)

本篇內(nèi)容主要講解“Kubernetes調(diào)度器的使用方法”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Kubernetes調(diào)度器的使用方法”吧!

kube-scheduler是 kubernetes 系統(tǒng)的核心組件之一,主要負(fù)責(zé)整個(gè)集群資源的調(diào)度功能,根據(jù)特定的調(diào)度算法和策略,將 Pod 調(diào)度到最優(yōu)的工作節(jié)點(diǎn)上面去,從而更加合理、更加充分的利用集群的資源,這也是我們選擇使用 kubernetes 一個(gè)非常重要的理由。如果一門(mén)新的技術(shù)不能幫助企業(yè)節(jié)約成本、提供效率,我相信是很難推進(jìn)的。

調(diào)度流程

默認(rèn)情況下,kube-scheduler 提供的默認(rèn)調(diào)度器能夠滿(mǎn)足我們絕大多數(shù)的要求,我們前面和大家接觸的示例也基本上用的默認(rèn)的策略,都可以保證我們的 Pod 可以被分配到資源充足的節(jié)點(diǎn)上運(yùn)行。但是在實(shí)際的線(xiàn)上項(xiàng)目中,可能我們自己會(huì)比 kubernetes 更加了解我們自己的應(yīng)用,比如我們希望一個(gè) Pod 只能運(yùn)行在特定的幾個(gè)節(jié)點(diǎn)上,或者這幾個(gè)節(jié)點(diǎn)只能用來(lái)運(yùn)行特定類(lèi)型的應(yīng)用,這就需要我們的調(diào)度器能夠可控。

kube-scheduler 是 kubernetes 的調(diào)度器,它的主要作用就是根據(jù)特定的調(diào)度算法和調(diào)度策略將 Pod 調(diào)度到合適的 Node 節(jié)點(diǎn)上去,是一個(gè)獨(dú)立的二進(jìn)制程序,啟動(dòng)之后會(huì)一直監(jiān)聽(tīng) API Server,獲取到 PodSpec.NodeName 為空的 Pod,對(duì)每個(gè) Pod 都會(huì)創(chuàng)建一個(gè) binding。

Kubernetes調(diào)度器的使用方法

kube-scheduler structrue

這個(gè)過(guò)程在我們看來(lái)好像比較簡(jiǎn)單,但在實(shí)際的生產(chǎn)環(huán)境中,需要考慮的問(wèn)題就有很多了:

  • 如何保證全部的節(jié)點(diǎn)調(diào)度的公平性?要知道并不是說(shuō)有節(jié)點(diǎn)資源配置都是一樣的

  • 如何保證每個(gè)節(jié)點(diǎn)都能被分配資源?

  • 集群資源如何能夠被高效利用?

  • 集群資源如何才能被最大化使用?

  • 如何保證 Pod 調(diào)度的性能和效率?

  • 用戶(hù)是否可以根據(jù)自己的實(shí)際需求定制自己的調(diào)度策略?

考慮到實(shí)際環(huán)境中的各種復(fù)雜情況,kubernetes 的調(diào)度器采用插件化的形式實(shí)現(xiàn),可以方便用戶(hù)進(jìn)行定制或者二次開(kāi)發(fā),我們可以自定義一個(gè)調(diào)度器并以插件形式和 kubernetes 進(jìn)行集成。

kubernetes 調(diào)度器的源碼位于 kubernetes/pkg/scheduler 中,大體的代碼目錄結(jié)構(gòu)如下所示:(不同的版本目錄結(jié)構(gòu)可能不太一樣)

kubernetes/pkg/scheduler
-- scheduler.go         //調(diào)度相關(guān)的具體實(shí)現(xiàn)
|-- algorithm
|   |-- predicates      //節(jié)點(diǎn)篩選策略
|   |-- priorities      //節(jié)點(diǎn)打分策略
|-- algorithmprovider
|   |-- defaults         //定義默認(rèn)的調(diào)度器

其中 Scheduler 創(chuàng)建和運(yùn)行的核心程序,對(duì)應(yīng)的代碼在 pkg/scheduler/scheduler.go,如果要查看kube-scheduler的入口程序,對(duì)應(yīng)的代碼在 cmd/kube-scheduler/scheduler.go。

調(diào)度主要分為以下幾個(gè)部分:

  • 首先是預(yù)選過(guò)程,過(guò)濾掉不滿(mǎn)足條件的節(jié)點(diǎn),這個(gè)過(guò)程稱(chēng)為Predicates

  • 然后是優(yōu)選過(guò)程,對(duì)通過(guò)的節(jié)點(diǎn)按照優(yōu)先級(jí)排序,稱(chēng)之為Priorities

  • 最后從中選擇優(yōu)先級(jí)最高的節(jié)點(diǎn),如果中間任何一步驟有錯(cuò)誤,就直接返回錯(cuò)誤

Predicates階段首先遍歷全部節(jié)點(diǎn),過(guò)濾掉不滿(mǎn)足條件的節(jié)點(diǎn),屬于強(qiáng)制性規(guī)則,這一階段輸出的所有滿(mǎn)足要求的 Node 將被記錄并作為第二階段的輸入,如果所有的節(jié)點(diǎn)都不滿(mǎn)足條件,那么 Pod 將會(huì)一直處于 Pending 狀態(tài),直到有節(jié)點(diǎn)滿(mǎn)足條件,在這期間調(diào)度器會(huì)不斷的重試。

所以我們?cè)诓渴饝?yīng)用的時(shí)候,如果發(fā)現(xiàn)有 Pod 一直處于 Pending 狀態(tài),那么就是沒(méi)有滿(mǎn)足調(diào)度條件的節(jié)點(diǎn),這個(gè)時(shí)候可以去檢查下節(jié)點(diǎn)資源是否可用。

Priorities階段即再次對(duì)節(jié)點(diǎn)進(jìn)行篩選,如果有多個(gè)節(jié)點(diǎn)都滿(mǎn)足條件的話(huà),那么系統(tǒng)會(huì)按照節(jié)點(diǎn)的優(yōu)先級(jí)(priorites)大小對(duì)節(jié)點(diǎn)進(jìn)行排序,最后選擇優(yōu)先級(jí)最高的節(jié)點(diǎn)來(lái)部署 Pod 應(yīng)用。

下面是調(diào)度過(guò)程的簡(jiǎn)單示意圖:kube-scheduler filter

更詳細(xì)的流程是這樣的:

  • 首先,客戶(hù)端通過(guò) API Server 的 REST API 或者 kubectl 工具創(chuàng)建 Pod 資源

  • API Server 收到用戶(hù)請(qǐng)求后,存儲(chǔ)相關(guān)數(shù)據(jù)到 etcd 數(shù)據(jù)庫(kù)中

  • 調(diào)度器監(jiān)聽(tīng) API Server 查看為調(diào)度(bind)的 Pod 列表,循環(huán)遍歷地為每個(gè) Pod 嘗試分配節(jié)點(diǎn),這個(gè)分配過(guò)程就是我們上面提到的兩個(gè)階段:

    • 預(yù)選階段(Predicates),過(guò)濾節(jié)點(diǎn),調(diào)度器用一組規(guī)則過(guò)濾掉不符合要求的 Node 節(jié)點(diǎn),比如 Pod 設(shè)置了資源的 request,那么可用資源比 Pod 需要的資源少的主機(jī)顯然就會(huì)被過(guò)濾掉

    • 優(yōu)選階段(Priorities),為節(jié)點(diǎn)的優(yōu)先級(jí)打分,將上一階段過(guò)濾出來(lái)的 Node 列表進(jìn)行打分,調(diào)度器會(huì)考慮一些整體的優(yōu)化策略,比如把 Deployment 控制的多個(gè) Pod 副本分布到不同的主機(jī)上,使用最低負(fù)載的主機(jī)等等策略

  • 經(jīng)過(guò)上面的階段過(guò)濾后選擇打分最高的 Node 節(jié)點(diǎn)和 Pod 進(jìn)行 binding 操作,然后將結(jié)果存儲(chǔ)到 etcd 中

  • 最后被選擇出來(lái)的 Node 節(jié)點(diǎn)對(duì)應(yīng)的 kubelet 去執(zhí)行創(chuàng)建 Pod 的相關(guān)操作

其中Predicates過(guò)濾有一系列的算法可以使用,我們這里簡(jiǎn)單列舉幾個(gè):

  • PodFitsResources:節(jié)點(diǎn)上剩余的資源是否大于 Pod 請(qǐng)求的資源

  • PodFitsHost:如果 Pod 指定了 NodeName,檢查節(jié)點(diǎn)名稱(chēng)是否和 NodeName 匹配

  • PodFitsHostPorts:節(jié)點(diǎn)上已經(jīng)使用的 port 是否和 Pod 申請(qǐng)的 port 沖突

  • PodSelectorMatches:過(guò)濾掉和 Pod 指定的 label 不匹配的節(jié)點(diǎn)

  • NoDiskConflict:已經(jīng) mount 的 volume 和 Pod 指定的 volume 不沖突,除非它們都是只讀的

  • CheckNodeDiskPressure:檢查節(jié)點(diǎn)磁盤(pán)空間是否符合要求

  • CheckNodeMemoryPressure:檢查節(jié)點(diǎn)內(nèi)存是否夠用

除了這些過(guò)濾算法之外,還有一些其他的算法,更多更詳細(xì)的我們可以查看源碼文件:k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/predicates.go。

Priorities優(yōu)先級(jí)是由一系列鍵值對(duì)組成的,鍵是該優(yōu)先級(jí)的名稱(chēng),值是它的權(quán)重值,同樣,我們這里給大家列舉幾個(gè)具有代表性的選項(xiàng):

  • LeastRequestedPriority:通過(guò)計(jì)算 CPU 和內(nèi)存的使用率來(lái)決定權(quán)重,使用率越低權(quán)重越高,當(dāng)然正常肯定也是資源是使用率越低權(quán)重越高,能給別的 Pod 運(yùn)行的可能性就越大

  • SelectorSpreadPriority:為了更好的高可用,對(duì)同屬于一個(gè) Deployment 或者 RC 下面的多個(gè) Pod 副本,盡量調(diào)度到多個(gè)不同的節(jié)點(diǎn)上,當(dāng)一個(gè) Pod 被調(diào)度的時(shí)候,會(huì)先去查找該 Pod 對(duì)應(yīng)的 controller,然后查看該 controller 下面的已存在的 Pod,運(yùn)行 Pod 越少的節(jié)點(diǎn)權(quán)重越高

  • ImageLocalityPriority:就是如果在某個(gè)節(jié)點(diǎn)上已經(jīng)有要使用的鏡像節(jié)點(diǎn)了,鏡像總大小值越大,權(quán)重就越高

  • NodeAffinityPriority:這個(gè)就是根據(jù)節(jié)點(diǎn)的親和性來(lái)計(jì)算一個(gè)權(quán)重值,后面我們會(huì)詳細(xì)講解親和性的使用方法

除了這些策略之外,還有很多其他的策略,同樣我們可以查看源碼文件:k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/ 了解更多信息。每一個(gè)優(yōu)先級(jí)函數(shù)會(huì)返回一個(gè)0-10的分?jǐn)?shù),分?jǐn)?shù)越高表示節(jié)點(diǎn)越優(yōu),同時(shí)每一個(gè)函數(shù)也會(huì)對(duì)應(yīng)一個(gè)表示權(quán)重的值。最終主機(jī)的得分用以下公式計(jì)算得出:

finalScoreNode = (weight1 * priorityFunc1) + (weight2 * priorityFunc2) + … + (weightn * priorityFuncn)

自定義調(diào)度

上面就是 kube-scheduler 默認(rèn)調(diào)度的基本流程,除了使用默認(rèn)的調(diào)度器之外,我們也可以自定義調(diào)度策略。

調(diào)度器擴(kuò)展

kube-scheduler在啟動(dòng)的時(shí)候可以通過(guò) --policy-config-file參數(shù)來(lái)指定調(diào)度策略文件,我們可以根據(jù)我們自己的需要來(lái)組裝PredicatesPriority函數(shù)。選擇不同的過(guò)濾函數(shù)和優(yōu)先級(jí)函數(shù)、控制優(yōu)先級(jí)函數(shù)的權(quán)重、調(diào)整過(guò)濾函數(shù)的順序都會(huì)影響調(diào)度過(guò)程。

下面是官方的 Policy 文件示例:

{
    "kind" : "Policy",
    "apiVersion" : "v1",
    "predicates" : [
        {"name" : "PodFitsHostPorts"},
        {"name" : "PodFitsResources"},
        {"name" : "NoDiskConflict"},
        {"name" : "NoVolumeZoneConflict"},
        {"name" : "MatchNodeSelector"},
        {"name" : "HostName"}
    ],
    "priorities" : [
        {"name" : "LeastRequestedPriority", "weight" : 1},
        {"name" : "BalancedResourceAllocation", "weight" : 1},
        {"name" : "ServiceSpreadingPriority", "weight" : 1},
        {"name" : "EqualPriority", "weight" : 1}
    ]
}

多調(diào)度器

如果默認(rèn)的調(diào)度器不滿(mǎn)足要求,還可以部署自定義的調(diào)度器。并且,在整個(gè)集群中還可以同時(shí)運(yùn)行多個(gè)調(diào)度器實(shí)例,通過(guò)podSpec.schedulerName 來(lái)選擇使用哪一個(gè)調(diào)度器(默認(rèn)使用內(nèi)置的調(diào)度器)。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  schedulerName: my-scheduler  # 選擇使用自定義調(diào)度器 my-scheduler
  containers:
  - name: nginx
    image: nginx:1.10

要開(kāi)發(fā)我們自己的調(diào)度器也是比較容易的,比如我們這里的 my-scheduler:

  • 首先需要通過(guò)指定的 API 獲取節(jié)點(diǎn)和 Pod

  • 然后選擇phase=PendingschedulerName=my-scheduler的pod

  • 計(jì)算每個(gè) Pod 需要放置的位置之后,調(diào)度程序?qū)?chuàng)建一個(gè)Binding對(duì)象

  • 然后根據(jù)我們自定義的調(diào)度器的算法計(jì)算出最適合的目標(biāo)節(jié)點(diǎn)

優(yōu)先級(jí)調(diào)度

與前面所講的調(diào)度優(yōu)選策略中的優(yōu)先級(jí)(Priorities)不同,前面所講的優(yōu)先級(jí)指的是節(jié)點(diǎn)優(yōu)先級(jí),而我們這里所說(shuō)的優(yōu)先級(jí) pod priority 指的是 Pod 的優(yōu)先級(jí),高優(yōu)先級(jí)的 Pod 會(huì)優(yōu)先被調(diào)度,或者在資源不足低情況犧牲低優(yōu)先級(jí)的 Pod,以便于重要的 Pod 能夠得到資源部署。

要定義 Pod 優(yōu)先級(jí),就需要先定義PriorityClass對(duì)象,該對(duì)象沒(méi)有 Namespace 的限制:

apiVersion: v1
kind: PriorityClass
metadata:
  name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for XYZ service pods only."

其中:

  • value為 32 位整數(shù)的優(yōu)先級(jí),該值越大,優(yōu)先級(jí)越高

  • globalDefault用于未配置 PriorityClassName 的 Pod,整個(gè)集群中應(yīng)該只有一個(gè)PriorityClass將其設(shè)置為 true

然后通過(guò)在 Pod 的spec.priorityClassName中指定已定義的PriorityClass名稱(chēng)即可:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  priorityClassName: high-priority

另外一個(gè)值得注意的是當(dāng)節(jié)點(diǎn)沒(méi)有足夠的資源供調(diào)度器調(diào)度 Pod,導(dǎo)致 Pod 處于 pending 時(shí),搶占(preemption)邏輯就會(huì)被觸發(fā)。Preemption會(huì)嘗試從一個(gè)節(jié)點(diǎn)刪除低優(yōu)先級(jí)的 Pod,從而釋放資源使高優(yōu)先級(jí)的 Pod 得到節(jié)點(diǎn)資源進(jìn)行部署。

現(xiàn)在我們通過(guò)下面的圖再去回顧下 kubernetes 的調(diào)度過(guò)程是不是就清晰很多了:Kubernetes調(diào)度器的使用方法

到此,相信大家對(duì)“Kubernetes調(diào)度器的使用方法”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI