路线图

资源管理

星辉 2026-07-02 阅读 6 min 1,106 字 路线图
资源管理 封面

概述#

Kubernetes 的资源管理是整个平台稳定性的基石。如果说调度器是"把 Pod 放在哪台机器上"的决策者,那么资源配置就是"每个 Pod 该拿多少资源"的规则书。这一章从 Request/Limit 的基本概念讲起,到 QoS 等级与驱逐优先级,再到通过 LimitRange 和 ResourceQuota 对命名空间做资源治理,帮你建立完整的资源管理认知。


Request vs Limit#

核心定义#

在 Kubernetes 中,每个容器的资源声明分为两块:

  • Request(请求):调度器在给 Pod 找节点时依据的值。节点上所有 Pod 的 Request 之和不能超过节点可分配资源。如果节点资源不够满足一个 Pod 的 Request,这个 Pod 就永远调度不上去。
  • Limit(限制):容器在运行时能使用的资源上限。超过这个值的行为,视资源类型而不同。

对于 CPU 和内存,两者的行为有本质区别:

维度CPU内存
Request 的作用调度依据;保底保障调度依据;保底保障
Limit 的作用运行时 CPU 使用上限,可以超过 Request 但不超过 Limit硬上限,容器使用的内存绝不能超过 Limit
超限后果CPU 是可压缩资源,超限只会被 throttling(限速),容器不会被杀内存是不可压缩资源,超过 Limit 会触发 OOMKill,容器被强制杀死并重启
可以不设吗可以,但不设意味着该容器可以无限抢占 CPU可以,但不设意味着内存泄漏时可以吃光整个节点的内存

一个直观对比#

text
节点有 4 核 CPU、8GB 内存

Pod A: Request CPU=1核, Limit CPU=2核
Pod B: Request CPU=1核, Limit CPU=2核
Pod C: Request CPU=1核, Limit CPU=2核

三个 Pod 都能调度成功(Request 之和 = 3核 ≤ 4核)
运行时 CPU:
  - 空闲时,A 可以用到 2 核,B 和 C 同理
  - 争抢时,按 Request 比例分配:各得 1/3 的 CPU

内存则不同:
  - Request 内存 = 保底,Limit 内存 = 最后一条红线
  - 一旦某个 Pod 内存使用超过 Limit,内核 cgroup 的 OOM Killer 直接把进程杀掉(kubelet 只是事后把原因上报为 OOMKilled)

设置不当的后果#

问题现象后果
Request 太高一个只用 100m CPU 的服务设了 2000m Request调度器认为节点"已满",不再向该节点调度新 Pod,集群被迫拉新节点,大量资源浪费
Request 太低没有给突发流量留空间CPU 场景下 Pod 被频繁 throttle,响应变慢;内存场景下更危险——可能调度到一台内存已吃紧的节点上
Limit 太低业务峰值时频繁触发 LimitCPU:throttle 导致延迟飙升;内存:直接 OOMKill,Pod 不断重启
不设 Limit放任自流一个内存泄漏的 Pod 能拖垮整个节点,触发连锁雪崩——其他 Pod 被驱逐,节点 NotReady

配置示例#

yaml
resources:
  requests:
    cpu: "200m"      # 0.2 核,调度保底
    memory: "256Mi"   # 256MB 内存保底
  limits:
    cpu: "500m"       # 最多用 0.5 核
    memory: "512Mi"   # 超过 512MB 就 OOMKill

实战建议:对于大多数 Web/API 服务,limits 设为 requests 的 2-4 倍是比较合理的比例。先根据监控数据(Prometheus/Grafana)观察实际用量,再从保守值开始逐步调整。不要一拍脑袋设值。


QoS 三类#

Kubernetes 根据 Pod 中所有容器的 Request/Limit 配置,自动将 Pod 分为三个 QoS(Quality of Service)等级。这个等级的唯一作用就是决定节点资源紧张时,先杀谁

分类规则#

QoS 等级判定条件执行优先级
Guaranteed每个容器的 requests.cpu == limits.cpu requests.memory == limits.memory最高,最后被杀
Burstable至少有一个容器设置了 Request 或 Limit,但不满足 Guaranteed 条件中等
BestEffort所有容器都没有设置任何 Request 或 Limit最低,最先被杀

