影響 Kubernetes 調(diào)度的決策因素

本文永久鏈接:?https://www.xtplayer.cn/kubernetes/scheduler/influencing-kubernetes-scheduler-decisions/

為了提高節(jié)點(diǎn)資源的最大利用率,調(diào)度程序使用復(fù)雜的算法來確保最有效的 Pod 調(diào)度。在本文中,我們討論調(diào)度程序如何選擇最佳節(jié)點(diǎn)來運(yùn)行 Pod,以及如何影響其決策。

哪個(gè)節(jié)點(diǎn)具有可用資源?

選擇適當(dāng)?shù)墓?jié)點(diǎn)時(shí),調(diào)度程序會(huì)檢查每個(gè)節(jié)點(diǎn)是否有足夠的資源滿足 Pod 調(diào)度。如果您已經(jīng)聲明 Pod 所需的 CPU 和內(nèi)存量(通過請(qǐng)求和限制),調(diào)度程序?qū)⑹褂靡韵鹿絹碛?jì)算給定節(jié)點(diǎn)上的可用內(nèi)存:

調(diào)度可用內(nèi)存 = 節(jié)點(diǎn)總內(nèi)存 - 已預(yù)留內(nèi)存

保留內(nèi)存是指:

Kubernetes 守護(hù)進(jìn)程使用的內(nèi)存,例如:kubeletcontainerd(一種容器運(yùn)行時(shí))。

節(jié)點(diǎn)操作系統(tǒng)使用的內(nèi)存,例如:內(nèi)核守護(hù)程序。

通過使用此方程式,調(diào)度程序可確保由于過多 Pod 競(jìng)爭(zhēng)消耗節(jié)點(diǎn)所有可用資源,從而導(dǎo)致節(jié)點(diǎn)資源耗盡引起其他系統(tǒng)異常,比如系統(tǒng)觸發(fā) oom。

影響調(diào)度過程

在不受用戶影響的情況下,調(diào)度程序在將 Pod 調(diào)度到節(jié)點(diǎn)時(shí)執(zhí)行以下步驟:

調(diào)度程序檢測(cè)到已創(chuàng)建新的 Pod,但尚未將其分配給節(jié)點(diǎn);

它檢查 Pod 需求,并相應(yīng)地篩選出所有不合適的節(jié)點(diǎn);

根據(jù)權(quán)重將剩下的節(jié)點(diǎn)進(jìn)行排序,權(quán)重最高的排在第一位;

調(diào)度程序選擇排序列表中的第一個(gè)節(jié)點(diǎn),然后將 Pod 分配給它。

通常,我們會(huì)讓調(diào)度程序自動(dòng)選擇合適的節(jié)點(diǎn)(前提是 Pod 配置了資源請(qǐng)求和限制)。但是,有時(shí)可能需要通過強(qiáng)制調(diào)度程序選擇特定節(jié)點(diǎn)或手動(dòng)向多個(gè)節(jié)點(diǎn)添加權(quán)重來影響此決策,以使其比其他節(jié)點(diǎn)適合 Pod 調(diào)度。

讓我們看看我們?nèi)绾巫龅竭@一點(diǎn):

節(jié)點(diǎn)名稱

在最簡(jiǎn)單的節(jié)點(diǎn)選擇配置中,您只需在?.spec.nodeName?中指定其名稱,就可以強(qiáng)制 Pod 在指定節(jié)點(diǎn)上運(yùn)行。例如,以下 YAML 定義 Pod 強(qiáng)制在 app-prod01 上進(jìn)行調(diào)度:

YAML

apiVersion:v1

kind:Pod

metadata:

name:nginx

spec:

containers:

-name:nginx

image:nginx

nodeName:app-prod01

請(qǐng)注意,由于以下原因,此方法是最簡(jiǎn)單但最不推薦的節(jié)點(diǎn)選擇方法:

如果由于某種原因無法找到指定名稱的節(jié)點(diǎn)(例如,更改了主機(jī)名),則 Pod 將不會(huì)運(yùn)行。

如果該節(jié)點(diǎn)沒有 Pod 運(yùn)行所需的資源,則 Pod 會(huì)運(yùn)行失敗,并且也不會(huì)將該 Pod 調(diào)度到其他節(jié)點(diǎn)。

這會(huì)導(dǎo)致 Pods 與它們的節(jié)點(diǎn)緊密耦合,這是一種糟糕的設(shè)計(jì)實(shí)踐。

