2、资源配额(ResourceQuota)基础:概念、作用域与资源类型

ResourceQuota 是 Kubernetes 集群管理员用来限制命名空间(Namespace)级别资源消耗的核心策略对象。它通过声明式配置,为每个命名空间设定资源上限,防止单个租户或应用团队过度占用集群资源,保障多租户环境下的资源公平性与集群稳定性。

2.1 ResourceQuota 核心概念

ResourceQuota 本质上是一个准入控制机制。当用户尝试在命名空间中创建或更新 Pod、Service、PersistentVolumeClaim 等对象时,Kubernetes API Server 会调用配额插件,检查当前命名空间已消耗的资源量加上新请求的资源量是否超过配额上限。如果超出,请求将被拒绝并返回错误信息。

关键特性:
  • 命名空间级作用域:每个 ResourceQuota 对象绑定到一个特定的命名空间,无法跨命名空间生效。
  • 累加式计数:配额跟踪的是命名空间内所有对象的资源请求(requests)和限制(limits)的累加值,而非瞬时使用量。
  • 硬性限制:默认情况下,ResourceQuota 是硬配额(Hard),超出即拒绝。支持通过 spec.scopeSelector 实现软配额(BestEffort 或 NotBestEffort)。
  • 动态更新:配额可以在运行时修改,修改后立即生效,但不会影响已存在的对象。
ResourceQuota 准入控制流程 用户请求 创建 Pod / PVC API Server 准入控制器 ResourceQuota 检查命名空间 资源累加值 通过 拒绝 流程说明: 1. 用户向 API Server 发送创建 Pod 或 PVC 的请求。 2. API Server 的准入控制器拦截请求,触发 ResourceQuota 插件。 3. 配额插件查询命名空间内已存在的资源累加值(requests + limits)。 4. 将新请求的资源量加入累加值,与配额上限(Hard)比较。 5. 若未超出上限 → 请求通过,对象创建成功。 6. 若超出上限 → 请求被拒绝,返回 403 Forbidden 错误。 7. 配额更新后立即生效,但不会影响已存在的对象。 注意:配额检查是同步的,发生在对象持久化之前。

2.2 作用域(Scope)

ResourceQuota 支持通过作用域(Scope)对配额的应用范围进行精细化控制。作用域决定了配额规则适用于哪些类型的 Pod 或对象。Kubernetes 定义了以下标准作用域:

作用域名称 描述 适用场景
BestEffort 仅匹配 QoS 类别为 BestEffort 的 Pod(未设置 requests 和 limits) 限制低优先级、突发性任务的资源占用
NotBestEffort 匹配 QoS 类别为 Burstable 或 Guaranteed 的 Pod 保障有资源预留的生产级工作负载
Terminating 匹配设置了 activeDeadlineSeconds 的 Pod 限制批处理任务、CI/CD 作业
NotTerminating 匹配未设置 activeDeadlineSeconds 的 Pod 限制长期运行的服务
PriorityClass 通过 scopeSelector 匹配指定 PriorityClass 的 Pod 按优先级层级分配资源配额
CrossNamespacePodAffinity 匹配使用了跨命名空间 Pod 亲和性的 Pod 控制跨命名空间调度的影响范围
最佳实践: 建议为每个命名空间创建两个 ResourceQuota 对象:一个使用 NotBestEffort 作用域限制生产级 Pod 的资源,另一个使用 BestEffort 作用域限制临时任务的资源。这样可以避免 BestEffort Pod 抢占 NotBestEffort Pod 的配额。

2.3 资源类型详解

ResourceQuota 支持对四类资源进行配额限制:计算资源(CPU/内存)、存储资源、对象数量以及扩展资源。每种资源类型都有对应的配额键(Key)和计数方式。

2.3.1 计算资源(CPU / 内存)

计算资源配额通过 requests 和 limits 两个维度进行控制。Kubernetes 会分别累加命名空间内所有 Pod 容器的 requests 和 limits 值。

配额键 描述 单位 示例值
requests.cpu 所有 Pod 的 CPU 请求总和上限 核心数(m 或整数) 10、5000m
requests.memory 所有 Pod 的内存请求总和上限 字节(Ei/Pi/Ti/Gi/Mi/Ki) 20Gi、512Mi
limits.cpu 所有 Pod 的 CPU 限制总和上限 核心数(m 或整数) 20、10000m
limits.memory 所有 Pod 的内存限制总和上限 字节(Ei/Pi/Ti/Gi/Mi/Ki) 40Gi、1Ti

2.3.2 存储资源

存储资源配额包括持久卷声明(PVC)的存储请求总量以及特定存储类的存储上限。