判断逻辑很简单——Kubernetes 只看你有没有设、设了多少:

yaml
# Guaranteed:Request == Limit
resources:
  requests:
    cpu: "500m"
    memory: "512Mi"
  limits:
    cpu: "500m"
    memory: "512Mi"

# Burstable:有 Request 但不等于 Limit,或只设了其中一项
resources:
  requests:
    cpu: "200m"
    memory: "256Mi"
  limits:
    cpu: "1000m"      # CPU 不等于 Request → Burstable
    memory: "512Mi"

# BestEffort:什么都没设
# 整个 resources 字段为空

驱逐优先级#

当节点内存紧张时,kubelet 按照以下顺序驱逐 Pod:

text
1. BestEffort Pod(最先被杀)
2. Burstable Pod(使用量超过 Request 的先杀)
3. Guaranteed Pod(最后被杀,但超过 Limit 的仍然会被 OOMKill)

关键认知

  • Guaranteed 不是"免死金牌"——超过自身 Limit 一样被 OOMKill,只是在节点资源不足时被驱逐的顺序最靠后。
  • Burstable 是生产环境的大多数——合理设置 Request 提供保底,Limit 提供弹性空间。
  • BestEffort 在生产环境不应出现——这意味着这个 Pod 随时可能被杀,且没有任何资源保障。

实战建议:生产环境的所有服务至少应该是 Burstable。核心服务、数据库等有状态组件可以设为 Guaranteed 以获得最高稳定性。


LimitRange#

如果每个开发者都自己决定设不设 Request/Limit,结果必然是混乱的。LimitRange 是命名空间级别的资源,用来为没设 Request/Limit 的 Pod/容器自动填充默认值,同时限制单个 Pod 或容器不能设置过高或过低的值。

解决什么问题#

  1. 默认值:开发者忘了或不知道要设资源,LimitRange 自动补上合理的默认值
  2. 上限:防止某个 Pod 设置 cpu: "100"(100 核),把整个命名空间的资源配额吃掉
  3. 下限:防止设置 cpu: "1m"(0.001 核),导致调度到一个已经塞满 BestEffort Pod 的节点上

配置示例#

yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: app-limits
  namespace: production
spec:
  limits:
    # 针对容器的限制
    - type: Container
      # 默认值(没设 limits 时自动填入)
      default:
        cpu: "500m"
        memory: "512Mi"
      # 默认 Request(没设 requests 时自动填入)
      defaultRequest:
        cpu: "100m"
        memory: "128Mi"
      # 最大值:不允许超过
      max:
        cpu: "4"
        memory: "8Gi"
      # 最小值:不允许低于
      min:
        cpu: "50m"
        memory: "64Mi"
      # Limit/Request 比例上限
      maxLimitRequestRatio:
        cpu: "4"       # limits.cpu / requests.cpu ≤ 4
        memory: "2"    # limits.memory / requests.memory ≤ 2

这个配置的效果:

  • 如果有人部署一个没有任何 resources 字段的 Pod,LimitRange 会自动加上 requests: cpu=100m, memory=128Milimits: cpu=500m, memory=512Mi
  • 如果有人尝试设 cpu: "10"(超过 max 的 4 核),API Server 直接拒绝
  • 如果有人设 limits.cpu=4000mrequests.cpu=500m(比例 8:1,超过 maxLimitRequestRatio 的 4),也会被拒绝

查看命令#

bash
# 查看命名空间的 LimitRange
kubectl get limitrange -n production

# 查看详细信息(默认值和限制范围一目了然)
kubectl describe limitrange app-limits -n production

ResourceQuota#

LimitRange 管单个 Pod 的上限,ResourceQuota 管整个命名空间的总量。比如一个团队共用一个 namespace,你不想让某个人的 Deployment 把整个 namespace 的 CPU 额度全占满。

配置示例#

yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-quota
  namespace: production
spec:
  hard:
    # 计算资源总量
    requests.cpu: "20"         # 所有 Pod 的 CPU Request 之和不超过 20 核
    requests.memory: "40Gi"    # 所有 Pod 的内存 Request 之和不超过 40GB
    limits.cpu: "40"           # 所有 Pod 的 CPU Limit 之和不超过 40 核
    limits.memory: "80Gi"      # 所有 Pod 的内存 Limit 之和不超过 80GB
    # 对象数量限制
    pods: "50"                 # 最多 50 个 Pod
    services: "10"             # 最多 10 个 Service
    configmaps: "20"           # 最多 20 个 ConfigMap
    secrets: "20"
    persistentvolumeclaims: "10"