節(jié)點(diǎn)選擇器

覆蓋調(diào)度程序決策的第一個(gè)最簡(jiǎn)單的方法是使用 Pod 定義或 Pod 模板(如果使用的是 Deployments 之類的控制器)中的?.spec.nodeSelector?參數(shù)。nodeSelector 接受?一個(gè)或多個(gè)?鍵-值對(duì)標(biāo)簽,這些?鍵-值對(duì)?標(biāo)簽必須在節(jié)點(diǎn)設(shè)置才能正常的調(diào)度 Pod。假設(shè)您最近購(gòu)買了兩臺(tái)配備 SSD 磁盤的計(jì)算機(jī),您希望數(shù)據(jù)庫相關(guān)所有的 Pod 在 SSD 支持的節(jié)點(diǎn)上進(jìn)行調(diào)度,以獲得最佳的數(shù)據(jù)庫性能。DB Pod 的 Pod YAML 可能如下所示:

YAML

apiVersion:v1

kind:Pod

metadata:

name:db

spec:

containers:

-name:mongodb

image:mongo

nodeSelector:

disktype:ssd

根據(jù)該定義,當(dāng)調(diào)度程序選擇合適的 Pod 分配節(jié)點(diǎn)時(shí),將僅考慮具有?disktype=ssd?標(biāo)簽的節(jié)點(diǎn)。

此外,您可以使用自動(dòng)分配給節(jié)點(diǎn)的任何內(nèi)置標(biāo)簽來操縱選擇決策。例如,節(jié)點(diǎn)的主機(jī)名(kubernetes.io/hostname),體系結(jié)構(gòu)(kubernetes.io/arch),操作系統(tǒng)(kubernetes.io/os)等均可用于節(jié)點(diǎn)選擇。

節(jié)點(diǎn)親和性

當(dāng)您需要選擇特定的節(jié)點(diǎn)來運(yùn)行我們的 Pod 時(shí),節(jié)點(diǎn)選擇非常有用。但是選擇節(jié)點(diǎn)的方式是有限的,只有與所有定義的標(biāo)簽匹配的節(jié)點(diǎn)才被考慮用于 Pod 放置。Node Affinity 通過允許您定義硬節(jié)點(diǎn)和軟節(jié)點(diǎn)需求,為您提供了更大的靈活性。硬性要求必須在要選擇的節(jié)點(diǎn)上匹配。另一方面,軟條件允許您為具有特定標(biāo)簽的節(jié)點(diǎn)增加更多權(quán)重,以使它們在列表中的位置比對(duì)等節(jié)點(diǎn)更高。沒有軟需求標(biāo)簽的節(jié)點(diǎn)將不被忽略,但它們權(quán)重更小。

讓我們舉個(gè)例子:我們的數(shù)據(jù)庫是 I/O 密集型的。我們需要數(shù)據(jù)庫 Pods 始終在 SSD 支持的節(jié)點(diǎn)上運(yùn)行。此外,如果 Pod 部署在區(qū)域 zone1 或 zone2 中的節(jié)點(diǎn)上,因?yàn)樗鼈冊(cè)谖锢砩细拷鼞?yīng)用程序節(jié)點(diǎn),那么它們的延遲會(huì)更短。滿足我們需求的 Pod 定義可能如下所示:

YAML

apiVersion:v1

kind:Pod

metadata:

name:db

spec:

affinity:

nodeAffinity:

requiredDuringSchedulingIgnoredDuringExecution:

nodeSelectorTerms:

-matchExpressions:

-key:disk-type

operator:In

values:

-ssd

preferredDuringSchedulingIgnoredDuringExecution:

-weight:1

preference:

matchExpressions:

-key:zone

operator:In

values:

-zone1

-zone2

containers:

-name:db

image:mongo

nodeAffinity 節(jié)使用以下參數(shù)來定義硬性要求和軟性要求:

requiredDuringSchedulingIgnoredDuringExecution:部署 DB Pod 時(shí),節(jié)點(diǎn)必須具有 disk-type=ssd。

preferredDuringSchedulingIgnoredDuringExecution:?當(dāng)對(duì)節(jié)點(diǎn)進(jìn)行排序時(shí),調(diào)度器會(huì)給予標(biāo)簽為zone=zone1zone=zone2的節(jié)點(diǎn)更高的權(quán)重。如果有disk-type=ssdzone=zone1的節(jié)點(diǎn),則優(yōu)先選擇 disk-type=ssd 且無 zone 標(biāo)簽的節(jié)點(diǎn)或指向其他 zone 的節(jié)點(diǎn)。權(quán)重可以是 1 到 100 之間的任意值,權(quán)重號(hào)賦予匹配節(jié)點(diǎn)相對(duì)于其他節(jié)點(diǎn)更高的權(quán)重。數(shù)字越大,權(quán)值越高。

