如何使用AdmissionWebhook機(jī)制實(shí)現(xiàn)多集群資源配額控制

本篇文章為大家展示了如何使用Admission Webhook機(jī)制實(shí)現(xiàn)多集群資源配額控制,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

成都創(chuàng)新互聯(lián)公司主營(yíng)松滋網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,重慶APP軟件開(kāi)發(fā),松滋h5小程序開(kāi)發(fā)搭建,松滋網(wǎng)站營(yíng)銷推廣歡迎松滋等地區(qū)企業(yè)咨詢

1 要解決的問(wèn)題

集群分配給多個(gè)用戶使用時(shí),需要使用配額以限制用戶的資源使用,包括 CPU 核數(shù)、內(nèi)存大小、GPU 卡數(shù)等,以防止資源被某些用戶耗盡,造成不公平的資源分配。

大多數(shù)情況下,集群原生的 ResourceQuota 機(jī)制可以很好地解決問(wèn)題。但隨著集群規(guī)模擴(kuò)大,以及任務(wù)類型的增多,我們對(duì)配額管理的規(guī)則需要進(jìn)行調(diào)整:

  • ResourceQuota 針對(duì)單集群設(shè)計(jì),但實(shí)際上,開(kāi)發(fā)/生產(chǎn)中經(jīng)常使用 多集群環(huán)境。

  • 集群大多數(shù)任務(wù)通過(guò)比如deployment、mpijob高級(jí)資源對(duì)象進(jìn)行提交,我們希望在高級(jí)資源對(duì)象的 提交階段就能對(duì)配額進(jìn)行判斷。但 ResourceQuota 計(jì)算資源請(qǐng)求時(shí)以 pod 為粒度,從而無(wú)法滿足此需求。

基于以上問(wèn)題,我們需要自行進(jìn)行配額管理。而 Kubernetes 提供了動(dòng)態(tài)準(zhǔn)入的機(jī)制,允許我們編寫(xiě)自定義的插件,以實(shí)現(xiàn)請(qǐng)求的準(zhǔn)入。我們的配額管理方案,就以此入手。

2 集群動(dòng)態(tài)準(zhǔn)入原理

進(jìn)入 K8s 集群的請(qǐng)求,被 API server 接收后,會(huì)經(jīng)過(guò)如下幾個(gè)順序執(zhí)行的階段:

  1. 認(rèn)證/鑒權(quán)

  2. 準(zhǔn)入控制(變更)

  3. 格式驗(yàn)證

  4. 準(zhǔn)入控制(驗(yàn)證)

  5. 持久化

請(qǐng)求在上述前四個(gè)階段都會(huì)被相應(yīng)處理,并且依次被判斷是否允許通過(guò)。各個(gè)階段都通過(guò)后,才能夠被持久化,即存入到 etcd 數(shù)據(jù)庫(kù)中,從而變?yōu)橐淮纬晒Φ恼?qǐng)求。其中,在 準(zhǔn)入控制(變更)階段,mutating admission webhook 會(huì)被調(diào)用,可以修改請(qǐng)求中的內(nèi)容。而在 準(zhǔn)入控制(驗(yàn)證)階段,validating admission webhook 會(huì)被調(diào)用,可以校驗(yàn)請(qǐng)求內(nèi)容是否符合某些要求,從而決定是否允許或拒絕該請(qǐng)求。而這些 webhook 支持?jǐn)U展,可以被獨(dú)立地開(kāi)發(fā)和部署到集群中。

雖然,在 準(zhǔn)入控制(變更)階段,webhook也可以檢查和拒絕請(qǐng)求,但其被調(diào)用的次序無(wú)法保證,無(wú)法限制其它 webhook 對(duì)請(qǐng)求的資源進(jìn)行修改。因此,我們部署用于配額校驗(yàn)的 validating admission webhook,配置于 準(zhǔn)入控制(驗(yàn)證)階段調(diào)用,進(jìn)行請(qǐng)求資源的檢查,就可以實(shí)現(xiàn)資源配額管理的目的。

3 方案

