在 Kubernetes (K8s) 中,適當的資源管理是維持叢集穩定和高效運作的基石。如果沒有為 Pod 設定資源,可能會發生以下情況:
因此,強烈建議為所有在生產環境中運行的 Pod 設定資源。
K8s 透過兩個參數來管理容器的資源:requests 和 limits。
| 參數 | 餐廳比喻 | 作用 |
|---|---|---|
| Requests | 預約座位 | 用於 Pod 調度:向 K8s 預約資源。Scheduler 會確保 Node 上有足夠的「可分配資源」來滿足 Pod 的 requests 總和,才會將 Pod 調度到該 Node。 |
| Limits | 座位大小 | 用於資源限制:設定 Pod 可使用的資源天花板。防止 Pod 無限制地佔用資源,影響到同一 Node 上的其他 Pod。 |
requests:調度的入場券requests 是 Scheduler 進行決策的主要依據。一個 Node 的可分配資源,就是其總容量減去所有已調度 Pod 的 requests 總和。requests 並非強制保留。它只是一個調度時的承諾。如果一個 Pod 實際使用的資源少於其 requests,那麼 Node 上空閒出來的這部分資源可以被其他 Pod 使用。limits:資源使用的天花板limits 是由 kubelet 強制執行的硬性限制。limits.cpu 的 CPU 資源,其使用量會被節流 (Throttled),導致應用程式效能下降。limits.memory 的記憶體,它會被系統以 OOMKilled (Out of Memory Killed) 的方式終止並重啟。limits 必須大於或等於 requests。limits 而未設定 requests,則 requests 會被自動設為與 limits 相同。requests 而未設定 limits,則 Pod 可以使用該 Node 上所有的可用資源,直到 Node 資源耗盡。這是一種危險的設定,應盡量避免。
| 資源 | 單位 | 範例 | 說明 |
|---|---|---|---|
| CPU | Cores | 1 (1 個核心) 0.5 (半個核心) 500m (500 millicores) |
m 代表 millicore (千分之一核心)。1000m 等於 1 個核心。1m 是最小單位。 |
| Memory | Bytes | 128974848 (bytes) 129M (megabytes) 123Mi (mebibytes) |
建議使用 2 的冪次方單位 (Ei, Pi, Ti, Gi, Mi, Ki) 以避免混淆。 |
注意:在設定 Memory 時,請注意大小寫。
m(milli) 和M(Mega) 代表的數量級天差地遠。
K8s 會根據您為容器設定的 requests 和 limits,自動為 Pod 分配一個服務品質 (Quality of Service, QoS) 等級。這個等級決定了當 Node 資源不足時,哪個 Pod 會被優先驅逐。
| QoS 等級 | 設定條件 | 特性 | 驅逐順序 |
|---|---|---|---|
| Guaranteed | 所有容器都必須同時設定 requests 和 limits,且兩者的值完全相等。 |
擁有最高的優先級,資源得到完全保障。 | 最後被驅逐 |
| Burstable | 至少有一個容器設定了 requests,但 requests 和 limits 的值不相等。 |
可以超額使用資源 (burst),但資源不被完全保障。 | 第二順位被驅逐 |
| BestEffort | 所有容器都沒有設定任何 requests 或 limits。 |
優先級最低,沒有任何資源保障。 | 最先被驅逐 |
這就是為什麼設定 requests 和 limits 如此重要:透過將核心服務設定為 Guaranteed,您可以確保在極端情況下,它們會是最後被系統犧牲的對象,從而保障了服務的穩定性。
apiVersion: v1
kind: Pod
metadata:
name: qos-demo
spec:
containers:
- name: guaranteed-container
image: my-app
# QoS: Guaranteed (requests == limits)
resources:
requests:
memory: "200Mi"
cpu: "500m"
limits:
memory: "200Mi"
cpu: "500m"
- name: burstable-container
image: my-app
# QoS: Burstable (requests != limits)
resources:
requests:
memory: "100Mi"
cpu: "250m"
limits:
memory: "200Mi"
cpu: "1"
在這個範例中,如果 Node 資源耗盡,K8s 會先驅逐 burstable-container 所在的 Pod(如果它是 Burstable 或 BestEffort 等級),而 guaranteed-container 所在的 Pod 則會受到保護。
總結來說,資源管理不僅是關於限制,更是關於溝通。透過 requests 和 limits,您向 K8s 清楚地傳達了應用程式的需求和容忍度,而 K8s 則根據這些資訊,為您做出最合理的調度與資源分配決策,共同維護整個叢集的健康與穩定。