2. Kubernetes Resource Quota 基础:ResourceQuota 对象定义、作用域、与 LimitRange 的区别

在云原生成本分摊模型中,Resource Quota 是 Kubernetes 内置的准入控制机制,用于限制命名空间(Namespace)级别的资源消耗总量。它是实现多租户资源隔离、防止资源争抢、以及进行成本核算与分摊的基石。本章将深入解析 ResourceQuota 的对象定义、作用域,并对比其与 LimitRange 的核心差异。

2.1 ResourceQuota 对象定义

ResourceQuota 是一个 Kubernetes API 对象,通过 YAML 清单定义。它作用于一个特定的 Namespace,对该 Namespace 内所有 Pod 的聚合资源消耗设置硬性上限。

以下是一个典型的 ResourceQuota 定义示例,它限制了计算资源(CPU/内存)和存储资源(PVC 请求),以及核心对象数量(Pod、Service、ConfigMap 等):

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: team-alpha
spec:
  hard:
    requests.cpu: "4"
    requests.memory: "8Gi"
    limits.cpu: "8"
    limits.memory: "16Gi"
    persistentvolumeclaims: "10"
    requests.storage: "50Gi"
    pods: "20"
    services: "10"
    configmaps: "15"
    secrets: "15"
关键字段说明:
  • spec.hard:定义资源配额的上限值,是一个键值对映射。
  • requests.cpu / requests.memory:所有 Pod 的 requests 总和上限。
  • limits.cpu / limits.memory:所有 Pod 的 limits 总和上限。
  • pods / services / configmaps:限制该 Namespace 内可创建的对象数量。

2.2 ResourceQuota 作用域(Scope)

ResourceQuota 支持通过 spec.scopeSelector 或 spec.scopes 字段,将配额限制应用于特定类别的 Pod。作用域允许管理员对资源消耗进行更精细的控制,例如区分“尽力而为”和“有 QoS 保障”的工作负载。

常见的作用域包括:

作用域名称 匹配条件 典型用途
BestEffort Pod 未设置 requests 和 limits 限制低优先级、可被驱逐的批处理任务
NotBestEffort Pod 设置了 requests 或 limits 保障生产级服务的资源上限
Terminating Pod 设置了 activeDeadlineSeconds 限制有运行时间上限的 Job 或 CronJob
NotTerminating Pod 未设置 activeDeadlineSeconds 限制常驻服务(Deployment、StatefulSet)
PriorityClass 通过 scopeSelector 匹配特定 PriorityClass 按优先级等级分配资源池

以下示例展示了如何创建一个仅对 NotBestEffort Pod 生效的 ResourceQuota:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-not-besteffort
  namespace: team-alpha
spec:
  hard:
    requests.cpu: "6"
    requests.memory: "12Gi"
  scopes:
    - NotBestEffort
作用域使用注意: 当使用 scopes 字段时,ResourceQuota 仅统计匹配该作用域的 Pod 资源。如果 Namespace 内同时存在 BestEffort 和 NotBestEffort Pod,你需要创建两个独立的 ResourceQuota 对象来分别管理它们。

2.3 ResourceQuota 与 LimitRange 的区别

ResourceQuota 和 LimitRange 都是 Kubernetes 中用于资源治理的准入控制器,但它们的职责和粒度完全不同。理解两者的区别是构建成本分摊模型的前提。

以下 SVG 图直观展示了两者的核心差异:

ResourceQuota vs LimitRange 核心差异 ResourceQuota (命名空间级别) 限制所有 Pod 的 聚合 资源上限 示例:CPU 总量 ≤ 8 核 作用:防止 Namespace 资源滥用 LimitRange (Pod / 容器级别) 限制单个 Pod / 容器的资源范围 示例:每个容器 CPU 1~4 核 作用:为未设置资源的 Pod 注入默认值 两者协同工作:LimitRange 定义单个 Pod 的边界,ResourceQuota 定义 Namespace 的总边界

下表从多个维度详细对比了 ResourceQuota 与 LimitRange:

对比维度 ResourceQuota LimitRange
作用粒度 Namespace 级别(聚合统计) Pod / 容器级别(单个实例)
核心功能 设置资源消耗的 硬上限 设置资源请求/限制的 最小/最大范围 及默认值
触发时机 Pod 创建时检查 Namespace 总量是否超限 Pod 创建时校验或注入单个容器的资源值
典型场景 多租户成本分摊、资源容量规划 防止单个 Pod 资源过大或过小、为 Legacy 应用注入默认值
是否影响已有 Pod 否(仅限制新创建的对象) 否(仅对新创建的 Pod 生效)
与成本分摊的关系 直接提供 Namespace 资源消耗上限,用于计算最大可分摊成本 间接影响成本分摊的准确性(通过约束单个 Pod 的资源规格)

2.4 实战中的协同使用建议

在云原生成本分摊模型中,ResourceQuota 和 LimitRange 通常配合使用,形成“双层资源治理”策略:

  1. 第一层:LimitRange —— 为每个 Namespace 设置默认的 requests 和 limits,确保所有 Pod 都有明确的资源声明,避免“空跑”Pod 导致成本黑洞。
  2. 第二层:ResourceQuota —— 设置 Namespace 的资源总量上限,防止某个团队或项目过度消耗集群资源,保障成本分摊的公平性。
成本分摊最佳实践: 在启用 ResourceQuota 的 Namespace 中,务必同时配置 LimitRange。因为如果 Pod 未设置 limits,ResourceQuota 的 limits.cpu 和 limits.memory 将无法生效,导致配额形同虚设。LimitRange 可以自动为未设置资源的 Pod 注入默认值,确保 ResourceQuota 的统计完整性。

以下 SVG 图展示了 ResourceQuota 与 LimitRange 在 Pod 创建流程中的协同工作顺序:

Pod 创建时的资源准入控制流程 1. 用户提交 Pod 2. LimitRange 准入 校验/注入默认值 3. ResourceQuota 准入 检查 Namespace 总量 4. Pod 创建成功 准入失败 → 拒绝创建 流程说明:LimitRange 先执行(注入默认值),ResourceQuota 后执行(总量校验) 任一阶段失败,Pod 创建请求将被 API Server 拒绝