返回列表

AWS帳號認證開戶 容器資源限制詳解:CPU、記憶體與資源隔離

亞馬遜雲AWS / 2026-10-21 15:43:27

# 容器資源限制詳解:CPU、記憶體與資源隔離

在容器環境中,資源限制不是可選項,而是部署前必須完成的基礎配置。很多線上問題看起來像應用異常,實際上是 CPU 沒有限制、記憶體配置過低、節點超分過度,或資源隔離策略不合理導致。

本文不做概念鋪陳,直接從實際操作出發,說清楚以下幾個問題:

- 容器 CPU 和記憶體應該怎麼限制
- Docker 與 Kubernetes 分別怎麼配置
- `requests` 與 `limits` 怎麼設才不容易出事故
- 為什麼容器會 OOMKilled
- 為什麼 CPU 使用率不高但服務仍然變慢
- 如何驗證限制是否真正生效
- 線上故障如何排查

---

## 一、使用者搜尋這個主題時,真正想解決的是什麼

當使用者搜尋「容器資源限制詳解:CPU、記憶體與資源隔離」時,通常不是想了解術語,而是遇到了以下實際問題:

1. 容器沒有做限制,單個服務吃滿主機資源,影響其他業務
2. Pod 經常被殺掉,但不清楚是程式問題還是記憶體不足
3. Kubernetes 已經設了資源參數,但實際效能和預期不一致
4. 同樣的服務在測試環境正常,上線後出現 CPU 節流、延遲上升
5. 想知道不同類型業務應該如何設定 CPU、記憶體、QoS 與隔離策略

所以本文重點是:怎麼配置、怎麼驗證、怎麼排錯。

---

## 二、容器資源限制最容易出問題的幾個環節

實際部署中,問題大多出在這幾步:

### 1. 只設 limits,不設 requests

這會影響 Kubernetes 排程與資源保障。Pod 可能被排到資源本就緊張的節點,導致執行期抖動。

### 2. 記憶體 limit 設太小

應用啟動正常,但流量一上來就被 OOMKilled。

### 3. CPU limit 設太低

不是直接崩潰,而是請求延遲上升、GC 變慢、吞吐下降。

### 4. 沒有區分業務型別

AWS帳號認證開戶 API 服務、批次任務、快取服務、Java 應用,資源策略完全不同,不能套一份模板。

### 5. 只看應用監控,不看容器層監控

例如應用日誌沒有報錯,但實際上是 cgroup 限制造成節流或 OOM。

---

## 三、Docker 中如何設定 CPU 與記憶體限制

如果你目前使用的是單機 Docker 或在雲伺服器上直接跑容器,資源限制通常在 `docker run` 階段完成。

## 1. 限制記憶體

### 指令範例

```bash
docker run -d \
--name myapp \
--memory=512m \
--memory-swap=512m \
nginx
```

### 參數說明

- `--memory=512m`:容器最大可用記憶體為 512MB
- `--memory-swap=512m`:總記憶體加 swap 上限也為 512MB,等於禁止額外 swap

### 為什麼建議一起設定 `--memory-swap`

如果只設定 `--memory`,沒有明確控制 swap,容器可能在記憶體吃緊時進入 swap,導致延遲顯著增加。對 API 或資料庫類服務,這種情況通常比直接失敗更難排查。

### 驗證方式

```bash
docker inspect myapp | grep -i memory
```

或查看 cgroup 資訊:

```bash
cat /sys/fs/cgroup/memory/docker//memory.limit_in_bytes
```

不同系統路徑可能略有差異,使用 cgroup v2 的環境需要改查對應目錄。

---

## 2. 限制 CPU 核心數

### 指令範例

```bash
docker run -d \
--name cpu-test \
--cpus="1.5" \
nginx
```

### 含義

- `--cpus="1.5"` 表示容器最多可使用 1.5 個 CPU 核心的計算配額

這不是綁定實體核心,而是限制可用 CPU 時間比例。

