真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

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

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

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

1 要解決的問題

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

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

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

  • 集群大多數(shù)任務通過比如deploymentmpijob高級資源對象進行提交,我們希望在高級資源對象的 提交階段就能對配額進行判斷。但 ResourceQuota 計算資源請求時以 pod 為粒度,從而無法滿足此需求。

基于以上問題,我們需要自行進行配額管理。而 Kubernetes 提供了動態(tài)準入的機制,允許我們編寫自定義的插件,以實現(xiàn)請求的準入。我們的配額管理方案,就以此入手。

2 集群動態(tài)準入原理

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

  1. 認證/鑒權

  2. 準入控制(變更)

  3. 格式驗證

  4. 準入控制(驗證)

  5. 持久化

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

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

3 方案

3.1 如何在集群中部署校驗服務

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

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

  2. 實際處理校驗的服務,通過在 ValidatingWebhookConfiguration 配置的地址可訪問即可。

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

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

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

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

3.2 如何實現(xiàn)校驗服務

3.2.1 校驗服務架構設計
3.2.1.1 基本組件構成

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

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

  • API:準入服務接口,使用集群約定的 AdmissionReview 數(shù)據(jù)結構作為請求和返回

  • Quota usage service:請求資源使用量接口

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

  • Resource validator:對資源請求進行配額校驗

  • Quota adapter:對接外部配額服務供 validator 查詢

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

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

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

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

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

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

  2. 請求由 API server收取,由于在集群中正確配置了 ValidatingWebhookConfiguration,因此在準入控制的驗證階段,會請求集群中部署的 validating admission webhookAPI,使用 K8s 規(guī)定的結構體AdmissionReviewRequest 作為請求,期待 AdmissionReviewResponse 結構體作為返回。

  3. 配額校驗服務收到請求后,會進入負責處理 deployment 資源的 admission的邏輯,根據(jù)改請求的動作是 CREATE 或 UPDATE 來計算出此次請求需要新申請或者釋放的資源。

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

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

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

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

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

  • 校驗服務的接口 API必須采用 https 暴露服務。

  • 針對不用的資源類型,比如 deploymentmpijob 等,都需要實現(xiàn)相應的 admission以及 informer。

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

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

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

  • resource usage manager進行使用量、申請量和配額的判斷過程中,可能會出現(xiàn) 資源競爭、配額通過校驗但實際 資源創(chuàng)建失敗等問題。接下來我們會對這兩個問題進行解釋。

3.2.2 關于資源申請競爭

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

  1. usage 需要能夠被在資源請求后即時更新

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

在上述步驟 7 中,Resource usage manager校驗配額時,需要查詢應用組當前的資源占用情況,即應用組的 usage 值。此 usage 值由 informers負責更新和維護,但由于從資源請求被 validating admission webhook 通過,到 informer能夠觀察到,存在時間差。這個過程中,可能仍有資源請求,那么 usage 值就是不準確的了。因此,usage 需要能夠被在資源請求后即時更新。

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

  1. 應用組 2quotacpu: 10,usagecpu: 8

  2. 進入兩個請求 deployment1deployment2 申請使用應用組 2,它們的 apply 同為 cpu: 2

  3. 需要首先判斷 deployment1, 計算 apply + usage = cpu: 10,未超過 quota 值,因此 deployment1 的請求允許通過。

  4. usage 被更新為 cpu: 10

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

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

可行的解決辦法:

  • 資源申請進入隊列,由單點的服務依次消費和處理。

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

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

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

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

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

3.2.3 原生 ResourceQuota 的工作方式

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

即時更新解決申請競爭問題

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

checkQuotas 中最相關的源碼解讀:

// 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)過校驗后的配額信息,其中 newQuota.Status.Used 字段則記錄了該配額的資源使用情況。如果針對該配額的資源請求通過了,運行到這段代碼時,Used 字段中已經(jīng)被加上了新申請資源的量。隨后,Equals 函數(shù)被調(diào)用,即如果 Used 字段未變,說明沒有新的資源申請。否則,就會運行到 e.quotaAccessor.UpdateQuotaStatus,立刻去把 etcd 中的配額信息按照 newQuota.Status.Used 來更新。

定時全局更新解決創(chuàng)建失敗問題

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

Run 中最相關的源碼解讀:

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

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

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


分享文章:如何使用AdmissionWebhook機制實現(xiàn)多集群資源配額控制
網(wǎng)頁URL:http://weahome.cn/article/iioshg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部