注意,在進(jìn)行選擇時(shí),節(jié)點(diǎn)親和性允許您在選擇目標(biāo)節(jié)點(diǎn)上應(yīng)該存在(或不存在)哪些標(biāo)簽時(shí)擁有更多的自由。在本例中,我們使用 In 操作符定義了多個(gè)標(biāo)簽,目標(biāo)節(jié)點(diǎn)上存在任何一個(gè)標(biāo)簽即可。其他運(yùn)算符是 NotIn、Exists、doesnoexistists、Lt(小于)和 Gt(大于)。值得注意的是,NotIn 和 doesnot existist 實(shí)現(xiàn)了所謂的節(jié)點(diǎn)反親和性。

節(jié)點(diǎn)親和性和節(jié)點(diǎn)選擇器不是互斥的,它們可以共存于同一個(gè)定義文件中。但是,在這種情況下,節(jié)點(diǎn)選擇器和節(jié)點(diǎn)親和性硬要求必須匹配。

Pod 親和性

節(jié)點(diǎn)選擇器和節(jié)點(diǎn)親和性(以及反親和性)幫助我們影響調(diào)度器關(guān)于在何處放置 Pods 的決策。但是,它只允許您基于節(jié)點(diǎn)上的標(biāo)簽進(jìn)行選擇。它不關(guān)心 Pod 本身的標(biāo)簽。您可能需要在以下情況下根據(jù) Pod 標(biāo)簽進(jìn)行選擇:

需要將所有中間件 Pod 放在同一個(gè)物理節(jié)點(diǎn)上,與那些具有 role=front 標(biāo)簽的 Pod 一起,以減少它們之間的網(wǎng)絡(luò)延遲。

作為一種安全最佳實(shí)踐,我們不希望中間件 Pod 與處理用戶身份驗(yàn)證的 Pod 共存(role=auth)。這不是一個(gè)嚴(yán)格的要求。

如您所見,這些要求不能用節(jié)點(diǎn)選擇器或親和性來滿足,因?yàn)樵谶x擇過程中不考慮 Pod 標(biāo)簽——只考慮節(jié)點(diǎn)標(biāo)簽。

為了滿足這些需求,我們使用 Pod 親和性和反親和性。本質(zhì)上,它們的工作方式與節(jié)點(diǎn)親和性和反親和性相同。必須滿足硬性要求來選擇目標(biāo)節(jié)點(diǎn),而軟條件增加了擁有所選節(jié)點(diǎn)的機(jī)會(huì)(權(quán)重),但不是嚴(yán)格要求。讓我們舉個(gè)例子:

YAML

apiVersion:v1

kind:Pod

metadata:

name:middleware

spec:

affinity:

podAffinity:

requiredDuringSchedulingIgnoredDuringExecution:

-labelSelector:

matchExpressions:

-key:role

operator:In

values:

-frontend

topologyKey:kubernetes.io/hostname

podAntiAffinity:

preferredDuringSchedulingIgnoredDuringExecution:

-weight:100

podAffinityTerm:

labelSelector:

matchExpressions:

-key:role

operator:In

values:

-auth

topologyKey:kubernetes.io/hostname

containers:

-name:middleware

image:redis

在上面的 Pod 定義文件中,我們對(duì)硬性要求和軟性要求進(jìn)行了如下設(shè)置:

requiredDuringSchedulingIgnoredDuringExecution:我們的 Pod 必須在具有標(biāo)簽為 app-front 的 Pod 節(jié)點(diǎn)上調(diào)度。

preferredDuringSchedulingIgnoredDuringExecution:我們的 Pod 不應(yīng)該(但它可以)被調(diào)度到運(yùn)行帶有標(biāo)簽為 role=auth 的 Pod 的節(jié)點(diǎn)上。與節(jié)點(diǎn)親和性一樣,soft requirement 將權(quán)重從 1 設(shè)置為 100,以增加節(jié)點(diǎn)相對(duì)于其他節(jié)點(diǎn)的概率。在我們的示例中,軟需求被放置在 poantiaffinity 中,導(dǎo)致運(yùn)行具有標(biāo)簽為 role=auth 的 Pod 的節(jié)點(diǎn)在調(diào)度程序做出決定時(shí)被選中的可能性更小。

