3、资源配额(ResourceQuota)基础:Kubernetes ResourceQuota 对象定义、作用域、常用字段

在多租户或团队共享集群的场景中,资源配额(ResourceQuota)是防止“资源挤兑”的第一道防线。它通过限制命名空间(Namespace)级别的聚合资源用量,确保单个团队不会耗尽集群的全部 CPU 或内存,从而保障其他工作负载的稳定性。本章将深入解析 ResourceQuota 的对象定义、作用域机制以及核心字段。

3.1 ResourceQuota 对象定义与核心概念

ResourceQuota 是一个 Kubernetes 原生 API 对象,作用于特定的命名空间。它定义了一组硬性限制(Hard Limits),用于约束该命名空间内所有 Pod 和容器的资源请求(Requests)与限制(Limits)的总和。

核心原则: ResourceQuota 是“聚合约束”,而非“单个 Pod 约束”。它不限制单个 Pod 的资源大小,而是限制命名空间内所有 Pod 的资源总和。若需限制单个 Pod,应使用 LimitRange。

以下是一个标准的 ResourceQuota YAML 定义示例:

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"
    requests.nvidia.com/gpu: "1"
    persistentvolumeclaims: "10"
    pods: "20"
    configmaps: "10"
    services: "5"

3.2 资源配额作用域(Scope)

ResourceQuota 支持通过 scopes 字段对资源进行更精细的划分。作用域决定了配额是应用于所有 Pod,还是仅应用于特定 QoS 类别的 Pod。这是实现资源分层和优先级保障的关键机制。

作用域(Scope) 匹配条件 典型用途
BestEffort Pod 未设置任何 requests 或 limits 限制低优先级、可被驱逐的“尽力而为”型任务
NotBestEffort Pod 设置了至少一个 requests 或 limits 保障有资源声明的 Pod 的配额
Terminating Pod 设置了 activeDeadlineSeconds 限制批处理或定时任务的总资源
NotTerminating Pod 未设置 activeDeadlineSeconds 限制长期运行的服务(Deployment/StatefulSet)
PriorityClass Pod 关联了指定的 PriorityClass 名称 按优先级等级分配不同的资源池
实践建议: 在 GitOps 交付中,建议为每个命名空间创建两个 ResourceQuota:一个用于 NotTerminating(长期服务),另一个用于 Terminating(批处理任务),以实现资源池的物理隔离。

3.3 常用字段详解

ResourceQuota 的 spec.hard 字段支持三类资源:计算资源、存储资源和对象计数资源。以下是 GitOps 交付中最常用的字段清单:

3.3.1 计算资源(Compute Resources)

  • requests.cpu:所有非 BestEffort Pod 的 CPU 请求总和上限(单位:核心数或 millicores)。
  • requests.memory:所有非 BestEffort Pod 的内存请求总和上限(单位:字节、Ki、Mi、Gi)。
  • limits.cpu:所有非 BestEffort Pod 的 CPU 限制总和上限。
  • limits.memory:所有非 BestEffort Pod 的内存限制总和上限。
  • requests.nvidia.com/gpu:GPU 资源请求总和上限(适用于 AI/ML 工作负载)。

3.3.2 存储资源(Storage Resources)

  • requests.storage:所有 PVC 的存储容量请求总和上限。
  • persistentvolumeclaims:命名空间内允许的 PVC 总数上限。
  • storage-class-name.storageclass.storage.k8s.io/requests.storage:针对特定 StorageClass 的存储容量上限。

3.3.3 对象计数资源(Object Count Quotas)

  • pods:命名空间内允许的 Pod 总数上限。
  • services:Service 对象总数上限。
  • configmaps:ConfigMap 对象总数上限。
  • secrets:Secret 对象总数上限。
  • replicationcontrollers:ReplicationController 对象总数上限。

3.4 ResourceQuota 作用域与资源分层 SVG 图

下图展示了不同作用域如何将命名空间内的 Pod 划分为独立的资源池,每个池子受不同的 ResourceQuota 约束:

ResourceQuota 作用域分层模型 命名空间:team-alpha 长期服务池 Scope: NotTerminating Deployment A StatefulSet B Service C Deployment D 配额: requests.cpu=4, requests.memory=8Gi 批处理任务池 Scope: Terminating Job E CronJob F Job G CronJob H 配额: requests.cpu=2, requests.memory=4Gi

3.5 配额冲突与准入控制

当 ResourceQuota 被创建后,Kubernetes 的准入控制器(ResourceQuota Admission Controller)会在 Pod 创建或更新时进行校验。如果命名空间内的资源总和已超过配额上限,新的 Pod 创建请求将被拒绝,并返回 403 Forbidden 错误。

常见陷阱: 如果命名空间内存在未设置 requests 和 limits 的 Pod(BestEffort),而 ResourceQuota 中配置了 requests.cpu 或 limits.memory,这些 Pod 将无法创建。因为 ResourceQuota 要求所有非 BestEffort Pod 必须显式声明资源。解决方案是配合 LimitRange 为未设置资源的 Pod 注入默认值。

3.6 资源配额与 LimitRange 的协同关系

ResourceQuota 和 LimitRange 是 Kubernetes 资源管理的“双保险”。下表对比了二者的核心差异:

特性 ResourceQuota LimitRange
作用范围 命名空间级别(聚合约束) Pod/容器级别(单个约束)
主要功能 限制资源总量上限 设置单个 Pod 的资源最小/最大值及默认值
触发时机 Pod 创建时校验总量 Pod 创建时注入默认值或校验范围
典型场景 防止团队资源滥用 确保每个 Pod 有合理的资源声明
依赖关系 建议与 LimitRange 配合使用 可为 ResourceQuota 提供默认值支撑

3.7 在 GitOps 中声明 ResourceQuota

在 GitOps 工作流中,ResourceQuota 应作为应用交付的一部分,与 Namespace 和 LimitRange 一同存储在 Git 仓库中。推荐使用 Kustomize 的 resources 字段或 Helm 的模板机制进行声明式管理。

以下是一个 Kustomize 示例,展示如何将 ResourceQuota 集成到应用基线中:

# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: team-alpha
resources:
  - namespace.yaml
  - resourcequota.yaml
  - limitrange.yaml
  - deployment.yaml
  - service.yaml
GitOps 最佳实践: 将 ResourceQuota 与 LimitRange 放在同一个 Kustomize 的 base/ 目录下,作为“命名空间基线”的一部分。不同环境(dev/staging/prod)可以通过 overlay 调整配额数值,而无需修改底层资源定义。