4. 容器资源限制基础:requests 与 limits 的定义、CPU 与内存单位、QoS 类别
在 Kubernetes 集群中,容器资源限制是保障集群稳定性与公平调度的基石。没有资源约束的 Pod 可能耗尽节点资源,导致其他 Pod 被驱逐甚至节点宕机。本章深入解析 requests 与 limits 的定义、CPU/内存单位换算以及由此产生的三种 QoS(服务质量)类别,为后续的容量规划与 OPA 策略编写奠定基础。
4.1 requests 与 limits 的定义
Kubernetes 通过两个关键字段控制容器的资源使用:
- requests:容器启动时向节点请求的“最小保证资源”。调度器依据 requests 值选择满足条件的节点;如果节点资源不足,Pod 将处于 Pending 状态。
- limits:容器运行时允许使用的“资源上限”。当容器试图使用超过 limits 的资源时,CPU 会被节流(throttle),内存不足时容器会被 OOM Kill。
关键原则:limits 必须大于或等于 requests。如果只设置 limits 而未设置 requests,Kubernetes 会自动将 requests 设置为与 limits 相同的值。
以下是一个典型的资源声明示例:
apiVersion: v1
kind: Pod
metadata:
name: resource-demo
spec:
containers:
- name: app
image: nginx:1.25
resources:
requests:
cpu: "500m"
memory: "256Mi"
limits:
cpu: "1"
memory: "512Mi"
4.2 CPU 与内存单位详解
Kubernetes 使用标准化单位表示 CPU 和内存,理解这些单位对精确配置至关重要。
| 资源类型 | 单位 | 说明 | 示例 |
|---|---|---|---|
| CPU | 整数核 | 1 个 vCPU / 超线程核心 | cpu: "2" 表示 2 个完整核心 |
| 毫核(m) | 1 核 = 1000m,最小粒度 1m | cpu: "500m" 表示 0.5 个核心 |
|
| 小数 | 与毫核等价,但推荐使用 m 单位 | cpu: "0.5" 等价于 500m |
|
| 内存 | 字节(B) | 基础单位,通常不使用裸数字 | memory: "536870912"(不推荐) |
| Ki / Mi / Gi | 二进制单位(2^10 进制) | memory: "256Mi" = 256 × 1024² 字节 |
|
| K / M / G | 十进制单位(10^3 进制) | memory: "256M" = 256 × 1000² 字节 |
|
| 注意事项 | Kubernetes 内部以字节计算,但推荐使用二进制单位(Mi/Gi)避免精度误差 | ||
常见陷阱:CPU 的 "m" 单位是毫核,不是毫秒。设置
cpu: "1000m" 与 cpu: "1" 完全等价。内存的 "M" 与 "Mi" 相差约 4.86%,在大型内存配置中可能造成意外 OOM。
4.3 QoS 类别:Guaranteed / Burstable / BestEffort
Kubernetes 根据 Pod 中所有容器的 requests 与 limits 配置,自动将 Pod 归入三种 QoS(服务质量)类别之一。该类别决定了节点资源紧张时 Pod 被驱逐的优先级。
4.4 三种 QoS 类别的详细对比
| QoS 类别 | 触发条件 | CPU 行为 | 内存行为 | 驱逐优先级 | 典型场景 |
|---|---|---|---|---|---|
| Guaranteed | 所有容器 requests == limits(CPU 和内存均需满足) | 保证 requests 值,可突发至 limits | 保证 requests 值,超过 limits 触发 OOM | 最低(最后被驱逐) | 数据库、关键中间件、有状态服务 |
| Burstable | 至少一个容器设置了 requests,且不满足 Guaranteed 条件 | 保证 requests 值,可突发至 limits | 保证 requests 值,超过 limits 触发 OOM | 中等(按 OOM 分数排序) | Web 服务、API 网关、批处理任务 |
| BestEffort | 没有任何容器设置 requests 和 limits | 无保证,节点空闲时可使用任意 CPU | 无保证,节点空闲时可使用任意内存 | 最高(最先被驱逐) | 开发测试、非关键日志收集、临时任务 |
安全基线建议:生产环境应避免使用 BestEffort 类别。对于关键业务 Pod,推荐使用 Guaranteed 类别以确保资源稳定性;对于可弹性伸缩的微服务,Burstable 类别配合合理的 requests/limits 比例(如 1:2)是性价比最高的选择。
4.5 OOM 分数与驱逐机制
当节点内存不足时,kubelet 会启动驱逐流程。每个 Pod 的 OOM 分数由 QoS 类别和实际内存使用量共同决定:
- BestEffort Pod:OOM 分数最高(通常为 1000),优先被杀死。
- Burstable Pod:OOM 分数 = 1000 - (实际内存使用量 / 节点内存总量) × 1000。使用内存越多的 Pod 分数越高,越容易被杀死。
- Guaranteed Pod:OOM 分数最低(通常为 0-10),仅在节点发生系统级 OOM 且无其他 Pod 可杀时才会被终止。
4.6 安全基线配置示例
以下是一个符合生产安全基线的 Deployment 资源声明,结合了 QoS 类别选择与资源限制:
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
spec:
containers:
- name: app
image: myapp:1.0.0
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"
securityContext:
runAsNonRoot: true
runAsUser: 1001
capabilities:
drop: ["ALL"]
- name: sidecar
image: envoy:1.28
resources:
requests:
cpu: "200m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
securityContext:
runAsNonRoot: true
runAsUser: 1002
配置要点:
- 主容器与 sidecar 均设置了 requests 和 limits,且两者不相等 → 整体 Pod 属于 Burstable 类别。
- CPU 的 requests/limits 比例为 1:2,内存比例为 1:2,允许突发但有限制。
- 结合 securityContext 实现最小权限原则,符合安全基线要求。
4.7 常见配置错误与避坑指南
| 错误模式 | 后果 | 正确做法 |
|---|---|---|
| 只设置 limits 不设置 requests | requests 自动等于 limits,可能过度预留资源 | 显式设置 requests 为实际基线值 |
| CPU requests 设置过高 | 节点资源碎片化,Pod 调度失败 | 基于历史监控数据设置合理的 requests |
| 内存 limits 设置过低 | 容器频繁 OOM Kill,影响服务可用性 | 设置 limits 为 requests 的 1.5~2 倍,并配置 livenessProbe |
| 所有 Pod 使用 BestEffort | 节点资源紧张时大量 Pod 被驱逐 | 至少设置 requests,生产环境避免 BestEffort |
| 使用十进制内存单位(M/G) | 与二进制单位(Mi/Gi)存在约 5% 差异 | 统一使用二进制单位(Mi/Gi) |
容量规划警示:requests 的总和决定了集群的“资源承诺”,而 limits 的总和决定了“资源上限”。在规划节点容量时,应确保节点可分配资源 ≥ 所有 Pod 的 requests 总和,同时预留 10%~20% 的系统开销(kubelet、操作系统、DaemonSet 等)。