容器资源请求与限制:Requests和Limits配置、服务质量等级、资源超卖策略

好,咱们进入第二章。这一章聊的是Kubernetes里最基础、也最容易踩坑的部分——容器的Requests和Limits。说白了,就是告诉集群:“我这个Pod最少要多少资源,最多能吃多少资源”。

我见过太多团队,要么完全不设限制,导致一个Pod把整台机器打爆;要么设得太死,集群利用率低得可怜。嗯,咱们今天就把这事彻底聊透。

一、Requests和Limits到底是什么?

先看一个最简单的配置:

resources:
  requests:
    memory: "256Mi"
    cpu: "250m"
  limits:
    memory: "512Mi"
    cpu: "500m"

Requests:你向集群“申请”的资源量。调度器根据这个值决定把Pod放在哪台Node上。说白了,这是你的“最低保障”。

Limits:Pod最多能用的资源上限。超过这个值,CPU会被限流,内存会被OOM Kill。

我个人习惯把Requests理解为“预订座位”,Limits理解为“最多能吃几碗饭”。你预订了2个座位,但最多能吃4碗饭——这就是典型的Burstable模式。

二、服务质量等级:Guaranteed / Burstable / BestEffort

Kubernetes根据Requests和Limits的配置方式,把Pod分成三个等级。这个等级决定了Pod被“杀掉”的优先级。

1. Guaranteed(最高优先级)

条件:每个容器都设置了Requests和Limits,并且两者相等。

resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "512Mi"
    cpu: "500m"

这种Pod最“稳”。系统认为它需要固定资源,轻易不会动它。我在项目中遇到过,核心数据库、关键API网关,我都会设成Guaranteed。为什么?因为一旦内存紧张,系统优先杀BestEffort和Burstable,Guaranteed是最后一道防线。

核心原则:关键业务用Guaranteed,非关键业务用Burstable,临时任务用BestEffort。

2. Burstable(中等优先级)

条件:至少有一个容器设置了Requests,但Requests和Limits不相等。

resources:
  requests:
    memory: "256Mi"
    cpu: "250m"
  limits:
    memory: "1Gi"
    cpu: "1"

这是最常见的配置。说白了,你给Pod一个“最低保障”,但允许它在空闲时“多吃点”。我大部分微服务都这么配。你想想看,业务高峰期需要更多CPU,平时又用不了那么多——Burstable正好满足这种弹性需求。

3. BestEffort(最低优先级)

条件:完全不设置Requests和Limits。

# 没有resources字段

这种Pod“有啥吃啥”。系统空闲时它跑得欢,一旦资源紧张,第一个被干掉的就是它。我曾经在CI/CD流水线里用BestEffort跑一些非关键的测试任务——跑成了赚了,跑死了也无所谓。

避坑指南:千万不要在生产环境的核心服务上用BestEffort。我曾经见过一个团队,把线上API网关设成了BestEffort,结果隔壁Pod一吃内存,网关直接被OOM Kill,整个业务挂了半小时。

三、资源超卖策略:如何“榨干”集群资源?

好,现在问题来了:如果所有Pod都按Guaranteed配置,集群利用率可能只有30%-40%。太浪费了。怎么办?超卖。

超卖,说白了就是“多分配、少使用”。你给Pod设了1核CPU的Requests,但它实际只用0.2核。那剩下的0.8核就可以给别的Pod用。

1. CPU超卖

CPU是可压缩资源。什么意思?就是Pod用超了,系统可以“限流”,不会杀掉它,只是让它变慢。

我常用的策略:

  • 核心服务:Requests = Limits,不超卖
  • 普通服务:Requests设为实际使用量的70%,Limits设为峰值的150%
  • 批处理任务:Requests设得很低,Limits设得很高

举个例子:

# 普通Web服务
resources:
  requests:
    cpu: "200m"    # 实际平时只用150m
  limits:
    cpu: "500m"    # 高峰期能冲到400m

2. 内存超卖

内存是不可压缩资源。超了就是超了,系统只能杀掉Pod。所以内存超卖要非常谨慎。

我的经验:

  • 内存Requests = 实际使用量的90%
  • 内存Limits = 实际使用量的120%
  • 永远不要设置Limits超过Node内存的80%

个人技巧:我习惯用Vertical Pod Autoscaler(VPA)来推荐Requests和Limits。跑个几天,VPA会告诉你“这个Pod实际用了多少,建议设多少”。然后你再手动调整。别完全相信VPA,它有时候会推荐得太保守。

四、实战配置建议

说了这么多,给出一套我常用的配置模板:

业务类型 QoS等级 CPU Requests CPU Limits Memory Requests Memory Limits
核心API Guaranteed 1 1 1Gi 1Gi
普通微服务 Burstable 250m 500m 512Mi 1Gi
批处理任务 Burstable 100m 2 256Mi 2Gi
临时测试 BestEffort

嗯,这套配置我用了两年,集群利用率从35%提到了65%。当然,具体数值要根据你的业务调整。

五、常见坑与避坑指南

  • 坑1:Limits设得太低——Pod频繁被OOM Kill。我曾经有个Java服务,Limits只给了512Mi,结果JVM一GC就挂。后来调到2Gi才稳定。
  • 坑2:Requests设得太高——集群调度不进去。你想想看,每个Pod都申请2核,但实际只用0.5核,那10台Node的集群只能调度5个Pod,太浪费了。
  • 坑3:所有Pod都用Guaranteed——集群利用率极低。我见过一个团队,所有服务都设成Requests=Limits,结果集群利用率不到20%。
  • 坑4:完全不设Limits——某个Pod可能把整台机器打爆。特别是那些有内存泄漏的服务,不设Limits就是定时炸弹。

总结一句话:Requests保底,Limits防爆,QoS定生死,超卖提效率。把这四个点吃透了,Kubernetes资源管理你就入门了。

下一章咱们聊聊HPA和VPA,怎么让Pod自动伸缩。嗯,那才是真正的“自动驾驶”。