配额键 描述 单位 示例值
requests.storage 所有 PVC 的存储请求总和上限 字节 100Gi
persistentvolumeclaims PVC 对象数量上限 整数 50
requests.storage/<storage-class-name> 指定 StorageClass 的 PVC 存储请求总和上限 字节 50Gi
persistentvolumeclaims/<storage-class-name> 指定 StorageClass 的 PVC 对象数量上限 整数 20

2.3.3 对象数量

对象数量配额限制命名空间内可创建的 Kubernetes 资源对象个数。这有助于防止资源对象泛滥导致 etcd 压力过大或控制器性能下降。

配额键 描述 示例值
pods Pod 对象数量上限 100
services Service 对象数量上限 50
services.loadbalancers LoadBalancer 类型 Service 数量上限 10
services.nodeports NodePort 类型 Service 数量上限 20
configmaps ConfigMap 对象数量上限 200
secrets Secret 对象数量上限 200
replicationcontrollers ReplicationController 对象数量上限 50
resourcequotas ResourceQuota 对象数量上限 10

2.3.4 扩展资源

扩展资源(Extended Resources)是用户自定义的非 Kubernetes 原生资源,例如 GPU、FPGA、NVMe 磁盘等。ResourceQuota 同样支持对扩展资源进行配额限制。

apiVersion: v1
kind: ResourceQuota
metadata:
  name: gpu-quota
  namespace: ai-team
spec:
  hard:
    requests.nvidia.com/gpu: 8
    limits.nvidia.com/gpu: 16
    pods: 50
    requests.memory: 100Gi
    limits.memory: 200Gi
注意: 扩展资源的配额键必须与节点上报告的设备名称完全一致(包括域名前缀)。如果节点使用 nvidia.com/gpu,则配额键必须写 requests.nvidia.com/gpu,不能简写为 gpu。

2.4 完整 ResourceQuota 示例

以下是一个生产环境推荐的 ResourceQuota 配置,同时覆盖计算资源、存储资源和对象数量:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: production-quota
  namespace: production
spec:
  hard:
    # 计算资源
    requests.cpu: 20
    requests.memory: 80Gi
    limits.cpu: 40
    limits.memory: 160Gi
    # 存储资源
    requests.storage: 500Gi
    persistentvolumeclaims: 30
    requests.storage/fast-ssd: 200Gi
    persistentvolumeclaims/fast-ssd: 10
    # 对象数量
    pods: 100
    services: 20
    configmaps: 100
    secrets: 100
    # 扩展资源
    requests.nvidia.com/gpu: 4

2.5 配额与 LimitRange 的协同关系

ResourceQuota 和 LimitRange 是 Kubernetes 资源治理的两大支柱,但职责不同:

特性 ResourceQuota LimitRange
作用范围 命名空间级别(所有 Pod 累加) 单个 Pod / 容器级别
主要功能 限制资源总量上限 设置单个容器的资源默认值、最小/最大值
检查时机 创建/更新对象时(准入控制) 创建/更新 Pod 时(准入控制)
典型场景 多租户资源隔离、成本控制 防止单个容器资源过大或过小
是否必须配合 建议与 LimitRange 一起使用 建议与 ResourceQuota 一起使用
协同建议: 先通过 LimitRange 为每个容器设置默认的 requests 和 limits,再通过 ResourceQuota 限制命名空间的总资源上限。这样可以避免因容器未设置资源限制而导致配额计算不准确的问题。
ResourceQuota 与 LimitRange 协同架构 Namespace: production LimitRange 默认 requests/limits ResourceQuota 总量上限控制 Pod A (1C/2G) Pod B (2C/4G) Pod C (0.5C/1G) Pod D (1C/2G) LimitRange 为每个 Pod 设置默认资源值 → ResourceQuota 累加所有 Pod 的资源总量 → 超出配额则拒绝新 Pod 创建

2.6 配额监控与调试

管理员可以通过以下命令查看命名空间的当前配额使用情况:

# 查看命名空间的配额定义
kubectl get resourcequota -n production

# 查看配额使用详情(Used 列显示当前消耗)
kubectl describe resourcequota production-quota -n production

# 输出示例:
# Name:            production-quota
# Namespace:       production
# Resource         Used  Hard
# --------         ---   ---
# requests.cpu     12    20
# requests.memory  48Gi  80Gi
# limits.cpu       24    40
# limits.memory    96Gi  160Gi
# pods             45    100
# persistentvolumeclaims  12  30
调试技巧:
  • 当 Pod 创建失败并返回 403 Forbidden 时,使用 kubectl describe quota 检查是否达到配额上限。
  • 使用 kubectl get events -n <namespace> 查看被配额拒绝的详细事件。
  • 对于存储配额,注意 PVC 的 requests.storage 是累加所有 PVC 的 spec.resources.requests.storage 值,而非实际使用量。
  • 如果配额更新后 Pod 仍然创建失败,检查是否同时存在多个 ResourceQuota 对象,它们的限制会取并集(最严格的限制生效)。