為什麼需要資源管理#

Kubernetes 是一個跨多個節點(Node)的叢集管理平台,每個節點都可以視為一台具備固定運算資源的主機。要讓平台上的容器穩定運作,叢集必須清楚掌握整體資源使用狀況,並依照需求把資源合理分配給每一個容器:

  • 確保容器在生命週期內擁有足以運作的資源。
  • 避免某些低度使用的容器長時間獨佔資源造成浪費。
  • 在優先度與公平性之間取得平衡,盡可能提高利用率。

為此,Kubernetes 提供了兩種資源宣告方式 — 資源請求(Request)與資源限制(Limit),讓我們在 Pod spec 中指定每個容器需要多少資源、最多能用到多少。

Request 與 Limit 是什麼#

Request#

  • 容器啟動時所要求的最小資源量,是排程器決定 Pod 要被放到哪個節點的依據。
  • 只有當節點上「可分配資源 ≥ Request」時,Pod 才會被排到該節點上執行。

Limit#

  • 容器在執行期間可以使用的資源上限。
  • 若設定為 0,代表不對該資源設限,容器可以一路用上去。

兩者之間的關係#

容器宣告的 Request 必須大於等於 0,且不能超過節點可分配的容量:

0 <= request <= Node Allocatable

Limit 則必須大於等於 Request,理論上沒有上限:

request <= limit <= Infinity

可宣告的資源類型:CPU 與 Memory#

Kubernetes 把底層的硬體資源抽象成幾種計算資源,常用的兩種是 CPU 與記憶體:

  • CPU:以「核心(cores)」為計量單位。一個 CPU 大致對應到一個雲端 vCPU 或一條 Hyperthread。
  • Memory:以位元組為計量單位,可以使用整數或附帶後綴(E、P、T、G、M、K)的數值表示,例如 200Mi

Pod 的服務品質:QoS Class#

Pod 建立時,Kubernetes 會根據裡面每個容器的 Request 與 Limit,自動把 Pod 分到三種 QoS Class(Guaranteed/Burstable/BestEffort)之一。這個分類會直接影響系統資源吃緊時,誰會被優先驅逐。

Guaranteed#

當 Pod 內每個容器的 requests.memory 等於 limits.memory,且 requests.cpu 等於 limits.cpu 時,這個 Pod 會被歸類為 Guaranteed:

apiVersion: v1
kind: Pod
metadata:
  name: qos-demo
  namespace: qos-example
spec:
  containers:
    - name: qos-demo-ctr
      image: nginx
      resources:
        limits:
          memory: "200Mi"
          cpu: "700m"
        requests:
          memory: "200Mi"
          cpu: "700m"

Burstable#

需要同時滿足兩個條件:

  • 不是 Guaranteed Pod。
  • Pod 中至少有一個容器設定了 memory 或 cpu 的 Request。
apiVersion: v1
kind: Pod
metadata:
  name: qos-demo-2
  namespace: qos-example
spec:
  containers:
    - name: qos-demo-2-ctr
      image: nginx
      resources:
        limits:
          memory: "200Mi"
        requests:
          memory: "100Mi"

BestEffort#

當 Pod 內所有容器都沒有設定 Request 與 Limit 時,這個 Pod 會被歸類為 BestEffort:

apiVersion: v1
kind: Pod
metadata:
  name: qos-demo-3
  namespace: qos-example
spec:
  containers:
    - name: qos-demo-3-ctr
      image: nginx

可以透過以下指令查看實際分到的 QoS Class:

kubectl get pod qos-demo-3 --output=yaml

輸出中會看到類似結構:

spec:
  containers:
    ...
    resources: {}
status:
  qosClass: BestEffort

不同 QoS Class 的命運#

當系統資源吃緊時,Kubernetes 會依照 QoS Class 決定優先驅逐哪些 Pod:

  • BestEffort:優先級最低。記憶體不足時,第一批被清理的就是它們。
  • Burstable:擁有最低限度的資源保障,但允許在資源充裕時用到 Limit。當沒有 BestEffort Pod 可以驅逐時,Burstable 會是下一個目標。
  • Guaranteed:優先級最高,通常不會被殺掉或限流,除非自己用量超出 Limit,且沒有更低優先級的 Pod 可清理。

小結#

Request 與 Limit 看似只是兩個欄位,背後牽動著 Pod 的命運:

  • 設定 Request,是為了讓 Kubernetes 把 Pod 放到擁有足夠資源的節點上。
  • 設定 Limit,是為了避免單一容器吃掉整台機器。
  • 把 Limit 設得高於 Request,則代表容器「平時保底拿 Request、忙的時候才衝到 Limit」。

掌握這組基本機制,後續才有辦法談 Namespace、LimitRange、ResourceQuota,乃至於依資源指標自動擴縮容(Autoscaling)。

原文出處#

  • GitHub:https://github.com/MikeHsu0618/2022-ithelp/tree/main/Day21
  • iThome:https://ithelp.ithome.com.tw/articles/10295419