配合使用#

LimitRange 和 ResourceQuota 一起使用才能形成完整的资源治理闭环:

text
LimitRange(个体约束)
  ├─ 给没设资源的 Pod 填默认值
  ├─ 限制单个 Pod 的 min/max
  └─ 限制 Limit/Request 比例

ResourceQuota(整体约束)
  ├─ 限制 namespace 的所有 Pod 资源总和
  ├─ 限制 Pod/Service/ConfigMap 等对象的数量
  └─ 超限时 API Server 直接拒绝创建

查看命令#

bash
# 查看命名空间的 ResourceQuota
kubectl get resourcequota -n production

# 查看使用情况(已用/总量)
kubectl describe resourcequota team-quota -n production

多环境资源规划#

在实际工程中,QA、预发、生产三个环境承载的流量和重要性完全不同,资源策略也必须差异化。一套配置打天下,要么 QA 环境浪费严重,要么生产环境资源不足。

三环境资源特征对比#

维度QA / 测试环境预发环境生产环境
流量特征内部测试,低 QPS灰度流量,约为生产的 10-30%全量真实流量,有峰值波动
副本数1-2 个即可2-3 个按流量规划,通常 3+ 并配 HPA
Request 策略贴近实际使用,尽量小中等,留少量余量保守,保底值要能扛日常峰值
Limit 策略紧贴 Request(Limit/Request ≈ 1.5)适中弹性(Limit/Request ≈ 2)大弹性空间(Limit/Request ≈ 3-4)
QoS 目标Burstable 即可Burstable核心服务 Guaranteed,普通服务 Burstable
资源利用率目标50-70%(不怕 throttle)40-60%30-50%(留足突发空间)
节点规格小规格节点(4C8G / 8C16G)中等规格(8C16G / 16C32G)大规格(16C32G+),按业务选型

QA 环境:紧凑型配置#

QA 环境的核心目标是"用最少的资源跑通功能",资源配置应尽量紧凑:

yaml
# QA 环境 — 紧凑型
resources:
  requests:
    cpu: "50m"        # 0.05 核,够跑就行
    memory: "128Mi"
  limits:
    cpu: "200m"       # Limit/Request ≈ 4,给测试时一些弹性
    memory: "256Mi"   # 内存 Limit/Request ≈ 2
# 副本数:1(QA 不需要高可用)
replicas: 1

QA 环境策略要点

  • Request 设到最小可运行值,让一个节点上能挤更多服务
  • Limit 不需要太大弹性——QA 环境的流量是可控的
  • 不怕偶尔 throttle——QA 环境的响应慢可以接受
  • 用 LimitRange 强制设默认值,防止开发者忘记配置
  • ResourceQuota 设得紧,防止某个测试服务吃掉整个环境资源

预发环境:中间态配置#

预发环境是生产的缩小版,流量约为生产的 10-30%,资源配置应在 QA 和生产之间:

yaml
# 预发环境 — 中间态
resources:
  requests:
    cpu: "200m"       # 接近生产但缩减
    memory: "512Mi"
  limits:
    cpu: "500m"       # Limit/Request ≈ 2.5
    memory: "1Gi"
# 副本数:2(验证多副本行为)
replicas: 2

预发环境策略要点

  • Request 设为生产的 30-50%,验证调度和资源分配是否合理
  • Limit 留出弹性,模拟生产突发的场景
  • 副本数至少 2 个,验证滚动更新和多副本行为
  • 配置应尽量贴近生产,让预发能真正暴露生产可能遇到的问题
  • 预发是验证 HPA 配置的好地方——可以模拟流量验证扩缩行为

生产环境:保守型配置#

生产环境的核心目标是"稳定优先,留足余量":

yaml
# 生产环境 — 保守型
resources:
  requests:
    cpu: "500m"       # 保底值能扛日常峰值
    memory: "1Gi"
  limits:
    cpu: "2000m"      # Limit/Request ≈ 4,给流量突发留空间
    memory: "4Gi"     # 内存 Limit/Request ≈ 4
