EKS Pod 资源优化指南
📅 撰写日期: 2026-02-12 | 修改日期: 2026-02-14 | ⏱️ 阅读时间: 约 46 分钟
📌 基准环境: EKS 1.30+, Kubernetes 1.30+, Metrics Server v0.7+
概述
在 Kubernetes 环境中,Pod 资源设置直接影响集群效率和成本。50% 的容器仅使用了其请求 CPU 的 1/3,这导致平均 40-60% 的资源浪费。本指南通过 Pod 级别的资源优化,提供最大化集群效率并降低 30-50% 成本的实战策略。
与相关文档的区别
- karpenter-autoscaling.md: 节点级别的自动扩缩容(本文档是 Pod 级别)
- cost-management.md: 整体成本策略(本文档专注于资源设置)
- eks-resiliency-guide.md: 仅将资源设置作为检查清单项
核心内容
- Requests vs Limits 深入理解: CPU throttling 和 OOM Kill 机制
- QoS 类别策略: Guaranteed、Burstable、BestEffort 的实战应用
- VPA 完整指南: 自动资源调整与 HPA 共存模式
- Right-Sizing 方法论: 基于 P95 的资源估算及 Goldilocks 使用
- 成本影响分析: 资源优化的实际节省效果
学习目标
完成本指南后,您将能够:
- 理解 CPU 和 Memory requests/limits 的精确工作原理
- 根据工作负载特性选择合适的 QoS 类别
- 安全地配置 VPA 和 HPA 共存
- 基于实际使用量执行 Right-Sizing
- 将资源效率提升 30% 以上
前置要求
所需工具
| 工具 | 版本 | 用途 |
|---|---|---|
| kubectl | 1.28+ | Kubernetes 集群管理 |
| helm | 3.12+ | VPA、Goldilocks 安装 |
| metrics-server | 0.7+ | 资源指标收集 |
| kubectl-top | 内置 | 资 源使用量确认 |
所需权限
# RBAC 权限确认
kubectl auth can-i get pods --all-namespaces
kubectl auth can-i get resourcequotas
kubectl auth can-i create verticalpodautoscaler
前置知识
- Kubernetes Pod、Deployment 基本概念
- YAML 清单编写经验
- Linux cgroups 基本理解(推荐)
- Prometheus/Grafana 基本使用方法(推荐)
Resource Requests & Limits 深入理解
2.1 Requests vs Limits 的精确含义
Resource requests 和 limits 是 Kubernetes 资源管理的核心概念。
Requests(请求量)
- 定义: 调度器在 Pod 放置时保证的最小资源
- 作用: 节点选择依据、QoS 类别决定
- 保证: kubelet 始终确保此量的可用
Limits(限制量)
- 定义: kubelet 强制执行的最大资源
- 作用: 防止资源耗尽、限制嘈杂邻居(noisy neighbor)
- 强制: CPU 使用 throttling,Memory 使用 OOM Kill
核心差异
| 属性 | CPU | Memory |
|---|---|---|
| 超过 Requests 时 | 如果其他 Pod 未使用则可以使用 | 如果其他 Pod 未使用则可以使用 |
| 超过 Limits 时 | Throttling(进程速度降低) | OOM Kill(进程强制终止) |
| 是否可压缩 | 可压缩 (Compressible) | 不可压缩 (Incompressible) |
| 超额使用风险 | 性能下降 | 服务中断 |
2.2 CPU 资源深入理解
CPU Millicore 单位
# CPU 表示方法
resources:
requests:
cpu: "500m" # 500 millicore = 0.5 CPU core
cpu: "1" # 1000 millicore = 1 CPU core
cpu: "2.5" # 2500 millicore = 2.5 CPU cores
1 CPU core = 1000 millicore
- AWS vCPU、Azure vCore 均相同
- 在超线程环境中也是以逻辑核心为基准
CFS Bandwidth Throttling
Linux CFS (Completely Fair Scheduler) 强制执行 CPU limits:
# cgroups v2 基准
/sys/fs/cgroup/cpu.max
# 示例: "100000 100000" = 每 100ms 周期可使用 100ms (100% = 1 CPU)
# 示例: "50000 100000" = 每 100ms 周期可使用 50ms (50% = 0.5 CPU)
Throttling 机制
时间周期: 100ms
CPU Limit: 500m (0.5 CPU)
→ 100ms 中仅可使用 50ms
实际运行:
[0-50ms] ████████████████████ (运行)
[50-100ms] ...................... (throttled)
[100-150ms] ████████████████████ (运行)
[150-200ms] ...................... (throttled)
不设置 CPU Limits 的策略
Google、Datadog 等大规模集群运营组织不设置 CPU limits:
原因:
- CPU 是可压缩资源(其他 Pod 需要时会自动调整)
- 避免因 Throttling 导致的不必要性能下降
- 仅通过 Requests 即可实现调度和 QoS 控制
替代推荐:
- CPU requests 基于 P95 使用量设置
- 通过 HPA 按负载水平扩展
- 加强节点级别资源监控
例外(需要设置 Limits):
- 批处理作业(防止 CPU 独占)
- 不可信的工作负载
- 多租户环境
CPU 资源设置示例
# 模式 1: 仅设置 Requests(推 荐)
apiVersion: v1
kind: Pod
metadata:
name: web-server
spec:
containers:
- name: nginx
image: nginx:1.25
resources:
requests:
cpu: "250m" # 基于 P95 使用量
memory: "128Mi"
# 省略 limits - 利用 CPU 可压缩资源特性
---
# 模式 2: 批处理作业(设置 Limits)
apiVersion: batch/v1
kind: Job
metadata:
name: data-processing
spec:
template:
spec:
containers:
- name: processor
image: data-processor:v1
resources:
requests:
cpu: "1000m"
limits:
cpu: "2000m" # 防止 CPU 独占
memory: "4Gi"
restartPolicy: OnFailure
2.3 Memory 资源深入理解
Memory 单位
# Memory 表示方法 (1024 基准 vs 1000 基准)
resources:
requests:
memory: "128Mi" # 128 * 1024^2 bytes = 134,217,728 bytes
memory: "128M" # 128 * 1000^2 bytes = 128,000,000 bytes
memory: "1Gi" # 1 * 1024^3 bytes = 1,073,741,824 bytes
memory: "1G" # 1 * 1000^3 bytes = 1,000,000,000 bytes
推荐: 使用 Mi、Gi(1024 基准,Kubernetes 标准)
OOM Kill 机制
当超过 Memory limits 时,Linux OOM Killer 会强制终止进程:
实际使用量 > Memory Limit
→ 超过 cgroup memory.max
→ Kernel OOM Killer 触发
→ 进程 SIGKILL
→ Pod 状态: OOMKilled
→ kubelet 重启 Pod(遵循 RestartPolicy)
OOM Score 计算
# 查看每个进程的 OOM Score
cat /proc/<PID>/oom_score
# OOM Score 计算因素
# 1. 内存使用量(越高分数越高)
# 2. oom_score_adj 值(每个 QoS 类别不同)
# 3. root 进程保护(-1000 = 绝不 Kill)
Memory limits 必须设置
Memory 是不可压缩资源,因此必须设置 limits:
原因:
- Memory 耗尽时整个节点不稳定
- 可能导致 Kernel Panic
- 影响其他 Pod(节点 Eviction)
推荐设置:
requests = limits(Guaranteed QoS)- 或
limits = requests * 1.5(Burstable QoS) - JVM 应用:Heap 大小设置为 limits 的 75%
Memory 资源设置示例
# 模式 1: Guaranteed QoS(稳定性优先)
apiVersion: apps/v1
kind: Deployment
metadata:
name: database
spec:
replicas: 3
template:
spec:
containers:
- name: postgres
image: postgres:16
resources:
requests:
cpu: "2000m"
memory: "4Gi"
limits:
cpu: "2000m" # 与 requests 相同
memory: "4Gi" # 与 requests 相同 (Guaranteed)
---
# 模式 2: JVM 应用
apiVersion: apps/v1
kind: Deployment
metadata:
name: java-app
spec:
template:
spec:
containers:
- name: app
image: java-app:v1
env:
- name: JAVA_OPTS
value: "-Xmx3072m -Xms3072m" # limits 的 75% (4Gi * 0.75 = 3Gi)
resources:
requests:
memory: "4Gi"
limits:
memory: "4Gi"
---
# 模式 3: Node.js 应用
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodejs-api
spec:
template:
spec:
containers:
- name: api
image: nodejs-api:v2
env:
- name: NODE_OPTIONS
value: "--max-old-space-size=896" # limits 的 70% (1280Mi * 0.7 = 896Mi)
resources:
requests:
memory: "1280Mi"
limits:
memory: "1280Mi"
2.4 Ephemeral Storage
容器本地存储也可以作为资源进行管理:
apiVersion: v1
kind: Pod
metadata:
name: ephemeral-demo
spec:
containers:
- name: app
image: busybox
resources:
requests:
ephemeral-storage: "2Gi" # 最低保证
limits:
ephemeral-storage: "4Gi" # 最大使用量
volumeMounts:
- name: cache
mountPath: /cache
volumes:
- name: cache
emptyDir:
sizeLimit: "4Gi"
Ephemeral Storage 包含项:
- 容器层写入
- 日志文件(
/var/log) - emptyDir 卷
- 临时文件
节点 Eviction 阈值:
# kubelet 设置
evictionHard:
nodefs.available: "10%" # 节点整体磁盘低于 10% 时 eviction
nodefs.inodesFree: "5%" # inode 低于 5% 时 eviction
imagefs.available: "10%" # 镜像文件系统低于 10% 时 eviction