返回首页

3.2 Resource Request / Limit 与 QoS

很多人学 Kubernetes 时,最容易“看懂 YAML,却看不懂资源行为”。

比如:

  • 为什么 Pod 能调度上去,但跑起来很卡?
  • 为什么明明限制了 CPU,服务只是变慢,却没有直接挂掉?
  • 为什么内存一超就 OOMKilled
  • 为什么有的 Pod 在节点压力下会优先被驱逐?

这些问题背后,几乎都和 requestslimits、QoS 有关。

这一章我们把这条线完整串起来:资源申请怎么影响调度,资源上限怎么影响运行,QoS 又怎么影响驱逐顺序。

1. Request 与 Limit 的含义与区别

Kubernetes 允许你为容器声明资源需求。官方文档说明:当你为 Pod 中的容器设置资源 request 时,kube-scheduler 会依据 request 决定 Pod 可以放到哪些节点;而 limits 则用于约束容器运行时可使用的资源上限。::cite[327]

1.1 最简单的理解

  • request:调度阶段的“保底申请”
  • limit:运行阶段的“使用上限”

也就是说:

  • 调度器主要看 request
  • 容器运行时是否会被限制,主要看 limit

1.2 一张表理解 request 和 limit

维度 request limit
作用阶段 调度阶段 运行阶段
关注对象 调度器是否允许放到某节点 容器最多能用多少
CPU 行为 保证可分配下限 超过上限会被节流
内存行为 影响节点放置 超过上限可能触发 OOM
是否建议设置 建议设置 多数生产场景建议设置

1.3 一个标准示例

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

这段配置可以理解为:

  • 调度器会按 250m CPU + 256Mi 内存 去找节点;
  • 容器运行后,最多只能使用 500m CPU + 512Mi 内存

2. CPU 与内存资源如何被调度与限制

2.1 CPU:主要体现为“可调度 + 节流”

官方文档指出:当你为容器配置 CPU request 和 CPU limit 时,容器在系统有空闲 CPU 的情况下,至少能获得 request 对应的 CPU 份额;同时,容器不能超过设定的 CPU limit。::cite[328]

换句话说:

  • 调度时,CPU request 参与节点筛选;
  • 运行时,CPU limit 决定最多能跑多快。

如果一个服务 CPU 经常打满、响应变慢,但进程并没有退出,常见原因之一就是:被 CPU limit 节流了

2.2 内存:主要体现为“可调度 + OOM 风险”

内存和 CPU 最大的不同在于:内存超限的代价通常更重

官方资源管理文档说明,Pod 的资源分配同样基于 request,而运行期会受 limit 约束。对内存来说,一旦进程实际占用持续超过 limit,就更容易被内核 OOM 处理,最终体现为容器退出或 OOMKilled。::cite[327]

所以你会发现:

  • CPU 超限:常常是变慢;
  • 内存超限:常常是直接被杀。

2.3 一个便于记忆的对比

资源 request 影响什么 limit 影响什么 超限典型表现
CPU 是否能调度到节点 最大可用 CPU throttling,变慢
Memory 是否能调度到节点 最大可用内存 OOMKilled,重启

3. 实操:分别观察 request 与 limit

3.1 创建一个 Burstable Pod

apiVersion: v1
kind: Pod
metadata:
  name: burstable-demo
spec:
  containers:
    - name: app
      image: nginx:1.27
      resources:
        requests:
          cpu: "100m"
          memory: "128Mi"
        limits:
          cpu: "500m"
          memory: "256Mi"

应用资源:

kubectl apply -f burstable-demo.yaml

查看详细信息:

kubectl describe pod burstable-demo

你会看到:

  • requests 被记录下来,供调度和 QoS 使用;
  • limits 被记录下来,供运行时限制使用。

3.2 创建一个 Guaranteed Pod

apiVersion: v1
kind: Pod
metadata:
  name: guaranteed-demo
spec:
  containers:
    - name: app
      image: nginx:1.27
      resources:
        requests:
          cpu: "500m"
          memory: "256Mi"
        limits:
          cpu: "500m"
          memory: "256Mi"

在这个例子里,CPU 和内存的 request 与 limit 完全相等,因此它会进入 Guaranteed QoS。

3.3 创建一个 BestEffort Pod

apiVersion: v1
kind: Pod
metadata:
  name: besteffort-demo
spec:
  containers:
    - name: app
      image: nginx:1.27

这个 Pod 没有设置任何 CPU / 内存 request 和 limit,因此是 BestEffort。

4. QoS 分类:Guaranteed、Burstable、BestEffort

Kubernetes 会根据 Pod 中各容器声明的 CPU / 内存 request 与 limit,为 Pod 自动分配 QoS 等级。官方文档说明,这个分类会影响节点资源不足时的驱逐决策。::cite[132]

4.1 Guaranteed

满足条件:Pod 内每个容器都同时设置了 CPU 和内存 request / limit,且 request 必须分别等于 limit。 这是官方定义 Guaranteed QoS 的条件。::cite[132]

适合场景:

  • 数据库
  • 消息队列
  • 强依赖稳定资源的核心服务

特点:

  • 资源边界最明确;
  • 在资源压力下通常最晚被驱逐。