# 副本数:3+ 并配 HPA
replicas: 3
# HPA 配置
hpa:
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 70

生产环境策略要点

  • Request 设为日常峰值的 1.2-1.5 倍——宁可浪费一点,也不要在峰值时被 throttle
  • Limit 设为 Request 的 3-4 倍——应对突发流量和内存峰值
  • 核心服务(数据库、网关、认证)设为 Guaranteed(Request == Limit),确保最后被驱逐
  • 内存 Limit 必须设——不设内存 Limit 等于允许一个 Pod 拖垮整个节点
  • 配合 HPA,让 Pod 数量随 CPU 自动伸缩,Request 是 HPA 计算利用率的分母

多环境配置管理实践#

用 Helm values 覆盖实现同一应用在不同环境的资源差异化:

yaml
# values-qa.yaml
resources:
  requests:
    cpu: "50m"
    memory: "128Mi"
  limits:
    cpu: "200m"
    memory: "256Mi"
replicas: 1

# values-staging.yaml
resources:
  requests:
    cpu: "200m"
    memory: "512Mi"
  limits:
    cpu: "500m"
    memory: "1Gi"
replicas: 2

# values-production.yaml
resources:
  requests:
    cpu: "500m"
    memory: "1Gi"
  limits:
    cpu: "2000m"
    memory: "4Gi"
replicas: 3
hpa:
  enabled: true
  minReplicas: 3
  maxReplicas: 10

部署命令:

bash
helm install myapp ./myapp-chart -f values-qa.yaml -n qa
helm install myapp ./myapp-chart -f values-staging.yaml -n staging
helm install myapp ./myapp-chart -f values-production.yaml -n production

多环境 LimitRange 差异化#

不同环境的 LimitRange 默认值也应该不同:

参数QA预发生产
defaultRequest.cpu50m200m500m
defaultRequest.memory128Mi512Mi1Gi
default.cpu (Limit)200m500m2000m
default.memory (Limit)256Mi1Gi4Gi
max.cpu1000m2000m8000m
max.memory2Gi4Gi16Gi
maxLimitRequestRatio.cpu434

常见反模式#

反模式问题正确做法
三环境用同一套 valuesQA 浪费或生产不足分环境 values 文件
生产 Request = QA Request生产峰值时大量 throttle生产 Request 设为日常峰值的 1.2-1.5 倍
生产不设内存 Limit一个内存泄漏 Pod 拖垮节点内存 Limit 必须设,CPU Limit 可酌情
QA 环境 Request 设太大一个节点跑不了几个服务,成本浪费QA Request 设到最小可运行值
预发副本数 = 1无法验证滚动更新和多副本行为预发至少 2 副本
生产 Limit/Request = 1(全 Guaranteed)弹性不足,HPA 扩容前就 throttle只有核心服务用 Guaranteed

实战要点#

  1. Request 是核心:影响调度、QoS 等级、HPA 的百分比指标计算。务必设置合理值。
  2. 先观察再设值:部署 Prometheus + Grafana(哪怕是最简部署),观察 1-2 天的 CPU/内存实际使用量后再定 Request/Limit。
  3. LimitRange 全覆盖:生产命名空间必须配置 LimitRange,防止 BestEffort Pod 出现。开发/测试环境可以放宽但不建议完全取消。
  4. ResourceQuota 按团队分:多团队共享集群时,每个团队一个 namespace + 各自的 ResourceQuota,避免互相影响。
  5. Guaranteed 不是银弹:只有对稳定性要求极高的核心组件才需要 Guaranteed。大部分服务用 Burstable 即可。

小结#

资源配置是 Kubernetes 运维中最基础也最容易被忽视的一环。Request 决定调度和 QoS,Limit 决定运行时天花板,两者缺一不可。QoS 的三级分类(Guaranteed > Burstable > BestEffort)直接影响节点压力下的驱逐顺序。LimitRange 和 ResourceQuota 分别从"个体"和"整体"两个维度做资源治理,配合使用才能真正管住集群资源。

多环境资源规划是工程实践中最常踩坑的领域——QA 紧凑省钱、预发中间态验证、生产保守留余量,三套策略对应三套 values 文件。记住:不设资源的 Pod 在生产环境就是定时炸弹,三环境用同一套配置是更大的定时炸弹