3.1 如何在集群中部署校驗(yàn)服務(wù)

在 K8s 集群中使用自定義的 validating admission webhook 需要部署:

  1. ValidatingWebhookConfiguration 配置(需要集群?jiǎn)⒂?ValidatingAdmissionWebhook) ,用于定義要對(duì)何種資源對(duì)象(pod, deployment, mpijob 等)進(jìn)行校驗(yàn),并提供用于實(shí)際處理校驗(yàn)的服務(wù)回調(diào)地址。推薦使用在集群內(nèi)配置 Service 的方式來(lái)提供校驗(yàn)服務(wù)的地址。

  2. 實(shí)際處理校驗(yàn)的服務(wù),通過(guò)在 ValidatingWebhookConfiguration 配置的地址可訪問(wèn)即可。

單集群環(huán)境中,將校驗(yàn)服務(wù)以 deployment 的方式在集群中部署。多集群環(huán)境中,可以選擇:

  1. 使用 virtual kubelet,cluster federation 等方案將多集群合并為單集群,從而退化為采用單集群方案部署。

  2. 將校驗(yàn)服務(wù)以 deloyment 的方式部署于一個(gè)或多個(gè)集群中,但要注意保證服務(wù)到各個(gè)集群網(wǎng)絡(luò)連通。

需要注意的是,不論是單集群還是多集群的環(huán)境中,處理校驗(yàn)的服務(wù)都需要進(jìn)行資源監(jiān)控,這一般由單點(diǎn)實(shí)現(xiàn)。因此都需要 進(jìn)行選主。

3.2 如何實(shí)現(xiàn)校驗(yàn)服務(wù)

3.2.1 校驗(yàn)服務(wù)架構(gòu)設(shè)計(jì)
3.2.1.1 基本組件構(gòu)成

如何使用Admission Webhook機(jī)制實(shí)現(xiàn)多集群資源配額控制

  • API server:集群請(qǐng)求入口,調(diào)用 validating admission webhook 以驗(yàn)證請(qǐng)求

  • API:準(zhǔn)入服務(wù)接口,使用集群約定的 AdmissionReview 數(shù)據(jù)結(jié)構(gòu)作為請(qǐng)求和返回

  • Quota usage service:請(qǐng)求資源使用量接口

  • Admissions:準(zhǔn)入服務(wù)實(shí)現(xiàn),包括 deploymentmpijob 等不同資源類型準(zhǔn)入

  • Resource validator:對(duì)資源請(qǐng)求進(jìn)行配額校驗(yàn)

  • Quota adapter:對(duì)接外部配額服務(wù)供 validator 查詢

  • Resource usage manager:資源使用管理器,維護(hù)資源使用情況,實(shí)現(xiàn)配額判斷

  • Informers:通過(guò) K8s 提供的 watch 機(jī)制監(jiān)控集群中資源,包括 deploymentmpijob 等,以維護(hù)當(dāng)前資源使用

  • Store:存放資源使用數(shù)據(jù),可以對(duì)接服務(wù)本地內(nèi)存實(shí)現(xiàn),或者對(duì)接 redis 服務(wù)實(shí)現(xiàn)

3.2.1.2 資源配額判斷的基本流程

