【k8s】——資源限制

一、前言

      kubernetes最大的優勢之一:它能夠有效地利用計算資源。對於資源的使用,k8s本身支持資源的配置。在K8s中定義Pod中運行容器有兩個維度的限制:
 1. 資源需求:即運行Pod的節點必須滿足運行Pod的最基本需求才能運行Pod。
   如: Pod運行至少需要2G內存,1核CPU
    2. 資源限額:即運行Pod期間,可能內存使用量會增加,那最多能使用多少內存,這就是資源限額。

Tips:目前k8s在對資源限制方面還有欠缺,特別是Java應用,因爲Pod運行起來後,它看到的資源是Node上全部的資源,雖然可通過requests和limits限制,但我們都知道JVM啓動後,它要計算自己的堆內存中不同區域的大小,而這些大小通常是按比例劃分的,假若JVM啓動後,根據Node上實際的內存大小來計算堆內存中老年代,Eden,倖存區那肯定會出問題,因爲,我們給它分片的內存肯定不夠,所以這個要特別注意,而解決辦法,只能是在啓動Java應用前,配置JVM能使用的最大內存量。(elasticsearch)

二、K8s的資源


1、CPU:
  我們知道2核2線程的CPU,可被系統識別爲4個邏輯CPU,在K8s中對CPU的分配限制是對邏輯CPU做分片限制的。
  也就是說分配給容器一個CPU,實際是分配一個邏輯CPU。
  而且1個邏輯CPU還可被單獨劃分子單位,即 1個邏輯CPU,還可被劃分爲1000個millicore(毫核), 簡單說就是1個邏輯CPU,繼續邏輯分割爲1000個豪核心。
  豪核:可簡單理解爲將CPU的時間片做邏輯分割,每一段時間片就是一個豪核心。
  所以:500m 就是500豪核心,即0.5個邏輯CPU.

Tips:

  • 當資源緊俏,發生資源搶佔時,Pod可以分享時間片。例如,在1U的node上,容器A請求0.6U,容器B請求0.4U。資源緊俏時,將會按照請求的比例分配時間片。容器A:0.6U/(0.6U+0.4U);容器B:0.4U/(0.6U+0.4U)。
  • 當資源剩餘,發生超用時,即實際使用超過請求,Pod按照比例分配剩餘資源。例如,在1U的node上,容器A請求0.6U,容器B請求0.3U,剩餘0.1U。兩個容器都想超用,剩餘的0.1U將會按照請求的比例進行2:1分配給兩個容器。

關於提高資源利用率,可以將負載高峯時間錯開的應用部署在一起,提高node利用率。


2、內存:內存和磁盤資源。
  K,M,G,T,P,E #通常這些單位是以1000爲換算標準的。
  Ki, Mi, Gi, Ti, Pi, Ei #這些通常是以1024爲換算標準的。

 

三、K8s中資源限制對調度Pod的影響

  

   cpu.limits: 是我們設置Pod運行時,最大可使用500m個CPU,但要保障Pod能在Node上成功啓動起來,就必需能提供cpu.requests個CPU.
  當預選策略在選擇備選Node時,會首先考慮當前Pod運行, 其所需資源是否足夠, 來做爲首要判斷條件,假如某Node上已經運行了一些Pod,預選策略會獲取當前所有Pod的cpu.requests ,ram.requests等,這裏以cpu.requests來說明,比如說某Node上是2核2線程的CPU,所有容器的cpu.requests全部加起來假如已經3.9個CPU了,那麼此Node在預選階段就會被篩選掉。

四、QoS

1、QoS類型:
 Guranteed:
  每個容器的CPU,RAM資源都設置了相同值的requests 和 limits屬性。
  簡單說: cpu.limits = cpu.requests
      memory.limits = memory.requests
  這類Pod的運行優先級最高,但凡這樣配置了cpu和內存的limits和requests,它會自動被歸爲此類。
  Burstable:
    每個容器至少定義了CPU,RAM的requests屬性,這裏說每個容器是指:一個Pod中可以運行多個容器。
    那麼這類容器就會被自動歸爲burstable,而此類就屬於中等優先級。
  BestEffort:
    沒有一個容器設置了requests 或 limits,則會歸爲此類,而此類別是最低優先級。

2、QoS類型的作用:
  Node上會運行很多Pod,當運行一段時間後,發現Node上的資源緊張了,這時K8s就會根據QoS類別來選擇Kill掉一部分Pod,那些會先被Kill掉?
  當然就是優先級最低的,也就是BestEffort,若BestEffort被Kill完了,還是緊張,接下來就是Kill中等優先級的,即Burstable,依次類推。

  這裏有個問題,BestEffort因爲沒有設置requests和limits,可根據誰佔用資源最多,就kill誰,但Burstable設置了requests和limits,它的kill標準是什麼?
  若按照誰佔資源多kill誰,那遇到這樣的問題,怎麼選擇?
    PodA: 啓動時設置了memory.request=512M , memory.limits=1G
    PodB: 設置爲: memory.requests=1G, memory.limits=2G

    PodA: 運行了一段時間後,佔用了500M了,它可能還有繼續申請內存。
    PodB: 它則佔用了512M內存了,但它可能也還需要申請內存。
    想想,現在Node資源緊張了,會先kill誰?
    其實,會優先kill PodA , 爲啥?
    因爲它啓動時,說自己需要512M內存就夠了,但你現在這麼積極的申請內存,都快把你需求的內存吃完了,只能說明你太激進了,因此會先kill。
    而PodB,啓動時需要1G,但目前才用了1半,說明它比較溫和,因此不會先kill它。

五、k8s資源限制的使用

方法一:在Pod Container Spec中設定資源限制

     在K8S中,對於資源的設定是落在Pod裏的Container上的,主要有兩類,limits控制上限,requests控制下限。其位置在:

  • spec.containers[].resources.limits.cpu
  • spec.containers[].resources.limits.memory
  • spec.containers[].resources.requests.cpu
  • spec.containers[].resources.requests.memory
spec:
  containers:
  - image: xxx
    name: xxxx
    resources:
      limits:    #最大
        cpu: "4"
        memory: 2Gi
      requests:  #初始
        cpu: 250m
        memory: 250Mi

 

方法二:在Namespace中限定

    方法一雖然很好,但是其不是強制性的,因此很容易出現因忘記設定limits/request,導致Host資源使用過度的情形,因此我們需要一種全局性的資源限制設定,以防止這種情況發生。K8S通過在Namespace設定LimitRange來達成這一目的。

配置默認request/limit

如果配置裏默認的request/limit,那麼當Pod Spec沒有設定request/limit的時候,會使用這個配置,有效避免無限使用資源的情況。

配置位置在:

  • spec.limits[].default.cpu,default limit
  • spec.limits[].default.memory,同上
  • spec.limits[].defaultRequest.cpu,default request
  • spec.limits[].defaultRequest.memory,同上

配置request/limit的約束

我們還可以在K8S裏對request/limit進行以下限定:

  • 某資源的request必須>=某值
  • 某資源的limit必須<=某值

這樣的話就能有效避免Pod Spec中亂設limit導致資源耗盡的情況,或者亂設request導致Pod無法得到足夠資源的情況。

配置位置在:

  • spec.limits[].max.cpulimit必須<=某值
  • spec.limits[].max.memory,同上
  • spec.limits[].min.cpurequest必須>=某值
  • spec.limits[].min.memory,同上

六、參考文章

1、K8s容器資源限制

2、QoS官方入門文檔

3、QoS設計文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章