2. Kubernetes 资源配额基础:ResourceQuota 对象详解、LimitRange 对象详解、命名空间级别的资源管控

2.1 为什么需要命名空间级别的资源管控?

在 Kubernetes 多租户或团队共享集群的场景中,如果没有资源配额约束,单个命名空间或应用可能耗尽集群全部 CPU/内存,导致其他服务不可用。资源管控的核心目标是:公平分配、容量规划、成本核算、稳定性保障。

Kubernetes 提供两个原生 API 对象来实现命名空间级别的资源管控:

  • ResourceQuota:限制命名空间内所有 Pod/Container 的资源总量上限(硬配额)。
  • LimitRange:为命名空间内未显式设置资源请求/限制的 Pod 或 Container 提供默认值,并约束单个 Pod/Container 的资源上下界。
核心原则: ResourceQuota 控制“总量”,LimitRange 控制“个体”。两者配合使用才能构建完整的资源治理体系。

2.2 ResourceQuota 对象详解

2.2.1 核心概念与作用域

ResourceQuota 是一个命名空间级别的 API 对象,定义了一组资源配额约束。当命名空间内的资源使用量超过配额时,Kubernetes API Server 会拒绝后续的创建请求(Pod、PVC、Service 等)。

ResourceQuota 支持三种作用域(Scope):

作用域(Scope) 含义 典型场景
BestEffort 仅统计 QoS 为 BestEffort 的 Pod 限制低优先级批处理任务
NotBestEffort 统计 QoS 非 BestEffort 的 Pod(Burstable/Guaranteed) 保障生产级服务的资源
Terminating / NotTerminating 按 Pod 是否设置 activeDeadlineSeconds 区分 区分长期服务与一次性任务

2.2.2 可配资源类型

ResourceQuota 可以限制以下三类资源:

  • 计算资源:requests.cpu、requests.memory、limits.cpu、limits.memory
  • 存储资源:requests.storage、persistentvolumeclaims、特定 StorageClass 的存储(如 requests.storage/ssd)
  • 对象数量:pods、services、configmaps、secrets、replicationcontrollers、resourcequotas 等

2.2.3 示例:ResourceQuota YAML

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: team-a
spec:
  hard:
    requests.cpu: "4"
    requests.memory: "8Gi"
    limits.cpu: "8"
    limits.memory: "16Gi"
    pods: "20"
    persistentvolumeclaims: "5"
    requests.storage: "100Gi"
关键行为: 当命名空间内所有 Pod 的 requests.cpu 总和达到 4 核时,后续任何 Pod 创建请求都会被拒绝,直到有 Pod 被删除释放资源。

2.2.4 配额评估与准入控制

ResourceQuota 的评估发生在 API Server 的准入控制阶段(Admission Control)。每次创建/更新 Pod 时,API Server 会计算当前命名空间内所有同类资源的累计使用量,加上新请求的资源量,与配额上限比较。若超出则返回 403 Forbidden。

使用 kubectl describe resourcequota compute-quota -n team-a 可以查看当前使用量与配额上限的对比:

Name:            compute-quota
Namespace:       team-a
Resource         Used  Hard
--------         ----  ----
limits.cpu       3     8
limits.memory    6Gi   16Gi
pods             12    20
requests.cpu     2     4
requests.memory  4Gi   8Gi

2.3 LimitRange 对象详解

2.3.1 为什么需要 LimitRange?

ResourceQuota 只限制总量,但无法约束单个 Pod/Container 的资源规格。如果某个团队创建了一个请求 4 核 CPU 的 Pod,而配额总量只有 4 核,其他 Pod 将无法调度。LimitRange 解决了以下问题:

  • 为未设置资源请求/限制的 Pod 提供默认值(Default)。
  • 限制单个 Container 或 Pod 的资源上下界(Min/Max)。
  • 约束 PVC 的存储请求范围。

2.3.2 LimitRange 的四种限制类型

类型(Type) 作用对象 可配字段
Container Pod 内的每个 Container Min, Max, Default, DefaultRequest, MaxLimitRequestRatio
Pod Pod 级别(所有 Container 总和) Min, Max
PersistentVolumeClaim PVC 的存储请求 Min, Max

2.3.3 示例:LimitRange YAML

apiVersion: v1
kind: LimitRange
metadata:
  name: container-limits
  namespace: team-a
spec:
  limits:
  - type: Container
    max:
      cpu: "2"
      memory: "4Gi"
    min:
      cpu: "100m"
      memory: "128Mi"
    default:
      cpu: "500m"
      memory: "512Mi"
    defaultRequest:
      cpu: "200m"
      memory: "256Mi"
    maxLimitRequestRatio:
      cpu: "4"
注意: maxLimitRequestRatio 用于限制 limits 与 requests 的比例。例如 ratio=4 表示 limits.cpu / requests.cpu ≤ 4,防止过度超卖。

2.3.4 LimitRange 的准入控制行为

当 Pod 创建时,LimitRange 的准入控制器会按以下顺序处理:

  1. 如果 Container 未设置 resources.requests,则使用 defaultRequest。
  2. 如果 Container 未设置 resources.limits,则使用 default。
  3. 如果 Container 设置的 requests 或 limits 超出 min/max 范围,则拒绝创建。
  4. 如果 limits/requests 比例超过 maxLimitRequestRatio,则拒绝创建。

2.4 ResourceQuota 与 LimitRange 的协同关系

下图展示了在命名空间内,ResourceQuota 与 LimitRange 如何协同工作:

ResourceQuota 与 LimitRange 协同架构 命名空间资源管控协同架构 命名空间 team-a ResourceQuota 总量上限:CPU 4核 / 内存 8Gi Pod 上限:20 个 LimitRange 默认值:CPU 500m / 内存 512Mi 范围:100m~2 CPU / 128Mi~4Gi Pod A CPU: 1 / Mem: 2Gi Pod B CPU: 0.5 / Mem: 1Gi Pod C CPU: 0.5 / Mem: 1Gi LimitRange 确保每个 Pod 规格合规 → ResourceQuota 确保总量不超限 两者在 Admission Control 阶段依次校验

2.5 最佳实践与避坑指南

生产级配置建议:
  • 始终为每个命名空间同时配置 ResourceQuota 和 LimitRange,缺一不可。
  • ResourceQuota 的 requests 应设置为集群容量的 60%~80%,预留缓冲。
  • LimitRange 的 default 和 defaultRequest 应匹配团队典型工作负载。
  • 使用 kubectl describe quota 和 kubectl describe limitrange 定期审计。
常见陷阱:
  • 只配 ResourceQuota 不配 LimitRange → 未设置资源限制的 Pod 可能被拒绝(因为配额无法计算)。
  • LimitRange 的 min 设置过高 → 小规格 Pod 无法创建。
  • ResourceQuota 的 limits 与 requests 比例失衡 → 导致资源碎片。
  • 忘记为 StorageClass 设置配额 → 存储资源可能被单个 PVC 耗尽。

2.6 本章小结