topologyKey?用于對(duì)規(guī)則將應(yīng)用于哪個(gè)領(lǐng)域做出更細(xì)粒度的決策。topologyKey 接受一個(gè)標(biāo)簽鍵,該標(biāo)簽鍵必須出現(xiàn)在選擇過程中考慮的節(jié)點(diǎn)上。在我們的示例中,我們使用了自動(dòng)填充的標(biāo)簽,該標(biāo)簽在默認(rèn)情況下自動(dòng)添加到所有節(jié)點(diǎn),并引用節(jié)點(diǎn)的主機(jī)名。但是您可以使用其他自動(dòng)填充的標(biāo)簽,甚至是自定義的標(biāo)簽。例如,您可能需要只在具有 rack 或 zone 標(biāo)簽的節(jié)點(diǎn)上應(yīng)用 Pod 親和規(guī)則。

關(guān)于 IgnoredDuringExecution 的注釋

您可能已經(jīng)注意到,硬需求和軟需求都有?IgnoredDuringExecution?后綴。這意味著在做出調(diào)度決策之后,調(diào)度程序?qū)⒉粫?huì)嘗試更改已經(jīng)放置的 Pods,即使條件發(fā)生了變化。例如,根據(jù)節(jié)點(diǎn)親和性規(guī)則,將一個(gè) Pod 調(diào)度到一個(gè)具有標(biāo)簽為 app=prod 的節(jié)點(diǎn)上。如果該標(biāo)簽被更改為 app=dev, 舊 Pod 不會(huì)被終止,并在另一個(gè)有 app=prod 標(biāo)簽的節(jié)點(diǎn)上啟動(dòng)新的 Pod。這個(gè)行為在將來可能會(huì)改變,以允許調(diào)度程序在部署后繼續(xù)檢查節(jié)點(diǎn)和 Pod 的關(guān)聯(lián)性(和反關(guān)聯(lián)性)規(guī)則。

污點(diǎn)與容忍

在某些場(chǎng)景中,您可能希望阻止將 Pod 調(diào)度到特定節(jié)點(diǎn)。可能您正在運(yùn)行測(cè)試或掃描此節(jié)點(diǎn)以查找威脅,而您不希望應(yīng)用程序受到影響。節(jié)點(diǎn)反親和性可以實(shí)現(xiàn)這一目標(biāo)。但是,這是一個(gè)重大的管理負(fù)擔(dān),因?yàn)槟枰虿渴鸬郊旱拿總€(gè)新 Pod 添加反關(guān)聯(lián)規(guī)則。對(duì)于這種場(chǎng)景,您應(yīng)該使用污點(diǎn)。

當(dāng)一個(gè)節(jié)點(diǎn)配置了污點(diǎn)時(shí),除非 Pod 能夠容忍這種污點(diǎn),否則不能對(duì)它調(diào)度 Pod。容忍只是一個(gè)與污點(diǎn)匹配的鍵-值對(duì)。讓我們舉個(gè)例子來說明:

需要對(duì)主機(jī) web01 進(jìn)行污染,以使其不接受更多 Pod。taint 命令如下:

YAML

kubectltaintnodesweb01locked=true:NoSchedule

上面的命令在名為 web01 的節(jié)點(diǎn)上放置了一個(gè)污點(diǎn),該節(jié)點(diǎn)具有以下屬性:

標(biāo)簽 locked=true,該標(biāo)簽必須配置在想要運(yùn)行在該節(jié)點(diǎn)的 Pod 上。

NoSchedule 的污點(diǎn)類型。污點(diǎn)類型定義了應(yīng)用污點(diǎn)的行為,它有以下幾種可能:

NoSchedule:此節(jié)點(diǎn)一定不要調(diào)度。

PreferNoSchedule:盡量不要調(diào)度,類似軟親和性。

NoExecute:不僅不會(huì)調(diào)度,還會(huì)驅(qū)逐 Node 上已有的 Pod。

在帶有污點(diǎn)的節(jié)點(diǎn)上,Pod 的定義文件可能如下所示:

YAML

apiVersion:v1

kind:Pod

metadata:

name:mypod

spec:

containers:

-name:mycontainer

image:nginx

tolerations:

-key:"locked"

operator:"Equal"

value:"true"

effect:"NoSchedule"

