kubernetes Pod資源調度之優先(搶占)調度


目錄

    對於運行各種負載(如Service、Job)的中等規模或者大規模的集群來說,出於各種原因,我們需要盡可能提高集群的資源利用率。而提高資源利用率的常規做法是采用優先級方案,即不同類型的負載對應不同的優先級,同時允許集群中的所有負載所需的資源總量超過集群可提供的資源,在這種情況下,當發生資源不足的情況時,系統可以選擇釋 放一些不重要的負載(優先級最低的),保障最重要的負載能夠獲取足夠的資源穩定運行。

    Kubernetes 1.8版本之前,當集群的可用資源不足時,在用戶提交新的Pod創建請求后,該Pod會一直處於Pending狀態,即使這個Pod是一個很重要(很有身份)的Pod,也只能被動等待其他Pod被刪除並釋放資源,才能有機會被調度成功。

    Kubernetes 1.8版本引入了基於Pod優先級 搶占Pod Priority Preemption的調度策略,此時Kubernetes會嘗試釋放目標節點上低優先級的Pod,以騰出空間(資源)安置高優先級的Pod,這種調度方式被稱為“搶占式調度”。在Kubernetes 1.11版本中,該特性升級為Beta版本,默認開啟,在后繼的Kubernetes 1.14版本中正式Release。如何聲明一個負載相對其他負載“更重要”?我們可以通過以下幾個維度來定義:

    • Priority,優先級
    • QoS,服務質量等級
    • 系統定義的其他度量指標

    優先級搶占調度策略的核心行為分別是驅逐Eviction與搶占Preemption,這兩種行為的使用場景不同,效果相同。Evictionkubelet進程的行為,即當一個Node發生資源不足under resource pressure的情況時,該節點上的kubelet進程會執行驅逐動作,此時Kubelet會綜合考慮Pod的優先級、資源申請量與實際使用量等信息來計算哪些Pod需要被驅逐;當同樣優先級的Pod需要被驅逐時,實際使用的資源量超過申請量最大倍數的高耗能Pod會被首先驅逐。對於QoS等級為Best EffortPod來說,由於沒有定義資源申請CPU/Memory Request,所以它們實際使用的資源可能非常大。Preemption則是Scheduler執行的行為,當一個新的Pod因為資源無法滿足而不能被調度時,Scheduler可能(有權決定)選擇驅逐部分低優先級的Pod實例來滿足此Pod的調度目標,這就是Preemption機制。

    需要注意的是,Scheduler可能會驅逐Node A上的一個Pod以滿足Node B上的一個新Pod的調度任務。比如下面的這個例子:

    一個低優先級的Pod A在Node A(屬於機架R)上運行,此時有一個高優先級的 Pod B等待調度,目標節點是同屬機架R的Node B,他們中的一個或全部都定義了antiaffinity規則,不允許在同一個機架上運行,此時Scheduler只好“丟車保帥”,驅逐低優 先級的Pod A以滿足高優先級的Pod B的調度。

    Pod優先級調度示例如下
    首先,由集群管理員創建PriorityClassesPriorityClass不屬於任何命名空間:

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

    上述YAML文件定義了一個名為high-priority的優先級類別,優先級為100000,數字越大,優先級越高,超過一億的數字被系統保留,用於指派給系統組件。

    可以在任意Pod中引用上述Pod優先級類別:

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

    如果發生了需要搶占的調度,高優先級Pod就可能搶占節點N,並將其低優先級Pod驅逐出節點N,高優先級Podstatus信息中的nominatedNodeName字段會記錄目標節點N的名稱。需要注意,高優先級Pod仍然無法保證最終被調度到節點N上,在節點N上低優先級Pod被驅逐的過程中,如果有新的節點滿足高優先級Pod的需求,就會把它調度到新的Node上。而如果在等待低優先級的Pod退出的過程中,又出現了優先級更高的Pod,調度器將會調度這個更高優先級的Pod到節點N上,並重新調度之前等待的高優先級Pod

    優先級搶占的調度方式可能會導致調度陷入“死循環”狀態。當Kubernetes集群配置了多個調度器Scheduler時,這一行為可能就會發生,比如下面這個例子:

    Scheduler A為了調度一個(批)Pod,特地驅逐了一些Pod,因此在集群中有了空 余的空間可以用來調度,此時Scheduler B恰好搶在Scheduler A之前調度了一個新的 Pod,消耗了相應的資源,因此,當Scheduler A清理完資源后正式發起Pod的調度時, 卻發現資源不足,被目標節點的kubelet進程拒絕了調度請求!這種情況的確無解,因 此最好的做法是讓多個Scheduler相互協作來共同實現一個目標。

    最后要指出一點:使用優先級搶占的調度策略可能會導致某些Pod永遠無法被成功調度。因此優先級調度不但增加了系統的復雜性,還可能帶來額外不穩定的因素。因此,一旦發生資源緊張的局面,首先要考 慮的是集群擴容,如果無法擴容,則再考慮有監管的優先級調度特性, 比如結合基於Namespace的資源配額限制來約束任意優先級搶占行為。

    文章參考來源:《kubernetes權威指南-第4版》


    免責聲明!

    本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



     
    粵ICP備18138465號   © 2018-2025 CODEPRJ.COM