### 進階設定方式

```bash
docker run -d \
--cpu-period=100000 \
--cpu-quota=50000 \
nginx
```

以上表示每 100000 微秒週期內,最多使用 50000 微秒 CPU 時間,即 0.5 CPU。

通常直接使用 `--cpus` 更直觀。

---

## 3. 綁定 CPU 核心

對延遲敏感型應用,可以指定容器只在特定核心上執行:

```bash
docker run -d \
--name pinned-app \
--cpuset-cpus="0,1" \
nginx
```

這種方式適合:

- 高性能計算
- 某些低延遲服務
- 需要避免跨核調度抖動的場景

不適合大多數普通 Web 應用,因為會降低調度彈性。

---

## 4. Docker Compose 配置範例

```yaml
version: '3.8'
services:
app:
image: myapp:latest
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
```

注意:

- `deploy.resources` 在不同執行模式下支援程度不同
- 若不是 Swarm 環境,需要確認 Compose 版本與執行方式
- 實務上很多團隊在本機測試時誤以為已生效,實際沒有套用成功

建議配置後立即用 `docker stats` 驗證。

---

## 四、Kubernetes 中如何設定 CPU 與記憶體限制

Kubernetes 的重點不只是限制,更包括排程、資源保障與節點分配。

最常用的是 `requests` 和 `limits`。