以用戶創(chuàng)建 deployment 資源為例:

  1. 用戶創(chuàng)建 deployment 資源,定義中需要包含指定了應(yīng)用組信息的 annotation,比如 ti.cloud.tencent.com/group-id: 1,表示申請(qǐng)使用應(yīng)用組 1 中的資源(如果沒(méi)有帶有應(yīng)用組信息,則根據(jù)具體場(chǎng)景,直接拒絕,或者提交到默認(rèn)的應(yīng)用組,比如應(yīng)用組 0 等)。

  2. 請(qǐng)求由 API server收取,由于在集群中正確配置了 ValidatingWebhookConfiguration,因此在準(zhǔn)入控制的驗(yàn)證階段,會(huì)請(qǐng)求集群中部署的 validating admission webhookAPI,使用 K8s 規(guī)定的結(jié)構(gòu)體AdmissionReviewRequest 作為請(qǐng)求,期待 AdmissionReviewResponse 結(jié)構(gòu)體作為返回。

  3. 配額校驗(yàn)服務(wù)收到請(qǐng)求后,會(huì)進(jìn)入負(fù)責(zé)處理 deployment 資源的 admission的邏輯,根據(jù)改請(qǐng)求的動(dòng)作是 CREATE 或 UPDATE 來(lái)計(jì)算出此次請(qǐng)求需要新申請(qǐng)或者釋放的資源。

  4. deploymentspec.template.spec.containers[*].resources.requests 字段中提取要申請(qǐng)的資源,比如為 cpu: 2memory: 1Gi,以 apply 表示。

  5. Resource validator查找 quota adapter獲取應(yīng)用組 1 的配額信息,比如 cpu: 10memory: 20Gi ,以 quota 表示。連同上述獲取的 apply,向 resource usage manager申請(qǐng)資源。

  6. Resource usage manager一直在通過(guò) informer監(jiān)控獲取 deployment 的資源使用情況,并維護(hù)在 store中。Store可以使用本地內(nèi)存,從而無(wú)外部依賴?;蛘呤褂?Redis 作為存儲(chǔ)介質(zhì),方便服務(wù)水平擴(kuò)展。

  7. Resource usage manager收到 resource validator的請(qǐng)求時(shí),可以通過(guò) store查到應(yīng)用組 1 當(dāng)前已經(jīng)占用的資源情況,比如 cpu: 8memory: 16Gi,以 usage 表示。檢查發(fā)現(xiàn) apply + usage <= quota 則認(rèn)為沒(méi)有超過(guò)配額,請(qǐng)求通過(guò),并最終返回給 API server。

以上就是實(shí)現(xiàn)資源配額檢查的基本流程。有一些細(xì)節(jié)值得補(bǔ)充說(shuō)明:

  • 校驗(yàn)服務(wù)的接口 API必須采用 https 暴露服務(wù)。

  • 針對(duì)不用的資源類型,比如 deployment、mpijob 等,都需要實(shí)現(xiàn)相應(yīng)的 admission以及 informer。

  • 每個(gè)資源類型可能有不同的版本,比如 deploymentapps/v1apps/v1beta1 等,需要根據(jù)集群的實(shí)際情況兼容處理。

  • 收到 UPDATE 請(qǐng)求時(shí),需要根據(jù)資源類型中 pod 的字段是否變化,來(lái)判斷是否需要重建當(dāng)前已有的 pod 實(shí)例,以正確計(jì)算資源申請(qǐng)的數(shù)目。

  • 除了 K8s 自帶的資源類型,比如 cpu 等,如果還需要自定義的資源類型配額控制,比如 GPU 類型等,需要在資源請(qǐng)求約定好相應(yīng)的 annotations,比如 ti.cloud.tencent.com/gpu-type: V100

  • resource usage manager進(jìn)行使用量、申請(qǐng)量和配額的判斷過(guò)程中,可能會(huì)出現(xiàn) 資源競(jìng)爭(zhēng)、配額通過(guò)校驗(yàn)但實(shí)際 資源創(chuàng)建失敗等問(wèn)題。接下來(lái)我們會(huì)對(duì)這兩個(gè)問(wèn)題進(jìn)行解釋。

3.2.2 關(guān)于資源申請(qǐng)競(jìng)爭(zhēng)

由于并發(fā)資源請(qǐng)求的存在:

  1. usage 需要能夠被在資源請(qǐng)求后即時(shí)更新

  2. usage 的更新需要進(jìn)行并發(fā)控制

在上述步驟 7 中,Resource usage manager校驗(yàn)配額時(shí),需要查詢應(yīng)用組當(dāng)前的資源占用情況,即應(yīng)用組的 usage 值。此 usage 值由 informers負(fù)責(zé)更新和維護(hù),但由于從資源請(qǐng)求被 validating admission webhook 通過(guò),到 informer能夠觀察到,存在時(shí)間差。這個(gè)過(guò)程中,可能仍有資源請(qǐng)求,那么 usage 值就是不準(zhǔn)確的了。因此,usage 需要能夠被在資源請(qǐng)求后即時(shí)更新。

