requests 与 limits 是什么
requests 表示「至少要给我这么多资源」,调度器按它做装箱计算,也用它判定容器的服务质量等级;limits 表示「最多只能用这么多」,最终落到内核的 cgroup 配额上成为硬约束。一个是给调度器看的账,一个是给运行时看的闸门,两者不写会带来完全不同的后果,混为一谈是资源相关故障的主要来源。
超限以后会发生什么
CPU 属于可压缩资源:超过 limit 只会被节流,进程变慢但不会报错,表现为延迟升高与吞吐下降,从监控指标上看得见。内存不可压缩:超过 limit 会被内核直接杀掉,容器退出码 137、原因是内存不足。当节点整体资源紧张时,系统还会按服务质量等级决定先驱逐谁,所以 requests 填得准不准,直接决定业务被牺牲的顺序。
基本信息
| 适用环境 | 任何 Kubernetes 发行版,在容器资源的字段下声明 |
|---|---|
| CPU 单位 | 核或毫核,1 核等于 1000m |
| 内存单位 | 支持十进制与二进制写法,二进制写法更常见 |
| 调度依据 | requests 之和与节点可分配量比较 |
| 只写 limits 时 | requests 默认等于 limits,等级变为最高保障 |
| 不写任何值 | 等级最低,节点压力大时优先被驱逐 |
典型使用场景
- 资源规划:按实测稳态用量设置请求值,让调度器把 Pod 放到说得下的节点
- 防止单实例吃满节点:用 limit 兜住异常流量下的资源消耗
- 保证关键服务优先:给核心组件设置更完整的请求值提升保障等级
- 排查性能问题:区分是CPU被节流还是内存触发重启
- 成本核算:按请求量估算集群整体容量与预留资源
- 多租户隔离:给每个业务设定边界,避免互相抢占
完整写法
完整写法
containers:
- name: api
image: registry.example.com/api:1.4.2
resources:
requests:
cpu: 200m # 调度按此值装箱
memory: 256Mi # 建议接近实测稳态
limits:
cpu: 1000m # 超过被节流,进程变慢但不报错
memory: 512Mi # 超过被杀,退出码 137字段与后果
| 字段 | 作用 | 超限后果 |
|---|---|---|
| requests 与 CPU | 调度装箱、等级判定 | 无硬限制,多个容器会互相争抢 |
| limits 与 CPU | cgroup 配额 | 被节流,延迟升高但不产生错误 |
| requests 与内存 | 调度装箱、等级判定 | 节点内存不足时按等级排序被驱逐 |
| limits 与内存 | cgroup 上限 | 容器被杀并重启,表现为退出码 137 |
服务质量等级对照
| 等级 | 达成条件 | 被驱逐顺序 |
|---|---|---|
| 最高保障 | 每个容器都同时写了 CPU 与内存的请求和上限且两者相等 | 最后被驱逐 |
| 中等保障 | 写了部分请求或请求与上限不等 | 居中 |
| 最低保障 | 完全没有声明资源 | 最先被驱逐 |
设值经验
- 请求值参考实测稳态用量而非峰值,按峰值设置会让集群利用率长期偏低
- 上限不要贴紧工作集,内存贴太紧会出现周期性重启,CPU 贴太紧会周期性抖动
- 一次性任务与批处理可放宽上限,在线服务应留出余量应对流量毛刺
- 为每个容器单独声明,不要让同一 Pod 里的大户挤掉小户
只写上限不写请求时,请求默认等于上限,容器进入最高保障等级,代价是调度更保守、集群利用率下降。
内存上限设置过低会导致容器被反复杀掉重启;Java 与 Node 这类运行时的堆外内存不计入堆设置,需要按整体内存评估。
自动扩缩基于请求值计算利用率,没有请求值时该指标不可用,扩容会一直显示未知而无法触发。