## 1. 基本配置範例

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 2
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-app
image: nginx:latest
resources:
requests:
cpu: "500m"
memory: "256Mi"
limits:
cpu: "1"
memory: "512Mi"
```

### 參數怎麼理解

- `requests.cpu: 500m`:排程時至少預留 0.5 核心
- `limits.cpu: 1`:執行時最多用 1 核心
- `requests.memory: 256Mi`:排程時保證至少 256Mi 記憶體
- `limits.memory: 512Mi`:超過 512Mi 時可能被 OOM 殺掉

---

## 2. requests 與 limits 的實務設定方法

很多文章只說兩者不同,但沒告訴你怎麼填。實務上可以這樣做。

AWS帳號認證開戶 ### 場景 A:穩定型 API 服務

適合流量較平穩、延遲敏感的服務。

建議:

- `requests` 設為平時使用量的 P95
- `limits` 設為 `requests` 的 1.5 到 2 倍

例如:

- 平時 CPU 約 300m,尖峰 700m
- 平時記憶體 220Mi,尖峰 380Mi

AWS帳號認證開戶 則可設為:

```yaml
requests:
cpu: "400m"
memory: "256Mi"
limits:
cpu: "800m"
memory: "512Mi"
```

### 場景 B:Java 應用

Java 對記憶體限制更敏感,除了 Heap,還包括 Metaspace、Thread Stack、Direct Memory。

建議:

- 不要把 JVM Heap 設到接近容器 memory limit
- 預留 20% 到 30% 給非 Heap 區域

例如容器限制 1Gi:

- `-Xmx` 建議先從 512Mi 到 700Mi 開始,而不是直接設 1024Mi

### 場景 C:批次任務 / 離線處理

這類任務可能短時間大量吃 CPU。

建議:

- `requests` 可相對保守
- `limits.cpu` 可放寬
- 記憶體一定要根據實測,不要只看平均值

### 場景 D:快取或內存型服務

如 Redis 類服務,記憶體比 CPU 更關鍵。

建議:

- memory limit 必須明確
- 應用內部淘汰策略要和容器限制配合
- 不要讓容器 OOM 當作常規淘汰手段

---

## 3. 為什麼有些 Pod 沒爆 CPU,卻明顯變慢

這通常是 CPU Throttling,也就是 CPU 節流。

AWS帳號認證開戶 當容器達到 `limits.cpu` 後,即使節點還有空閒 CPU,容器也可能被限制執行時間。表面看 CPU 使用率不一定很高,但應用延遲會上升。

### 排查方式

先看 Pod 資源:

```bash
kubectl top pod -n default
```

再看容器節流指標,常用 Prometheus 指標如:

- `container_cpu_cfs_throttled_periods_total`
- `container_cpu_cfs_throttled_seconds_total`

如果節流持續增加,代表 `limits.cpu` 可能設太低。

### 解法

- 提高 `limits.cpu`
- 對延遲敏感應用,縮小 `requests` 與 `limits` 落差
- 避免在高峰期把 CPU limit 卡得過死

---

## 五、記憶體限制與 OOMKilled 排查實戰

容器最常見的故障之一就是 OOMKilled。

## 1. 查看 Pod 是否因 OOM 被殺

```bash
kubectl describe pod -n
```

重點看:

- `Last State`
- `Reason: OOMKilled`
- `Exit Code: 137`

如果出現這些訊息,基本可以確認是記憶體超限。

---

## 2. Docker 中查看 OOM

```bash
docker inspect | grep -i oom
```

AWS帳號認證開戶 或者直接看宿主機核心日誌:

```bash
dmesg | grep -i kill
```

常見會看到類似:

```bash
Out of memory: Kill process 12345 (java)
```

---

## 3. OOM 的真正常見原因

不是只有「記憶體不夠」這麼簡單,實務上常見是:

### 原因一:應用本身有記憶體洩漏

特徵:

- 使用量持續上升
- 重啟後短暫恢復
- 流量不變但記憶體曲線持續增長

### 原因二:limit 設得過低

特徵:

- 啟動正常
- 只在高峰期或大查詢時觸發
- 擴大 limit 後立即改善

### 原因三:JVM、Node.js、Python 等執行時與容器記憶體不匹配

例如:

- Java 預設堆外內存未控制
- Node.js 預設 old space 設定不符合容器限制
- Python 多進程模型帶來額外記憶體開銷

### 原因四:快取、buffer、連接池撐大

例如:

- MySQL client 連接池過大
- Nginx buffer 調過頭
- Redis 客戶端積壓大量資料

---

## 4. 解決 OOM 的實際步驟

### 步驟 1:先確認容器限制值

```bash
kubectl get pod -o yaml
```

檢查 `resources.limits.memory`。

### 步驟 2:比對監控中的實際峰值

不要看平均值,要看峰值、尖峰時間段和 GC 前後波動。

### 步驟 3:檢查應用內部參數

例如 Java:

```bash
JAVA_OPTS="-Xms512m -Xmx512m"
```

如果容器 limit 是 512Mi,這種設定就很危險,因為還有非 Heap 記憶體。

### 步驟 4:調整 limit 並做壓測

建議每次調整 20% 到 30%,配合流量回放或壓測,不要一次翻倍後就認為問題已解決。

---

## 六、資源隔離不只是 CPU 和記憶體,還包括節點與命名空間層面

在 Kubernetes 中,單純設定 Pod 資源還不夠,還要考慮多租戶或多業務隔離。

## 1. 使用 Namespace + ResourceQuota

這適合限制某個團隊、某個專案可使用的總資源。

```yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
pods: "20"
```

作用:

- 防止某個 namespace 無限制建立 Pod
- 控制總 requests 與 limits
- 避免共享叢集中的資源失控

---

## 2. 使用 LimitRange 統一默認值

避免開發人員忘記設定資源參數。

AWS帳號認證開戶 ```yaml
apiVersion: v1
kind: LimitRange
metadata:
name: default-limit-range
namespace: default
spec:
limits:
- default:
cpu: "1"
memory: "512Mi"
defaultRequest:
cpu: "200m"
memory: "256Mi"
type: Container
```

如果沒有設定,系統可自動套用預設值。

這對共享測試環境很實用。

---

## 3. 使用節點親和性與污點隔離業務

對高負載服務,建議不要和普通業務混部。

### 做法

- 給高規格節點打標籤
- 使用 `nodeSelector` 或 `nodeAffinity`
- 必要時對節點加 taint,讓只有特定 Pod 可調度上去

範例:

```yaml
spec:
nodeSelector:
workload: high-cpu
```

適用場景:

- 高 CPU 計算型服務
- 大記憶體服務
- 需要更穩定延遲的關鍵業務

---

## 七、如何驗證容器資源限制是否真的生效

配置完成後,不驗證等於沒做。

## 1. Docker 驗證

```bash
docker stats
```

重點看:

- CPU %
- MEM USAGE / LIMIT
- 容器是否達到上限

也可以進入容器內查看:

```bash
docker exec -it myapp sh
```

然後檢查 cgroup 限制檔案。

---

## 2. Kubernetes 驗證

AWS帳號認證開戶 ### 查看資源設定

```bash
kubectl get pod -o jsonpath='{.spec.containers[*].resources}'
```

### 查看實際使用

```bash
kubectl top pod
kubectl top node
```

AWS帳號認證開戶 ### 查看事件

```bash
kubectl describe pod
```

如果有 OOM、Eviction、調度失敗,這裡通常能看到線索。

---

## 3. 壓測驗證

不要只靠靜態查看,必須在壓測下驗證。

建議觀察:

- 平均與 P99 延遲
- CPU 是否接近 limit
- 記憶體是否穩定回收
- 是否出現 throttling
- 是否有重啟或 OOM

如果只在低流量下測試,很容易誤判配置合理。

---

## 八、常見配置錯誤與對應處理方式

## 錯誤 1:只設定 memory limit,沒有設定 CPU

後果:

AWS帳號認證開戶 - 容器可能搶佔大量 CPU
- 同節點其他服務延遲上升

處理:

- 至少為每個服務設定合理的 CPU requests
- 核心服務同時設定 limits

---

## 錯誤 2:CPU limit 設太小

後果:

- 不一定報錯
- 但 RT 飆高、吞吐下降

處理:

- 檢查節流指標
- 提高 CPU limit 或改為更貼近實際需求

---

## 錯誤 3:記憶體 limit 直接等於應用啟動參數

後果:

- 啟動看似正常
- 流量一上來就 OOM

處理:

- 預留執行時額外記憶體
- 對 JVM 類應用預留至少 20% 以上餘量

---

## 錯誤 4:多個高負載 Pod 全排到同一節點

後果:

- 節點資源局部熱點
- 同機服務抖動

處理:

- 使用 Pod Anti-Affinity
- 檢查排程策略
- 為關鍵服務做節點隔離

---

## 錯誤 5:把 requests 設得過高

後果:

- Pod 難以調度
- 節點看起來有空閒,但新 Pod 起不來

處理:

- 根據歷史監控調整 requests
- 不要用理論峰值直接當 requests

---

## 九、不同業務類型的資源配置建議

以下是實務中可直接參考的思路。

## 1. Nginx / 輕量 Web 服務

建議:

- CPU:`requests 100m~200m`,`limits 500m~1`
- 記憶體:`128Mi~256Mi` 起步
- 重點觀察連線數與 buffer 使用

## 2. Java 微服務

AWS帳號認證開戶 建議:

- 記憶體先估算 Heap、非 Heap、執行緒數
- `limits.memory` 不要過緊
- CPU 盡量避免限制過低,否則 GC 容易放大延遲

## 3. Go API 服務

建議:

AWS帳號認證開戶 - 通常記憶體較可控
- CPU limit 可根據 goroutine 實際壓測調整
- 注意高併發時連線池與快取占用

## 4. Redis 類快取服務

建議:

- 明確設定 memory limit
- 應用內 maxmemory 應低於容器 limit
- 預留系統與連線緩衝空間

## 5. 批次任務

建議:

- 適合獨立節點池
- 可放寬 CPU limit,但要避免影響線上服務
- Job 結束後及時釋放資源

---

AWS帳號認證開戶 ## 十、線上故障排查流程:容器變慢、重啟、搶資源時怎麼查

下面是一套可直接落地的排查順序。

## 場景一:Pod 頻繁重啟

AWS帳號認證開戶 ### 排查步驟

1. 查看 Pod 狀態

```bash
kubectl get pod -n
```

2. 查看事件與退出原因

```bash
kubectl describe pod -n
```

3. 查看上一次容器日誌

```bash
kubectl logs --previous -n
```

4. 確認是否 OOMKilled、探針失敗、啟動超時

AWS帳號認證開戶 ### 常見結論

- `OOMKilled`:調整記憶體限制或應用參數
- `CrashLoopBackOff`:先分辨是程式崩潰還是資源不足
- `Unhealthy`:探針過嚴,或 CPU 節流導致回應慢

---

## 場景二:服務 RT 升高,但 CPU 看起來不高

### 排查步驟

1. 查容器節流指標
2. 查 GC、執行緒池、請求堆積
3. 查節點是否有資源競爭
4. 確認 CPU limit 是否設太低

AWS帳號認證開戶 ### 常見結論

- 很多情況不是 CPU 不夠,而是被限得太死

AWS帳號認證開戶 ---

## 場景三:新 Pod 一直 Pending

AWS帳號認證開戶 ### 排查步驟

```bash
kubectl describe pod
```

看事件中是否出現:

- `Insufficient cpu`
- `Insufficient memory`
- 節點親和性不匹配
- taint 無法容忍

### 常見結論

- requests 設過高
- 節點池容量不足
- 隔離策略配置錯誤

---

## 十一、容器資源限制的配置實踐建議

如果你要把這套方法真正用在線上,建議按下面順序執行。

## 建議 1:先收集基線,再定初始值

不要一上來拍腦袋填 `500m/512Mi`。

至少先收集:

- 平均 CPU
- P95 CPU
- 峰值 CPU
- 平均記憶體
- 峰值記憶體
- 啟動期與高峰期的差異

## 建議 2:所有服務都要有 requests

AWS帳號認證開戶 即使是測試環境,也應盡量補齊,否則排程結果沒有參考價值。

## 建議 3:關鍵業務避免極端超分

尤其對 API 閘道、核心交易服務、資料處理入口,不要把多個高負載容器隨意堆在同一節點。

## 建議 4:記憶體以穩為主,CPU 以測為主

- 記憶體寧可保守一點,避免 OOM
- CPU 應依壓測結果調整,不要只看監控平均值

## 建議 5:將限制驗證納入發布流程

每次新版本發布前,至少確認:

- requests / limits 是否有變更
- 啟動記憶體是否異常增加
- 壓測下是否出現 throttling
- HPA 是否會因設定不合理而誤擴縮容

---

## 十二、實用命令清單

以下命令可直接用於日常巡檢與故障排查。

### Docker

```bash
docker stats
docker inspect
docker exec -it sh
dmesg | grep -i oom
```

### Kubernetes

```bash
kubectl get pod -A
kubectl describe pod -n
kubectl top pod -n
kubectl top node
kubectl logs --previous -n
kubectl get pod -o yaml
kubectl get events -n --sort-by=.metadata.creationTimestamp
```

---

## 結語

容器資源限制的核心,不是把 CPU 和記憶體填上去就結束,而是讓服務在可控範圍內穩定運行。

真正有效的做法是:

- 根據實際監控設定 `requests` 和 `limits`
- 對不同業務類型採用不同策略
- 配置後立即驗證是否生效
- 對 OOM、節流、Pending 等問題建立固定排查流程
- 在 namespace、節點、排程層面補齊資源隔離

如果你目前正遇到容器 OOM、CPU 被限速、Pod 難以調度或多服務互相搶資源,最直接的切入點不是重啟服務,而是先檢查資源配置與隔離策略是否合理。這往往比修改程式更快見效。

Telegram售前客服
客服ID
@cloudcup
联系
Telegram售后客服
客服ID
@yanhuacloud
联系