并且對(duì) usage 的更新需要進(jìn)行并發(fā)控制,舉個(gè)例子:

  1. 應(yīng)用組 2quotacpu: 10,usagecpu: 8

  2. 進(jìn)入兩個(gè)請(qǐng)求 deployment1deployment2 申請(qǐng)使用應(yīng)用組 2,它們的 apply 同為 cpu: 2

  3. 需要首先判斷 deployment1, 計(jì)算 apply + usage = cpu: 10,未超過(guò) quota 值,因此 deployment1 的請(qǐng)求允許通過(guò)。

  4. usage 被更新為 cpu: 10

  5. 再去判斷 deployment2,由于 usage 被更新為 cpu: 10,則算出 apply + usage = cpu: 12,超過(guò)了 quota 的值,因此不允許通過(guò)該請(qǐng)求。

上述過(guò)程中,容易發(fā)現(xiàn) usage 是關(guān)鍵的 共享變量,需要順序查詢和更新。若 deployment1deployment2 不加控制地同時(shí)使用 usagecpu: 8,就會(huì)導(dǎo)致 deployment1deployment2 請(qǐng)求都被通過(guò),從而實(shí)際超出了配額限制。這樣,用戶可能占用 超過(guò)配額規(guī)定的資源。

可行的解決辦法:

  • 資源申請(qǐng)進(jìn)入隊(duì)列,由單點(diǎn)的服務(wù)依次消費(fèi)和處理。

  • 將共享的變量 usage 所處的臨界區(qū)上鎖,在鎖內(nèi)查詢和更新 usage 的值。

3.2.3 關(guān)于資源創(chuàng)建失敗

由于資源競(jìng)爭(zhēng)的問(wèn)題,我們要求 usage 需要能夠被在資源請(qǐng)求后即時(shí)更新,但這也帶來(lái)新的問(wèn)題。在 4. 準(zhǔn)入控制(驗(yàn)證)階段之后,請(qǐng)求的資源對(duì)象會(huì)進(jìn)入 5. 持久化階段,這個(gè)過(guò)程中也可能出現(xiàn)異常(比如其他的 webhook 又拒絕了該請(qǐng)求,或者集群斷電,etcd 故障等)導(dǎo)致任務(wù)沒(méi)有實(shí)際提交成功到集群數(shù)據(jù)庫(kù)。在這種情況下,我們?cè)?驗(yàn)證階段,已經(jīng)增加了 usage 的值,就把沒(méi)有實(shí)際占用配額的任務(wù)算作占用了配額。這樣,用戶可能占用 不足配額規(guī)定的資源。

為了解決這個(gè)問(wèn)題,后臺(tái)服務(wù)會(huì)定時(shí)全局更新每個(gè)應(yīng)用組的 usage 值。這樣,如果出現(xiàn)了 驗(yàn)證階段增加了 usage 值,但任務(wù)實(shí)際提交到數(shù)據(jù)庫(kù)失敗的情況,在全局更新的時(shí)候,usage 值最終會(huì)重新更新為那個(gè)時(shí)刻應(yīng)用組在集群內(nèi)資源使用的準(zhǔn)確值。

但在極少數(shù)情況下,全局更新會(huì)在這種時(shí)刻發(fā)生:某最終會(huì)成功存入 etcd 持久化的資源對(duì)象創(chuàng)建請(qǐng)求,已經(jīng)通過(guò) webhook 驗(yàn)證,但尚未完成 持久化的時(shí)刻。這種時(shí)刻的存在,導(dǎo)致全局更新依然會(huì)帶來(lái)用戶占用 超過(guò)配額的問(wèn)題。 比如,在之前的例子中,deployment1 更新了 usage 值之后,恰巧發(fā)生了全局更新。此時(shí) deployment1 的信息恰好尚未存入 etcd,所以全局更新會(huì)把 usage 重新更新為舊值,這樣會(huì)導(dǎo)致 dployment2 也能被通過(guò),從而超過(guò)了配額限制。 但通常,從 驗(yàn)證持久化的時(shí)間很短。低頻的全局更新情況下,此種情況 幾乎不會(huì)發(fā)生。后續(xù),如果有進(jìn)一步的需求,可以采用更復(fù)雜的方案來(lái)規(guī)避這個(gè)問(wèn)題。

