跳到主要内容

Resource 配置速查

requests 决定 Pod 能不能被调度上去、QoS 落在哪一档;limits 决定运行时会不会被限流或 OOMKill。本页把单位写法、语义区别、常用模板和踩坑点浓缩成速查表,原理详解见调度与资源管理。

单位说明​

CPU​

CPU 以「核」为单位,支持小数和毫核(m,millicore)两种写法,最小粒度 1m。

写法含义备注
11 核等价于 1000m
0.5 / 500m0.5 核两种写法等价,推荐统一用毫核
100m0.1 核小型服务 request 的常见起步值

CPU 是可压缩资源:用量超过 limit 时被 CFS 限流(throttle),进程变慢但不会被杀。

内存​

内存以字节为单位,单位后缀分二进制和十进制两族,含义不同,不要混用:

后缀族写法进制换算
二进制Ki Mi Gi Ti10241Mi = 1024Ki = 1,048,576 B
十进制k M G T10001M = 1000k = 1,000,000 B
裸数字134217728—直接按字节计
  • 建议统一用 Mi/Gi:十进制的 1G 比二进制的 1Gi 少约 7%,混用容易估错量。
  • 内存后缀里还有个小写的 m 表示毫字节(0.001 B),没有实际用途,写出来基本是笔误。
  • 内存是不可压缩资源:用量超过 limit 直接 OOMKill(退出码 137),没有「变慢」这个中间态。

Request 与 Limit 的语义​

维度requestslimits
调度调度器按它筛选节点:节点 allocatable 减去已分配的 requests 后还装得下,才算可行节点不参与调度
运行时保证能拿到的下限;节点有空闲 CPU 时按各容器 request 权重瓜分CPU 超限被 throttle;内存超限被 OOMKill
QoS判定 QoS 等级的输入之一判定 QoS 等级的输入之一
超卖节点上所有 Pod 的 requests 之和不超过 allocatablelimits 之和允许超过节点容量(超卖),代价是资源紧张时有人被限流或被杀

常见搭配策略​

场景requestslimits理由
Web 服务(nginx、Node 等)cpu: 100m–250m,memory: 128–256Mi内存给 request 的 2 倍左右;CPU 不设 limit,或放宽到 request 的 3–4 倍流量有峰谷,CPU 需要突发空间;内存按日常峰值留 buffer,防止抖动期 OOM
批处理 / Jobcpu: 500m–1,memory: 512Mi–1Gi与 requests 相等(凑 Guaranteed)跑到一半被驱逐重来的代价最高,用 Guaranteed 换取稳定性
Java 应用cpu: 500m–1;内存按「堆 + 非堆」估算,如堆 1g 则 memory: 1536Mi–2Gi内存 limit 不低于 request;CPU limit 谨慎,宁可不设JVM 启动期瞬时 CPU 很高,limit 卡太死会拖慢启动、引起 throttle 抖动;堆外还有元空间、直接内存、线程栈要预留

配置示例​

容器级 requests/limits​

apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- name: app
image: nginx:1.27
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi

Namespace 级 LimitRange​

给整个 namespace 设置默认值与上下限,容器没写 resources 时自动补默认 request/limit:

apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: demo
spec:
limits:
- type: Container
default: # 容器未声明时的默认 limits
cpu: 500m
memory: 512Mi
defaultRequest: # 容器未声明时的默认 requests
cpu: 100m
memory: 128Mi
max: # 单容器允许的上限
cpu: "2"
memory: 2Gi
min: # 单容器允许的下限
cpu: 50m
memory: 64Mi

Namespace 级 ResourceQuota​

限制整个 namespace 的资源总量与对象数量,超出的 Pod 在创建时直接被拒:

apiVersion: v1
kind: ResourceQuota
metadata:
name: team-quota
namespace: demo
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
pods: "20"
services: "10"
persistentvolumeclaims: "5"
配额一设,request 必填

namespace 一旦配置了包含 requests.cpu 或 requests.memory 的 ResourceQuota,新建 Pod 的每个容器都必须显式声明对应的 request(可借助 LimitRange 的 defaultRequest 兜底),否则创建会被拒绝。

QoS 等级速查​

QoS 是 Pod 级属性,由所有容器的 requests/limits 声明情况共同决定:

QoS 等级判定规则节点资源紧张时适用场景
Guaranteed每个容器的 cpu 和 memory 都同时设置了 requests 和 limits,且二者相等最后被驱逐(oom_score_adj 最小)关键业务、有状态服务
Burstable至少一个容器设置了 requests 或 limits,但不满足 Guaranteed 条件中间梯队,实际用量超出 requests 越多越先被驱逐普通 Web 服务
BestEffort所有容器都没有设置任何 requests 和 limits最先被驱逐(oom_score_adj 最大)一次性任务、可随时重跑的 Job
关键业务尽量 Guaranteed

生产核心服务建议把 requests 与 limits 设为相等:驱逐顺序排最后、OOM 优先级最低,节点压力再大也是最后一批受害者。若担心 CPU 被限流,可以只去掉 CPU 的 limit、保留足额 request,此时降级为 Burstable,但换来了 CPU 突发空间。

常见坑​

CPU limit 导致 Java / Go 应用 throttle​

CPU 限流由 CFS 带宽控制实现:kubelet 把 limit 换算成每个调度周期的配额 —— 周期 cpu.cfs_period_us 默认 100ms,limit: 500m 对应配额 cpu.cfs_quota_us 为 50ms。

问题在于多线程应用:Java 线程池、Go 的 goroutine 可能在一个 100ms 周期的头几毫秒就把 50ms 配额打满,然后整个容器被冻结到下个周期开始。表现为 RT 毛刺、p99 飙升,而监控里的 CPU 利用率看起来根本没用满,极具迷惑性。

排查与对策:

手段说明
container_cpu_cfs_throttled_periods_total被限流的周期数,持续增长即中招
container_cpu_cfs_throttled_seconds_total累计被冻结的时长
去掉或放宽 CPU limit只保留 request,空闲 CPU 按 request 权重分配,弹性最好
JVM 版本JDK 8u191+ / 11+ 能识别容器核数,更老版本会按节点核数开线程池,加剧配额消耗
Go 版本Go 1.25 起 GOMAXPROCS 默认感知 cgroup 配额;更早版本需引入 automaxprocs 库修正

只配 limit 不配 request​

Kubernetes 会自动把 request 补成与 limit 相等。这带来两个隐性后果:

  • 调度按 limit 预留资源,节点能容纳的 Pod 数骤减,集群利用率下降;
  • cpu 和 memory 都只配 limit 时,Pod 直接变成 Guaranteed —— 表面上「省事」,实际把整个服务的资源弹性焊死了。

正确姿势:request 必配,limit 按需配。

内存 limit 贴峰值配置​

内存不可压缩,超限即 OOMKill,没有 throttle 那样的缓冲带。JVM、Node 这类带运行时的程序真实峰值比直觉高(堆外内存、JIT、缓存),limit 贴着观测峰值配,流量一抖就重启。

建议按「峰值 × 1.2 ~ 1.5」设置,再用 container_memory_working_set_bytes 观察长期峰值后逐步收紧。