<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:Go 調(diào)度了解嗎?Kubernetes 調(diào)度和資源管理呢?

          共 12186字,需瀏覽 25分鐘

           ·

          2020-09-21 14:21


          作者?| 子譽(yù)? 螞蟻金服高級(jí)技術(shù)專(zhuān)家


          本文整理自《CNCF x Alibaba 云原生技術(shù)公開(kāi)課》第 18?講,點(diǎn)擊“閱讀原文”直達(dá)課程頁(yè)面。

          關(guān)注“Go語(yǔ)言中文網(wǎng)”公眾號(hào),回復(fù)關(guān)鍵詞“入門(mén)”,即可下載從零入門(mén) K8s 系列文章 PPT。



          Kubernetes 調(diào)度過(guò)程


          首先來(lái)看第一部分 - Kubernetes 的調(diào)度過(guò)程。

          如下圖所示,畫(huà)了一個(gè)很簡(jiǎn)單的 Kubernetes 集群架構(gòu),它包括了一個(gè) kube-ApiServer,一組 Web-hook Controllers,以及一個(gè)默認(rèn)的調(diào)度器 kube-Scheduler,還有兩臺(tái)物理機(jī)節(jié)點(diǎn) Node1 和 Node2,分別在上面部署了兩個(gè) kubelet。


          我們來(lái)看一下,假如要向這個(gè) Kubernetes 集群提交一個(gè) pod,它的調(diào)度過(guò)程是什么樣的一個(gè)流程?


          假設(shè)我們已經(jīng)寫(xiě)好了一個(gè) yaml 文件,就是下圖中的橙色圓圈 pod1,然后往 kube-ApiServer 里提交這個(gè) yaml 文件。



          此時(shí) ApiServer 會(huì)先把這個(gè)待創(chuàng)建的請(qǐng)求路由給我們的 webhook Controllers 進(jìn)行校驗(yàn)。



          通過(guò)校驗(yàn)之后,ApiServer 會(huì)在集群里面生成一個(gè) pod,此時(shí)生成的 pod,它的 nodeName 是空的,并且它的 phase 是 Pending 狀態(tài)。在生成了這個(gè) pod 之后,kube-Scheduler 以及 kubelet 都能 watch 到這個(gè) pod 的生成事件,kube-Scheduler 發(fā)現(xiàn)這個(gè) pod 的 nodeName 是空的之后,會(huì)認(rèn)為這個(gè) pod 是處于未調(diào)度狀態(tài)。



          接下來(lái),它會(huì)把這個(gè) pod 拿到自己里面進(jìn)行調(diào)度,通過(guò)一系列的調(diào)度算法,包括一系列的過(guò)濾和打分的算法后,Schedule 會(huì)選出一臺(tái)最合適的節(jié)點(diǎn),并且把這一臺(tái)節(jié)點(diǎn)的名稱(chēng)綁定在這個(gè) pod 的 spec 上,完成一次調(diào)度的過(guò)程。


          此時(shí)我們發(fā)現(xiàn),pod 的 spec 上,nodeName 已經(jīng)更新成了 Node1 這個(gè) node,更新完 nodeName 之后,在 Node1 上的這臺(tái) kubelet 會(huì) watch 到這個(gè) pod 是屬于自己節(jié)點(diǎn)上的一個(gè) pod。



          然后它會(huì)把這個(gè) pod 拿到節(jié)點(diǎn)上進(jìn)行操作,包括創(chuàng)建一些容器 storage 以及 network,最后等所有的資源都準(zhǔn)備完成,kubelet 會(huì)把狀態(tài)更新為 Running,這樣一個(gè)完整的調(diào)度過(guò)程就結(jié)束了。


          通過(guò)剛剛一個(gè)調(diào)度過(guò)程的演示,我們用一句話來(lái)概括一下調(diào)度過(guò)程:它其實(shí)就是在做一件事情,即把 pod 放到合適的 node 上。


          這里有個(gè)關(guān)鍵字“合適”,什么是合適呢?下面給出幾點(diǎn)合適定義的特點(diǎn):


          • 首先要滿足 pod 的資源要求;

          • 其次要滿足 pod 的一些特殊關(guān)系的要求;

          • 再次要滿足 node 的一些限制條件的要求;

          • 最后還要做到整個(gè)集群資源的合理利用。


          做到以上的要求后,可以認(rèn)為我們把 pod 放到了一個(gè)合適的節(jié)點(diǎn)上了。


          接下來(lái)我會(huì)為大家介紹 Kubernetes 是怎么做到滿足這些 pod 和 node 的要求的。






          Kubernetes 基礎(chǔ)調(diào)度力


          下面為大家介紹一下 Kubernetes 的基礎(chǔ)調(diào)度能力,Kubernetes 的基礎(chǔ)調(diào)度能力會(huì)以兩部分來(lái)展開(kāi)介紹:


          • 第一部分是資源調(diào)度——介紹一下 Kubernetes 基本的一些 Resources 的配置方式,還有 Qos 的概念,以及 Resource Quota 的概念和使用方式;


          • 第二部分是關(guān)系調(diào)度——在關(guān)系調(diào)度上,介紹兩種關(guān)系場(chǎng)景:第一種是?pod 和 pod 之間的關(guān)系場(chǎng)景,包括怎么去親和一個(gè) pod,怎么去互斥一個(gè) pod;第二種是?pod 和 node 之間的關(guān)系場(chǎng)景,包括怎么去親和一個(gè) node,以及有一些 node 怎么去限制 pod 調(diào)度上來(lái)。


          1. 如何滿足 Pod 資源要求


          pod 的資源配置方法

          ?

          ?

          上圖是 pod spec 的一個(gè) demo,我們的資源其實(shí)是填在 pod spec 中,具體在 containers 的 resources 里。


          resources 包含兩個(gè)部分:


          • 第一部分是 requests;

          • 第二部分是 limits。


          這兩部分里面的內(nèi)容是一模一樣的,但是它代表的含義有所不同:request 代表的是對(duì)這個(gè) pod 基本保底的一些資源要求;limit 代表的是對(duì)這個(gè) pod 可用能力上限的一種限制。request、limit 的實(shí)現(xiàn)是一個(gè) map 結(jié)構(gòu),它里面可以填不同的資源的 key/value。


          我們可以大概分成四大類(lèi)的基礎(chǔ)資源:


          • 第一類(lèi)是 CPU 資源;

          • 第二類(lèi)是 memory;

          • 第三類(lèi)是 ephemeral-storage,是一種臨時(shí)存儲(chǔ);

          • 第四類(lèi)是通用的擴(kuò)展資源,比如說(shuō)像 GPU。


          CPU 資源,比如說(shuō)上面的例子填的是2,申請(qǐng)的是兩個(gè) CPU,也可以寫(xiě)成 2000m 這種十進(jìn)制的轉(zhuǎn)換方式,來(lái)表達(dá)有些時(shí)候可能對(duì) CPU 可能是一個(gè)小數(shù)的需求,比如說(shuō)像 0.2 個(gè)CPU,可以填 200m。而這種方式在 memory 和 storage 之上,它是一個(gè)二進(jìn)制的表達(dá)方式,如上圖右側(cè)所示,申請(qǐng)的是 1GB 的 memory,同樣也可以填成一個(gè) 1024mi 的表達(dá)方式,這樣可以更清楚地表達(dá)我們對(duì) memory 的需求。


          在擴(kuò)展資源上,Kubernetes 有一個(gè)要求,即擴(kuò)展資源必須是整數(shù)的,所以我們沒(méi)法申請(qǐng)到 0.5 的 GPU 這樣的資源,只能申請(qǐng) 1 個(gè) GPU 或者 2 個(gè) GPU。


          這里為大家介紹完了基礎(chǔ)資源的申請(qǐng)方式。


          接下來(lái),我會(huì)詳細(xì)給大家介紹一下 request 和 limit 到底有什么區(qū)別,以及如何通過(guò) request/limit 來(lái)表示 QoS。


          Pod QoS 類(lèi)型


          K8S 在 pod resources 里面提供了兩種填寫(xiě)方式:第一種是 request,第二種是 limit。


          它其實(shí)是為用戶提供了對(duì) Pod 一種彈性能力的定義。比如說(shuō)我們可以對(duì) request 填 2 個(gè) CPU,對(duì) limit 填 4 個(gè) CPU,這樣代表了我希望是有 2 個(gè) CPU 的保底能力,但其實(shí)在閑置的時(shí)候,可以使用 4 個(gè) GPU。


          說(shuō)到這個(gè)彈性能力,我們不得不提到一個(gè)概念:QoS 的概念。什么是 QoS呢?QoS 全稱(chēng)是 Quality of Service,它是 Kubernetes 用來(lái)表達(dá)一個(gè) pod 在資源能力上的服務(wù)質(zhì)量的標(biāo)準(zhǔn),Kubernetes 提供了三類(lèi) QoS Class:

          ?

          • 第一類(lèi)是 Guaranteed,它是一類(lèi)高 QoS Class,一般拿 Guaranteed 配置給一些需要資源保障能力的 pods;


          • 第二類(lèi)是 Burstable,它是中等的一個(gè) QoS label,一般會(huì)為一些希望有彈性能力的 pod 來(lái)配置 Burstable;


          • 第三類(lèi)是 BestEffort,它是低QoS Class,通過(guò)名字我們也知道,它是一種盡力而為式的服務(wù)質(zhì)量,K8S不承諾保障這類(lèi)Pods服務(wù)質(zhì)量。


          K8s 其實(shí)有一個(gè)不太好的地方,就是用戶沒(méi)法直接指定自己的 pod 是屬于哪一類(lèi) QoS,而是通過(guò) request 和 limit 的組合來(lái)自動(dòng)地映射上 QoS Class。


          通過(guò)上圖的例子,大家可以看到:假如我提交的是上面的一個(gè) spec,在 spec 提交成功之后,Kubernetes 會(huì)自動(dòng)給補(bǔ)上一個(gè) status,里面是 qosClass: Guaranteed,用戶自己提交的時(shí)候,是沒(méi)法定義自己的 QoS 等級(jí)。所以將這種方式稱(chēng)之為隱性的 QoS class 用法。


          Pod QoS 配置


          接下來(lái)介紹一下,我們?cè)趺赐ㄟ^(guò) request 和 limit 的組合來(lái)確定我們想要的 QoS level。


          • Guaranteed Pod



          首先我們?nèi)绾蝿?chuàng)建出來(lái)一個(gè) Guaranteed Pod?


          Kubernetes 里面有一個(gè)要求:如果你要?jiǎng)?chuàng)建出一個(gè) Guaranteed Pod,那么你的基礎(chǔ)資源(包括 CPU 和 memory),必須它的 request==limit,其他的資源可以不相等。只有在這種條件下,它創(chuàng)建出來(lái)的 pod 才是一種 Guaranteed Pod,否則它會(huì)屬于 Burstable,或者是 BestEffort Pod。


          • Burstable Pod

          ?

          然后看一下,我們?cè)趺磩?chuàng)建出來(lái)一個(gè) Burstable Pod,Burstable Pod 的范圍比較寬泛,它只要滿足 CPU/Memory ?的 request 和 limit 不相等,它就是一種 Burstable Pod。



          比如說(shuō)上面的例子,可以不用填寫(xiě) memory 的資源,只要填寫(xiě) CPU 的資源,它就是一種 Burstable Pod。


          • BestEffort Pod

          ?

          ?

          第三類(lèi) BestEffort Pod,它也是條件比較死的一種使用方式。它必須是所有資源的 request/limit 都不填,才是一種 BestEffort Pod。


          所以這里可以看到,通過(guò) request 和 limit 不同的用法,可以組合出不同的 Pod QoS。


          不同的 QoS 表現(xiàn)


          接下來(lái),為大家介紹一下:不同的 QoS 在調(diào)度和底層表現(xiàn)有什么樣的不同?


          不同的 QoS,它其實(shí)在調(diào)度和底層表現(xiàn)上都有一些不一樣。比如說(shuō)調(diào)度表現(xiàn),調(diào)度器只會(huì)使用 request 進(jìn)行調(diào)度,也就是說(shuō)不管你配了多大的 limit,它都不會(huì)進(jìn)行調(diào)度使用。


          在底層上,不同的 Qos 表現(xiàn)更不相同。比如說(shuō) CPU,它是按 request 來(lái)劃分權(quán)重的,不同的 QoS,它的 request 是完全不一樣的,比如說(shuō)像 Burstable 和 BestEffort,它可能 request 可以填很小的數(shù)字或者不填,這樣的話,它的時(shí)間片權(quán)重其實(shí)是非常低的。像 BestEffort,它的權(quán)重可能只有 2,而 Burstable 或 Guaranteed,它的權(quán)重可以多到幾千。


          另外,當(dāng)我們開(kāi)啟了 kubelet 的一個(gè)特性,叫 cpu-manager-policy=static 的時(shí)候,我們 Guaranteed Qos,如果它的 request 是一個(gè)整數(shù)的話,比如說(shuō)配了 2,它會(huì)對(duì) Guaranteed Pod 進(jìn)行綁核。


          具體的如下圖所示,它分配 CPU0 和 CPU1 給 Guaranteed Pod。



          非整數(shù)的 Guaranteed/Burstable/BestEffort,它們的 CPU 會(huì)放在一塊,組成一個(gè) CPU share pool,比如說(shuō)像上面這個(gè)例子,這臺(tái)節(jié)點(diǎn)假如說(shuō)有 8 個(gè)核,已經(jīng)分配了 2 個(gè)核給整數(shù)的 Guaranteed 綁核,那么剩下的 6 個(gè)核 CPU2~CPU7,它會(huì)被非整數(shù)的 Guaranteed/Burstable/BestEffort 共享,然后它們會(huì)根據(jù)不同的權(quán)重劃分時(shí)間片來(lái)使用 6 個(gè)核的 CPU。


          另外在 memory 上也會(huì)按照不同的 QoS 進(jìn)行劃分 OOMScore。


          • 比如說(shuō) Guaranteed Pod,會(huì)固定配置默認(rèn)的 -998 的 OOMScore;


          • 而 Burstable Pod 會(huì)根據(jù) Pod 內(nèi)存設(shè)計(jì)的大小和節(jié)點(diǎn)內(nèi)存的比例來(lái)分配 2-999 的 OOMScore;


          • BestEffort Pod 會(huì)固定分配 1000 的 OOMScore,OOMScore 得分越高的話,在物理機(jī)出現(xiàn) OOM 的時(shí)候會(huì)優(yōu)先被 kill 掉。


          另外在節(jié)點(diǎn)上的 eviction 動(dòng)作上,不同的 QoS?行為也是不一樣的,比如說(shuō)發(fā)生 eviction 的時(shí)候,會(huì)優(yōu)先考慮驅(qū)逐 BestEffort 的 pod。所以不同的 QoS?在底層的表現(xiàn)是截然不同的。這反過(guò)來(lái)也要求我們?cè)谏a(chǎn)過(guò)程中,根據(jù)不同業(yè)務(wù)的要求和屬性來(lái)配置資源的 Limits 和 Request,做到合理的規(guī)劃 QoS?Class。


          資源 Quota


          在生產(chǎn)中我們還會(huì)遇到一個(gè)場(chǎng)景:假如集群是由多個(gè)人同時(shí)提交的,或者是多個(gè)業(yè)務(wù)同時(shí)在使用,我們肯定要限制某個(gè)業(yè)務(wù)或某個(gè)人提交的總量,防止整個(gè)集群的資源都會(huì)被一個(gè)業(yè)務(wù)使用掉,導(dǎo)致另一個(gè)業(yè)務(wù)沒(méi)有資源使用。

          ?


          Kubernetes 給我們提供了一個(gè)能力叫?ResourceQuota。它可以做到限制 namespace 資源用量。具體的做法如上圖右側(cè)的 yaml 所示,可以看到它的 spec 包括了一個(gè) hard 和 scopeSelector。


          hard 內(nèi)容其實(shí)和 Resourcelist 很像,這里可以填一些基礎(chǔ)的資源。但是它比 ResourceList 更豐富一點(diǎn),它還可以填寫(xiě)一些 Pod,這樣可以限制 Pod 數(shù)量。另外,scopeSelector 還為這個(gè) ResourceQuota 提供了更豐富的索引能力。


          比如上面的例子中,索引出非 BestEffort 的 pod,限制的 cpu 是 1000 個(gè),memory 是 200G,Pod 是 10 個(gè)。ScopeName 除了提供 NotBestEffort,它還提供了更豐富的索引范圍,包括 Terminating/Not Terminating, BestEffort/NotBestEffort, PriorityClass。


          當(dāng)我們創(chuàng)建了這樣的 ResourceQuota 作用于集群,如果用戶真的用超了資源,表現(xiàn)的行為是:它在提交 Pod spec 時(shí),會(huì)收到一個(gè) forbidden 的 403 錯(cuò)誤,提示 exceeded quota。這樣用戶就無(wú)法再提交對(duì)應(yīng)用超的資源了。而如果再提交一個(gè)沒(méi)有包含在這個(gè) ResourceQuota 里的資源,還是能成功的。


          這就是 Kubernetes 里 ResourceQuota 的基本用法。我們可以用 ResourceQuota 方法來(lái)做到限制每一個(gè) namespace 的資源用量,從而保證其他用戶的資源使用。


          小結(jié):如何滿足 Pod 資源要求?


          上面介紹完了基礎(chǔ)資源的使用方式,也就是我們做到了如何滿足 Pod 資源要求。下面做一個(gè)小結(jié):


          • Pod 要配置合理的資源要求:CPU/Memory/EphemeralStorage/GPU;

          ?

          • 通過(guò) Request 和 Limit 來(lái)為不同業(yè)務(wù)特點(diǎn)的 Pod 選擇不同的 QoS。Guaranteed -?敏感型,需要業(yè)務(wù)保障;Burstable -?次敏感型,需要彈性業(yè)務(wù)BestEffort -?可容忍性業(yè)務(wù);

          ?

          • 為每個(gè) NS 配置 ResourceQuota 來(lái)防止過(guò)量使用,保障其他人的資源可用。


          2. 如何滿足 Pod 與 Pod 關(guān)系要求?


          接下來(lái)給大家介紹一下 Pod 的關(guān)系調(diào)度,首先是 Pod 和 Pod 的關(guān)系調(diào)度。我們?cè)谄綍r(shí)使用中可能會(huì)遇到一些場(chǎng)景:比如說(shuō)一個(gè) Pod 必須要和另外一個(gè) Pod 放在一起,或者不能和另外一個(gè) Pod 放在一起。


          在這種要求下, Kubernetes 提供了兩類(lèi)能力:


          • 第一類(lèi)能力稱(chēng)之為 Pod 親和調(diào)度:PodAffinity;

          • 第二類(lèi)就是 Pod 反親和調(diào)度:PodAntAffinity。


          Pod 親和調(diào)度



          首先我們來(lái)看 Pod 親和調(diào)度,假如我想把一個(gè) Pod 和另一個(gè) Pod 放在一起,這時(shí)可以看上圖中的實(shí)例寫(xiě)法,填寫(xiě)上 podAffinity,然后填上 required 要求。


          在這個(gè)例子中,必須要調(diào)度到帶了 key: k1 的 Pod 所在的節(jié)點(diǎn),并且打散粒度是按照節(jié)點(diǎn)粒度去打散索引的。這種情況下,假如能找到帶 key: k1 的 Pod 所在節(jié)點(diǎn),就會(huì)調(diào)度成功。假如這個(gè)集群不存在這樣的 Pod 節(jié)點(diǎn),或者是資源不夠的時(shí)候,那就會(huì)調(diào)度失敗。這是一個(gè)嚴(yán)格的親和調(diào)度,我們叫做強(qiáng)制親和調(diào)度。



          有些時(shí)候我們并不需要這么嚴(yán)格的調(diào)度策略。這時(shí)候可以把 required 改成 preferred,變成一個(gè)優(yōu)先親和調(diào)度。也就是優(yōu)先可以調(diào)度帶 key: k2 的 Pod 所在節(jié)點(diǎn)。并且這個(gè) preferred 里面可以是一個(gè) list 選擇,可以填上多個(gè)條件,比如權(quán)重等于 100 的是 key: k2,權(quán)重等于 10 的是 key: k1。那調(diào)度器在調(diào)度的時(shí)候會(huì)優(yōu)先把這個(gè) Pod 分配到權(quán)重分更高的調(diào)度條件節(jié)點(diǎn)上去。


          Pod 反親和調(diào)度


          上面介紹了親和調(diào)度,反親和調(diào)度與親和調(diào)度比較相似。功能上是取反的,但語(yǔ)法基本上是一樣的,僅是 podAffinity 換成了 podAntiAffinity,也是包括?required 強(qiáng)制反親和,以及一個(gè) preferred 優(yōu)先反親和。


          這里舉了兩個(gè)例子:一個(gè)是禁止調(diào)度到帶了 key: k1 標(biāo)簽的 Pod 所在節(jié)點(diǎn);另一個(gè)是優(yōu)先反親和調(diào)度到帶了 key: k2 標(biāo)簽的 Pod 所在節(jié)點(diǎn)。




          Kubernetes 除了 In 這個(gè) Operator 語(yǔ)法之外,還提供了更多豐富的語(yǔ)法組合來(lái)給大家使用。比如說(shuō) In/NotIn/Exists/DoesNotExist 這些組合方式。上圖的例子用的是 In,比如說(shuō)第一個(gè)強(qiáng)制反親和例子里面,相當(dāng)于我們必須要禁止調(diào)度到帶了 key: k1 標(biāo)簽的 Pod 所在節(jié)點(diǎn)。


          同樣的功能也可以使用 Exists,Exists 范圍可能會(huì)比 In 范圍更大,當(dāng) Operator 填了 Exists,就不需要再填寫(xiě) values。它做到的效果就是禁止調(diào)度到帶了 key: k1 標(biāo)簽的 Pod 所在節(jié)點(diǎn),不管 values 是什么值,只要帶了 k1 這個(gè) key 標(biāo)簽的 Pod 所在節(jié)點(diǎn),都不能調(diào)度過(guò)去。


          以上就是 Pod 與 Pod 之間的關(guān)系調(diào)度。


          3. 如何滿足 Pod 與 Node 關(guān)系調(diào)度


          Pod 與 Node 的關(guān)系調(diào)度又稱(chēng)之為 Node 親和調(diào)度,主要給大家介紹兩類(lèi)使用方法。


          NodeSelector



          第一類(lèi)是 NodeSelector,這是一類(lèi)相對(duì)比較簡(jiǎn)單的用法。


          比如說(shuō)有個(gè)場(chǎng)景:必須要調(diào)度 Pod 到帶了 k1: v1 標(biāo)簽的 Node 上,這時(shí)可以在 Pod 的 spec 中填寫(xiě)一個(gè) nodeSelector 要求。nodeSelector 本質(zhì)是一個(gè) map 結(jié)構(gòu),里面可以直接寫(xiě)上對(duì) node 標(biāo)簽的要求,比如 k1: v1。這樣我的 Pod 就會(huì)強(qiáng)制調(diào)度到帶了 k1: v1 標(biāo)簽的 Node 上。


          NodeAffinity


          NodeSelector 雖然是一個(gè)非常簡(jiǎn)單的用法,但這個(gè)用法有個(gè)問(wèn)題:它只能強(qiáng)制親和調(diào)度,假如我想優(yōu)先調(diào)度,就沒(méi)法用 nodeSelector 來(lái)做。于是 Kubernetes 社區(qū)又新加了一個(gè)用法,叫做 NodeAffinity。



          它和 PodAffinity 有點(diǎn)類(lèi)似,也提供了兩類(lèi)調(diào)度的策略:


          • 第一類(lèi)是 required,必須調(diào)度到某一類(lèi) Node 上;

          • 第二類(lèi)是 preferred,就是優(yōu)先調(diào)度到某一類(lèi) Node 上。


          它的基本語(yǔ)法和上文中的 PodAffinity 以及 PodAntiAffinity 也是類(lèi)似的。在 Operator 上,NodeAffinity 提供了比 PodAffinity 更豐富的 Operator 內(nèi)容。增加了 Gt 和 Lt,數(shù)值比較的用法。當(dāng)使用 Gt 的時(shí)候,values 只能填寫(xiě)數(shù)字。


          Node 標(biāo)記/容忍

          ?

          還有第三類(lèi)調(diào)度,可以通過(guò)給 Node 打一些標(biāo)記,來(lái)限制 Pod 調(diào)度到某些 Node 上。Kubernetes 把這些標(biāo)記稱(chēng)之為 Taints,它的字面意思是污染。

          ?


          那我們?nèi)绾蜗拗?Pod 調(diào)度到某些 Node 上呢?比如說(shuō)現(xiàn)在有個(gè) node 叫 demo-node,這個(gè)節(jié)點(diǎn)有問(wèn)題,我想限制一些 Pod 調(diào)度上來(lái)。這時(shí)可以給這個(gè)節(jié)點(diǎn)打一個(gè) taints,taints 內(nèi)容包括 key、value、effect:


          • key 就是配置的鍵值;

          • value 就是內(nèi)容;

          • effect 是標(biāo)記了這個(gè) taints 行為是什么。


          目前 Kubernetes 里面有三個(gè) taints 行為:


          • NoSchedule ?禁止新的 Pod 調(diào)度上來(lái);

          • PreferNoSchedul ?盡量不調(diào)度到這臺(tái);

          • NoExecute ?會(huì) evict 沒(méi)有對(duì)應(yīng) toleration 的 Pods,并且也不會(huì)調(diào)度新的上來(lái)。這個(gè)策略是非常嚴(yán)格的,大家在使用的時(shí)候要小心一點(diǎn)。


          如上圖綠色部分,給這個(gè) demo-node 打了 k1=v1,并且 effect 等于 NoSchedule 之后。它的效果是:新建的 Pod ?沒(méi)有專(zhuān)門(mén)容忍這個(gè) taint,那就沒(méi)法調(diào)度到這個(gè)節(jié)點(diǎn)上去了。


          假如有些 Pod 是可以調(diào)度到這個(gè)節(jié)點(diǎn)上的,應(yīng)該怎么來(lái)做呢?這時(shí)可以在 Pod 上打一個(gè) Pod Tolerations。從上圖中藍(lán)色部分可以看到:在 Pod 的 spec 中填寫(xiě)一個(gè) Tolerations,它里面也包含了 key、value、effect,這三個(gè)值和 taint 的值是完全對(duì)應(yīng)的,taint 里面的 key,value,effect 是什么內(nèi)容,Tolerations 里面也要填寫(xiě)相同的內(nèi)容。


          Tolerations 還多了一個(gè)選項(xiàng) Operator,Operator 有兩個(gè) value:Exists/Equal。Equal 的概念是必須要填寫(xiě) value,而 Exists 就跟上文說(shuō)的 NodeAffinity 一樣,不需要填寫(xiě) value,只要 key 值對(duì)上了,就認(rèn)為它跟 taints 是匹配的。


          上圖中的例子,給 Pod 打了一個(gè) Tolerations,只有打了這個(gè) Tolerations 的 Pod,才能調(diào)度到綠色部分打了 taints 的 Node 上去。這樣的好處是 Node 可以有選擇性的調(diào)度一些 Pod 上來(lái),而不是所有的 Pod 都可以調(diào)度上來(lái),這樣就做到了限制某些 Pod 調(diào)度到某些 Node 的效果。


          4. 小結(jié)


          我們已經(jīng)介紹完了 Pod/Node 的特殊關(guān)系和條件調(diào)度,來(lái)做一下小結(jié)。


          首先假如有需求是處理 Pod 與 Pod 的時(shí)候,比如 Pod 和另一個(gè) Pod 有親和的關(guān)系或者是互斥的關(guān)系,可以給它們配置下面的參數(shù):


          • PodAffinity

          • PodAntiAffinity


          假如存在 Pod 和 Node 有親和關(guān)系,可以配置下面的參數(shù):


          • NodeSelector

          • NodeAffinity


          假如有些 Node 是限制某些 Pod 調(diào)度的,比如說(shuō)一些故障的 Node,或者說(shuō)是一些特殊業(yè)務(wù)的 Node,可以配置下面的參數(shù):


          • Node -- Taints

          • Pod -- Tolerations






          Kubernetes 高級(jí)調(diào)度能力


          介紹完了基礎(chǔ)調(diào)度能力之后,下面來(lái)了解一下高級(jí)調(diào)度能力。


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


          優(yōu)先級(jí)調(diào)度和搶占,主要概念有:


          • Priority

          • Preemption


          首先來(lái)看一下調(diào)度過(guò)程提到的四個(gè)特點(diǎn),我們?nèi)绾巫龅郊旱暮侠砝茫?/span>當(dāng)集群資源足夠的話,只需要通過(guò)基礎(chǔ)調(diào)度能力就能組合出合理的使用方式。但是假如資源不夠,我們?cè)趺醋龅郊旱暮侠砝媚兀?/span>通常的策略有兩類(lèi):


          • 先到先得策略 (FIFO) ?-簡(jiǎn)單、相對(duì)公平,上手快;

          • 優(yōu)先級(jí)策略 (Priority) - 比較符合日常公司業(yè)務(wù)特點(diǎn)。


          在實(shí)際生產(chǎn)中,如果使用先到先得策略,反而是一種不公平的策略,因?yàn)楣緲I(yè)務(wù)里面肯定是有高優(yōu)先級(jí)的業(yè)務(wù)和低優(yōu)先級(jí)的業(yè)務(wù),所以優(yōu)先級(jí)策略會(huì)比先到先得策略更能夠符合日常公司業(yè)務(wù)特點(diǎn)。



          接下來(lái)介紹一下優(yōu)先級(jí)策略下的優(yōu)先級(jí)調(diào)度是什么樣的一個(gè)概念。


          比如說(shuō)有一個(gè) Node 已經(jīng)被一個(gè) Pod 占用了,這個(gè) Node 只有 2 個(gè) CPU。另一個(gè)高優(yōu)先級(jí) Pod 來(lái)的時(shí)候,低優(yōu)先級(jí)的 Pod 應(yīng)該把這兩個(gè) CPU 讓給高優(yōu)先級(jí)的 Pod 去使用。低優(yōu)先級(jí)的 Pod 需要回到等待隊(duì)列,或者是業(yè)務(wù)重新提交。這樣的流程就是優(yōu)先級(jí)搶占調(diào)度的一個(gè)流程。

          ?

          在 Kubernetes 里,PodPriority 和 Preemption,就是優(yōu)先級(jí)和搶占的特點(diǎn),在 v1.14 版本中變成了 stable。并且 PodPriority 和 Preemption 功能默認(rèn)都是開(kāi)啟的。

          ?

          2. 優(yōu)先級(jí)調(diào)度配置


          怎么使用?


          如何使用優(yōu)先級(jí)調(diào)度呢?需要?jiǎng)?chuàng)建一個(gè) priorityClass,然后再為每個(gè) Pod 配置上不同的 priorityClassName,這樣就完成了優(yōu)先級(jí)以及優(yōu)先級(jí)調(diào)度的配置。


          ?

          首先來(lái)看一下如何創(chuàng)建一個(gè) priorityClass。上圖右側(cè)定義了兩個(gè) demo:


          • 一個(gè)是創(chuàng)建了名為 high 的 priorityClass,它是高優(yōu)先級(jí),得分為 10000;

          • 另一個(gè)創(chuàng)建了名為 low 的 priorityClass,它的得分是 100。


          同時(shí)在第三部分給 Pod1 配置上了 high,Pod2 上配置了 low priorityClassName,藍(lán)色部分顯示了 pod 的 spec 的配置位置,就是在 spec 里面填寫(xiě)一個(gè) priorityClassName: high。這樣 Pod 和 priorityClass 做完配置,就為集群開(kāi)啟了一個(gè) priorityClass 調(diào)度。


          內(nèi)置優(yōu)先級(jí)配置


          當(dāng)然 Kubernetes 里面還內(nèi)置了默認(rèn)的優(yōu)先級(jí),如 DefaultpriorityWhenNoDefaultClassExistis。如果集群中沒(méi)有配置 DefaultpriorityWhenNoDefaultClassExistis,那所有的 Pod 關(guān)于此項(xiàng)數(shù)值都會(huì)被設(shè)置成 0。


          用戶可配置的最大優(yōu)先級(jí)限制為:HighestUserDefinablePriority = 10000000000(10 億),會(huì)小于系統(tǒng)級(jí)別優(yōu)先級(jí):SystemCriticalPriority = 20000000000(20 億)。


          其中內(nèi)置了兩個(gè)系統(tǒng)級(jí)別優(yōu)先級(jí):


          • system-cluster-critical

          • system-node-critical

          ?

          以上就是 K8s 優(yōu)先級(jí)調(diào)度里內(nèi)置的優(yōu)先級(jí)配置。

          ?

          3. 優(yōu)先級(jí)調(diào)度過(guò)程


          下面介紹簡(jiǎn)單的優(yōu)先級(jí)調(diào)度過(guò)程:


          首先介紹只觸發(fā)優(yōu)先級(jí)調(diào)度但是沒(méi)有觸發(fā)搶占調(diào)度的流程。


          假如有一個(gè) Pod1 和 Pod2,Pod1 配置了高優(yōu)先級(jí),Pod2 配置了低優(yōu)先級(jí)。同時(shí)提交 Pod1 和 Pod2 到調(diào)度隊(duì)列里。



          調(diào)度器處理隊(duì)列的時(shí)候會(huì)挑選一個(gè)高優(yōu)先級(jí)的 Pod1 進(jìn)行調(diào)度,經(jīng)過(guò)調(diào)度過(guò)程把 Pod1 綁定到 Node1 上。



          其次再挑選一個(gè)低優(yōu)先的 Pod2 進(jìn)行同樣的過(guò)程,綁定到 Node1 上。



          這樣就完成了一個(gè)簡(jiǎn)單的優(yōu)先級(jí)調(diào)度的流程。


          4. 優(yōu)先級(jí)搶占過(guò)程


          假如高優(yōu)先級(jí)的 Pod 在調(diào)度的時(shí)候沒(méi)有資源,那么會(huì)是一個(gè)怎么樣的流程呢?


          首先是跟上文同樣的場(chǎng)景,但是提前在 Node1 上放置了 Pod0,占去了一部分資源。同樣有 Pod1 和 Pod2 待調(diào)度,Pod1 的優(yōu)先級(jí)大于 Pod2。



          假如先把 Pod2 調(diào)度上去,它經(jīng)過(guò)一系列的調(diào)度過(guò)程綁定到了 Node1 上。



          緊接著再調(diào)度 Pod1,因?yàn)?Node1 上已經(jīng)存在了兩個(gè) Pod,資源不足,所以會(huì)遇到調(diào)度失敗。



          在調(diào)度失敗時(shí) Pod1 會(huì)進(jìn)入搶占流程,這時(shí)會(huì)進(jìn)行整個(gè)集群的節(jié)點(diǎn)篩選,最后挑出要搶占的 Pod 是 Pod2,此時(shí)調(diào)度器會(huì)把 Pod2 從 Node1 上移除數(shù)據(jù)。



          再把 Pod1 調(diào)度到 Node1 上。這樣就完成了一次搶占調(diào)度的流程。



          5. 優(yōu)先級(jí)搶占策略


          接下來(lái)介紹具體的搶占策略和搶占的流程:



          上圖右側(cè)是整個(gè) kube-scheduler?優(yōu)先級(jí)搶占的調(diào)度流程。首先一個(gè) Pod 進(jìn)入搶占的時(shí)候,會(huì)判斷 Pod 是否擁有搶占的資格,有可能上次已經(jīng)搶占過(guò)一次。如果符合搶占資格,它會(huì)先對(duì)所有的節(jié)點(diǎn)進(jìn)行一次過(guò)濾,過(guò)濾出符合這次搶占要求的節(jié)點(diǎn),如果不符合就過(guò)濾掉這批節(jié)點(diǎn)。


          接著從過(guò)濾剩下的節(jié)點(diǎn)中,挑選出合適的節(jié)點(diǎn)進(jìn)行搶占。這次搶占的過(guò)程會(huì)模擬一次調(diào)度,把上面優(yōu)先級(jí)低的 Pod 先移除出去,再把待搶占的 Pod 嘗試能否放置到此節(jié)點(diǎn)上;然后通過(guò)這個(gè)過(guò)程選出一批節(jié)點(diǎn),進(jìn)入下一個(gè)過(guò)程?ProcessPreemptionWithExtenders。這是一個(gè)擴(kuò)展的鉤子,用戶可以在這里加一些自己搶占節(jié)點(diǎn)的策略,如果沒(méi)有擴(kuò)展鉤子,這里面是不做任何動(dòng)作的。


          接下來(lái)的流程叫做 PickOneNodeForPreemption,就是從上面 selectNodeForPreemption list 里面挑選出最合適的一個(gè)節(jié)點(diǎn),這是有一定的策略的。上圖左側(cè)簡(jiǎn)單介紹了一下策略:


          • 優(yōu)先選擇打破 PDB 最少的節(jié)點(diǎn);

          • 其次選擇待搶占 Pods 中最大優(yōu)先級(jí)最小的節(jié)點(diǎn);

          • 再次選擇待搶占 Pods 優(yōu)先級(jí)加和最小的節(jié)點(diǎn);

          • 接下來(lái)選擇待搶占 Pods 數(shù)目最小的節(jié)點(diǎn);

          • 最后選擇擁有最晚啟動(dòng) Pod 的節(jié)點(diǎn)。


          通過(guò)這五步串行策略過(guò)濾之后,會(huì)選出一個(gè)最合適的節(jié)點(diǎn)。然后對(duì)這個(gè)節(jié)點(diǎn)上待搶占的 Pod 進(jìn)行 delete,這樣就完成了一次待搶占的過(guò)程。


          6. 小結(jié)


          簡(jiǎn)單介紹了一下調(diào)度的高級(jí)策略,在集群資源緊張的時(shí)候也能合理調(diào)度資源。我們回顧一下做了哪些事情:


          • 創(chuàng)建自定義的一些優(yōu)先級(jí)類(lèi)別 (PriorityClass);

          • 給不同類(lèi)型 Pods 配置不同的優(yōu)先級(jí) (PriorityClassName);

          • 通過(guò)組合不同類(lèi)型 Pods 運(yùn)行和優(yōu)先級(jí)搶占讓集群資源和調(diào)度彈性起來(lái)。





          推薦閱讀



          學(xué)習(xí)交流 Go 語(yǔ)言,掃碼回復(fù)「進(jìn)群」即可


          站長(zhǎng) polarisxu

          自己的原創(chuàng)文章

          不限于 Go 技術(shù)

          職場(chǎng)和創(chuàng)業(yè)經(jīng)驗(yàn)


          Go語(yǔ)言中文網(wǎng)

          每天為你

          分享 Go 知識(shí)

          Go愛(ài)好者值得關(guān)注




          戳原文,免費(fèi)觀看云原生公開(kāi)課!
          瀏覽 61
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大鸡巴视频在线观看免费 | 欧美户外操逼 | 青娱乐免费视频在线 | 99视频在线观看免费 | 久久国内综合视频 |