3.2.3 原生 ResourceQuota 的工作方式

K8s 集群中原生的配額管理 ResourceQuota 針對(duì)上述 資源申請(qǐng)競(jìng)爭(zhēng)資源創(chuàng)建失敗問(wèn)題,采用了類似的解決方案:

即時(shí)更新解決申請(qǐng)競(jìng)爭(zhēng)問(wèn)題

檢查完配額后,即時(shí)更新資源用量,K8s 系統(tǒng)自帶的樂(lè)觀鎖保證并發(fā)的資源控制(詳見(jiàn) K8s 源碼中 checkQuotas 的實(shí)現(xiàn)),解決資源競(jìng)爭(zhēng)問(wèn)題。

checkQuotas 中最相關(guān)的源碼解讀:

// now go through and try to issue updates.  Things get a little weird here:
// 1. check to see if the quota changed.  If not, skip.
// 2. if the quota changed and the update passes, be happy
// 3. if the quota changed and the update fails, add the original to a retry list
var updatedFailedQuotas []corev1.ResourceQuota
var lastErr error
for i := range quotas {
    newQuota := quotas[i]
    // if this quota didn't have its status changed, skip it
    if quota.Equals(originalQuotas[i].Status.Used, newQuota.Status.Used) {
        continue
    }
    if err := e.quotaAccessor.UpdateQuotaStatus(&newQuota); err != nil {
        updatedFailedQuotas = append(updatedFailedQuotas, newQuota)
        lastErr = err
    }
}

這里 quotas 是經(jīng)過(guò)校驗(yàn)后的配額信息,其中 newQuota.Status.Used 字段則記錄了該配額的資源使用情況。如果針對(duì)該配額的資源請(qǐng)求通過(guò)了,運(yùn)行到這段代碼時(shí),Used 字段中已經(jīng)被加上了新申請(qǐng)資源的量。隨后,Equals 函數(shù)被調(diào)用,即如果 Used 字段未變,說(shuō)明沒(méi)有新的資源申請(qǐng)。否則,就會(huì)運(yùn)行到 e.quotaAccessor.UpdateQuotaStatus,立刻去把 etcd 中的配額信息按照 newQuota.Status.Used 來(lái)更新。

定時(shí)全局更新解決創(chuàng)建失敗問(wèn)題

定時(shí)全局更新資源使用量(詳見(jiàn) K8s 源碼中 Run 的實(shí)現(xiàn)),解決可能的資源創(chuàng)建失敗問(wèn)題 。

Run 中最相關(guān)的源碼解讀:

// the timer for how often we do a full recalculation across all quotas
go wait.Until(func() { rq.enqueueAll() }, rq.resyncPeriod(), stopCh)

這里 rqResourceQuota 對(duì)象對(duì)應(yīng) controller 的自引用。這個(gè) Controller 運(yùn)行 Run 循環(huán),持續(xù)地控制所有 ResourceQuota 對(duì)象。循環(huán)中,不間斷定時(shí)調(diào)用 enqueueAll,即把所有的 ResourceQuota 壓入隊(duì)列中,修改其 Used 值,進(jìn)行全局更新。

上述內(nèi)容就是如何使用Admission Webhook機(jī)制實(shí)現(xiàn)多集群資源配額控制,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

網(wǎng)站名稱:如何使用AdmissionWebhook機(jī)制實(shí)現(xiàn)多集群資源配額控制
文章源于:http://muchs.cn/article46/iioshg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開(kāi)發(fā)、網(wǎng)站設(shè)計(jì)、云服務(wù)器、網(wǎng)站建設(shè)、建站公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)