4.2 Burstable

满足条件:至少有一个容器设置了 request 或 limit,但不满足 Guaranteed 条件。 官方示例中,设置了 request 和 limit 但两者不相等的 Pod,会被判定为 Burstable。::cite[133]

适合场景:

  • 大多数 Web 服务
  • 普通业务 API
  • 可水平扩展的无状态服务

特点:

  • 比 BestEffort 更稳;
  • 配置弹性更大;
  • 生产环境最常见。

4.3 BestEffort

满足条件:Pod 中所有容器都没有设置任何 CPU / 内存 request 和 limit。 官方文档明确指出,这种情况下 Pod 的 QoS 为 BestEffort。::cite[133]

适合场景:

  • 临时测试
  • 低价值批处理
  • 演示环境

特点:

  • 最容易被驱逐;
  • 资源不可预测;
  • 不适合关键生产业务。

4.4 一张表记住三类 QoS

QoS 类别 条件 稳定性 典型用途
Guaranteed 每个容器 CPU/内存 request=limit 最高 核心状态型服务
Burstable 设置了资源,但不满足 Guaranteed 中等 普通生产服务
BestEffort 什么都不配 最低 临时测试任务

5. OOM、驱逐与资源配置误区

5.1 OOM 不等于调度失败

很多初学者会混淆两个阶段:

  • 调度失败:Pod 没放上节点;
  • OOMKilled:Pod 已经在节点上运行了,但运行中内存超限或发生内存压力。

前者是调度问题,后者是运行时资源问题。

5.2 驱逐和 QoS 有直接关系

官方 QoS 文档说明:Kubernetes 依赖 QoS 分类,在节点资源不足时决定优先驱逐哪些 Pod。通常来说,BestEffort 最容易被驱逐,Burstable 次之,Guaranteed 通常最靠后。::cite[132]

所以 QoS 不是“考试概念”,而是会直接影响线上稳定性。

5.3 误区一:只配 limit,不配 request

这是很常见的错误。

问题在于:

  • 调度器核心看的是 request;
  • 如果 request 过低或缺失,Pod 可能被放进一个并不适合长期承载它的节点;
  • 运行期一旦真实负载上来,就容易出现资源争抢、延迟抖动,甚至被驱逐。

5.4 误区二:把 request 直接配成峰值

如果把 request 配得过大,调度器会认为这个 Pod 需要很多资源,从而导致:

  • 节点可选范围变小;
  • 集群利用率下降;
  • Pod 更容易 Pending。

所以 request 应该更接近稳定运行所需值,而不是盲目按理论峰值填写。

5.5 误区三:内存 limit 配太紧

内存和 CPU 不一样。

CPU 被卡住,多数情况下只是慢;但内存 limit 过紧,业务稍一抖动就可能直接 OOM。对于有缓存、JVM、Go 堆增长、批量读写峰值的应用,尤其要留足余量。

5.6 误区四:生产环境大量使用 BestEffort

BestEffort 最大的问题不是“省事”,而是不可控

一旦节点资源吃紧,这类 Pod 往往最先被牺牲。因此,正式环境里至少应该为关键业务配置 request,避免完全裸奔。

6. 实操:快速查看 QoS 与资源声明

6.1 查看 Pod 的 QoS

kubectl get pod guaranteed-demo -o yaml

你会在状态里看到:

status:
  qosClass: Guaranteed

6.2 对比三个示例 Pod

kubectl get pod guaranteed-demo burstable-demo besteffort-demo -o custom-columns=NAME:.metadata.name,QOS:.status.qosClass

你会得到类似结果:

NAME              QOS
guaranteed-demo    Guaranteed
burstable-demo    Burstable
besteffort-demo   BestEffort

6.3 查看资源声明

kubectl describe pod burstable-demo

重点关注:

  • Requests
  • Limits
  • QoS Class
  • Events

7. 生产环境里的配置建议

7.1 无状态服务

推荐从 Burstable 起步:

  • request 按稳定期负载设置;
  • limit 预留突发空间;
  • 配合 HPA/VPA 或监控持续调整。

7.2 核心状态服务

更适合 Guaranteed:

  • 资源更稳定;
  • 更不容易在压力下被驱逐;
  • 更利于做容量规划。

7.3 不要靠“感觉”配资源

更靠谱的方式是:

  1. 先基于压测和监控给出初值;
  2. 观察 CPU 使用率、内存峰值、重启次数、延迟抖动;
  3. 再持续修正 request / limit。

8. 本章小结

把这一章压缩成几句话:

  1. request 主要影响调度,limit 主要影响运行。
  2. CPU 超限更像变慢,内存超限更像被杀。
  3. QoS 由 request / limit 组合自动决定。
  4. 节点压力下,QoS 会影响驱逐优先级。
  5. 生产环境最常见的是 Burstable,核心服务常用 Guaranteed。

只要你把 request、limit、QoS 这三者串起来,后面再看驱逐、配额、优先级时,就会容易很多。


📝 版权声明:本文为原创技术博客,转载请注明出处。

如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!

上一篇

6.3:Pod 安全标准

下一篇

1.1 Kubernetes 是什么:容器编排的起点