1. Requests vs Limits
resources:
requests:
cpu: "250m" # 250 millicores = 0.25 CPU(排程用)
memory: "128Mi" # 最低保證記憶體
limits:
cpu: "500m" # 最大 CPU(超過被節流,不會被 kill)
memory: "256Mi" # 最大記憶體(超過被 OOMKilled)
| 資源 | 超過 Requests 時 | 超過 Limits 時 |
|---|---|---|
| CPU | 正常運行(burst) | 被節流(throttling,速度降低,不會被 kill) |
| 記憶體 | 正常運行 | 容器被終止 → OOMKilled |
CPU 單位:
1 CPU = 1000m(millicores)
0.5 CPU = 500m
100m = 0.1 CPU
記憶體單位:
Ki(kibibyte)= 1024 bytes
Mi(mebibyte)= 1024 Ki
Gi(gibibyte)= 1024 Mi
(KB/MB/GB 是十進位,值不同)
2. QoS 等級
QoS = Quality of Service(控制驅逐優先順序)
┌─────────────────────────────────────────────────────────┐
│ GUARANTEED — 最後被驅逐 │
│ ✓ CPU requests == CPU limits │
│ ✓ Memory requests == Memory limits │
│ ✓ Pod 中所有容器都必須滿足條件 │
├─────────────────────────────────────────────────────────┤
│ BURSTABLE — 中間優先順序 │
│ ✓ 至少一個容器設定了 request/limit │
│ ✗ 不滿足 Guaranteed 的條件 │
├─────────────────────────────────────────────────────────┤
│ BESTEFFORT — 最先被驅逐 │
│ ✗ 完全沒有設定 request/limit │
└─────────────────────────────────────────────────────────┘
| QoS 等級 | 條件 | 驅逐優先順序 |
|---|---|---|
| Guaranteed | CPU 和 Memory 的 requests == limits(所有容器) | 最低(最後被驅逐) |
| Burstable | 至少一個容器設定了 request/limit,但不滿足 Guaranteed | 中間 |
| BestEffort | 完全沒有 request/limit | 最高(最先被驅逐) |
考試重點: 查看 Pod QoS 等級的指令:
kubectl describe pod <name> | grep -i qos或kubectl get pod <name> -o jsonpath='{.status.qosClass}'。達到 Guaranteed: CPU 和 Memory 都必須設定 requests = limits,且所有容器(包含 init containers)都必須滿足。
3. LimitRange
LimitRange 為 Namespace 內的 Pod 設定預設 requests/limits — 當 Pod 自身沒有設定時套用。
apiVersion: v1
kind: LimitRange
metadata:
name: mem-limit-range
namespace: development
spec:
limits:
- type: Container
default: # 預設 limits(容器未設定 limits 時)
memory: 512Mi
cpu: 500m
defaultRequest: # 預設 requests(容器未設定 requests 時)
memory: 256Mi
cpu: 250m
max: # 允許的最大 limits
memory: 1Gi
cpu: "1"
min: # 要求的最小 requests
memory: 64Mi
cpu: 50m
4. ResourceQuota
apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: production
spec:
hard:
# 運算資源
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "20"
limits.memory: 40Gi
# 物件數量
pods: "50"
services: "20"
persistentvolumeclaims: "10"
secrets: "30"
configmaps: "30"
考試重點: 在 ResourceQuota 要求資源 limits 的 Namespace 中,所有 Pod 都必須設定 resource requests 和 limits。若沒有設定,LimitRange 需提供預設值。兩者皆無的情況下,API Server 會拒絕 Pod 建立。
5. 速查表
| 情境 | 處理方式 |
|---|---|
| 容器 OOMKilled | 增加 limits.memory |
| 容器被節流(慢) | 增加 limits.cpu |
| Pod 無法排程 | 降低 requests 或擴充叢集 |
| QoS 設為 Guaranteed | CPU 和 Memory 都設 requests == limits |
| 設定 Namespace 預設 limits | LimitRange |
| 限制 Namespace 整體資源 | ResourceQuota |
6. 練習題
Q1: 容器設定 cpu requests=200m、cpu limits=500m、memory requests=256Mi、memory limits=256Mi。此 Pod 的 QoS 等級是什麼(假設為唯一容器)?
- A) Guaranteed
- B) Burstable ✓
- C) BestEffort
- D) Critical
解析: Guaranteed 的條件是所有 requests 等於 limits。此處 cpu requests(200m) ≠ cpu limits(500m)。Memory requests 和 limits 相等(256Mi),但 Guaranteed 條件未完全滿足,因此等級為 Burstable。
Q2: 容器的記憶體使用量超過記憶體 limits。會發生什麼?
- A) 容器被節流(速度降低)
- B) 容器被終止並重啟(OOMKilled) ✓
- C) 容器從節點被驅逐
- D) Pod 被重新排程到其他節點
解析: 不同於 CPU(可壓縮——被節流但不會被 kill),記憶體是不可壓縮資源。容器超過記憶體 limits 時,會以 OOMKilled 退出碼被終止,並由容器運行時重啟。反覆 OOMKill 會導致 CrashLoopBackOff。
Q3: 某 Namespace 有 ResourceQuota 要求設定 limits.memory。在該 Namespace 建立沒有資源 limits 的新 Pod。會發生什麼?
- A) Pod 會無 limits 地啟動(ResourceQuota 僅適用於運行中的 Pod)
- B) 除非 LimitRange 提供預設值,否則 API Server 會拒絕 Pod ✓
- C) Pod 會以預設 limits 512Mi 啟動
- D) ResourceQuota 會自動更新以排除此 Pod
解析: 當 ResourceQuota 涵蓋記憶體 limits 的 Namespace,所有 Pod 都必須在 Spec 中指定記憶體 limits。若 LimitRange 未提供預設值,API Server 會拒絕 Pod。解決方案: 為 Pod 設定 limits,或在 Namespace 建立具有 default/defaultRequest 的 LimitRange。