讓我們仔細(xì)看看這個(gè)定義的容忍部分:

為了具有正確的容忍,我們需要指定鍵(locked),值(true)和運(yùn)算符。

運(yùn)算符可以是兩個(gè)值之一:

Equal:當(dāng)使用 equal 操作符時(shí),鍵、值和污染效果必須與節(jié)點(diǎn)的污染匹配。

Exists:在使用 exists 操作符時(shí),不需要將污點(diǎn)與容忍匹配,只需匹配建即可。

如果使用 Exists 運(yùn)算符,則可以忽略容忍鍵、值和效果。具有這種容忍的 Pod 可以被調(diào)度到具有任何受污點(diǎn)的節(jié)點(diǎn)。

注意,在 Pod 上放置容忍并不能保證它被部署到受污染的節(jié)點(diǎn)上。它只允許行為發(fā)生。如果要強(qiáng)制 Pod 加入受污染的節(jié)點(diǎn),還必須像前面討論的那樣向其定義添加節(jié)點(diǎn)親和性。

TL; DR

在節(jié)點(diǎn)上自動(dòng)放置 Pod 是 Kubernetes 誕生的原因之一。作為管理員,只要您對(duì) Pod 需求做出了良好的聲明,您就不用擔(dān)心節(jié)點(diǎn)是否有足夠的空閑資源來運(yùn)行這些 Pod。但是,有時(shí)您必須手動(dòng)干預(yù)和覆蓋系統(tǒng)關(guān)于在何處放置 Pods 的決定。在本文中,我們討論了幾種方法,在決定部署 Pods 時(shí),您可以通過這些方法對(duì)特定節(jié)點(diǎn)的調(diào)度器產(chǎn)生更大的影響。讓我們快速回顧一下這些方法:

節(jié)點(diǎn)名稱:通過將節(jié)點(diǎn)的主機(jī)名添加到 Pod 定義的?.spec.nodeName?參數(shù)中,可以強(qiáng)制此 Pod 在該特定節(jié)點(diǎn)上運(yùn)行。調(diào)度程序使用的任何選擇算法都將被忽略。不建議使用此方法。

節(jié)點(diǎn)選擇器:通過在節(jié)點(diǎn)上放置指定的標(biāo)簽,Pod 可以使用 nodeelector 參數(shù)指定一個(gè)或多個(gè)鍵-值標(biāo)簽,這些標(biāo)簽必須存在于目標(biāo)節(jié)點(diǎn)上才能被選中以運(yùn)行 Pod。推薦使用這種方法,因?yàn)樗黾恿撕芏囔`活性,并建立了松耦合的 node-Pod 關(guān)系。

節(jié)點(diǎn)親和性:在選擇應(yīng)該考慮哪個(gè)節(jié)點(diǎn)來調(diào)度特定的 Pod 時(shí),這種方法增加了更多的靈活性。使用節(jié)點(diǎn)親和性,Pod 可能嚴(yán)格要求在具有特定標(biāo)簽的節(jié)點(diǎn)上調(diào)度。它還可以通過影響調(diào)度程序?yàn)樘囟ü?jié)點(diǎn)賦予更大的權(quán)重來表示對(duì)特定節(jié)點(diǎn)的某種程度的偏好。

Pod 親和性和反親和性:當(dāng) Pod 與同一節(jié)點(diǎn)上的其他 Pod 共存(或不共存)時(shí),可以使用此方法。Pod 親和性允許將 Pod 部署在具有特定標(biāo)簽的 Pod 運(yùn)行的節(jié)點(diǎn)上。相反,Pod 可能會(huì)強(qiáng)制調(diào)度程序不將其調(diào)度到具有特定標(biāo)簽的 Pod 運(yùn)行的節(jié)點(diǎn)上。

污點(diǎn)和容忍:在這種方法中,您不需要決定將 Pod 調(diào)度到哪些節(jié)點(diǎn),而是決定哪些節(jié)點(diǎn)是否接受 所有 Pod 調(diào)度,或者只接受選定的 Pod 調(diào)度。通過污染一個(gè)節(jié)點(diǎn),調(diào)度程序?qū)⒉豢紤]將這個(gè)節(jié)點(diǎn)作為任何 Pod 的調(diào)度節(jié)點(diǎn),除非 Pod 配置了容忍。容忍由鍵、值和受染的效果組成。

原文鏈接:https://www.magalix.com/blog/influencing-kubernetes-scheduler-decisions

?著作權(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)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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