资源配额基础:Kubernetes ResourceQuota 概念、作用域、默认配额、配额范围

在 Operator 开发中,控制器生成的 Pod、PVC、Service 等资源会持续消耗集群容量。若缺乏配额约束,单个 Operator 或命名空间可能耗尽集群资源,影响其他工作负载。Kubernetes 的 ResourceQuota 正是为命名空间级别提供硬性资源上限的机制,是 Operator 资源配额分配策略的基石。

2.1 ResourceQuota 核心概念

ResourceQuota 是一个 Kubernetes 内置 API 对象,定义在 v1 核心组中。它通过准入控制(Admission Control)在资源创建或更新时进行校验,确保命名空间内所有 Pod、PVC、Service 等对象的资源总和不超过预设的硬限制。

关键特性:
  • 命名空间级别:每个 ResourceQuota 只作用于其所在的命名空间,无法跨命名空间生效。
  • 硬限制(Hard Limit):一旦资源总量达到配额上限,后续创建请求将被拒绝,并返回 403 Forbidden。
  • 累加计算:配额统计的是命名空间内所有符合作用域的资源总和,而非单个资源。
  • 动态更新:修改 ResourceQuota 后,已存在的资源不受影响,但新创建或更新的资源会按新配额校验。

2.2 资源配额作用域(Scope)

ResourceQuota 支持通过 scopes 字段限定配额生效的资源范围,避免对所有资源一刀切。常见作用域如下:

作用域名称 描述 适用场景
BestEffort 仅统计 QoS 等级为 BestEffort 的 Pod(未设置 requests/limits) 限制低优先级、无资源保障的 Pod 数量
NotBestEffort 排除 BestEffort Pod,统计其他 QoS 等级的 Pod 对 Guaranteed/Burstable Pod 单独设限
Terminating 统计设置了 activeDeadlineSeconds 的 Pod 限制有运行时长上限的批处理任务
NotTerminating 统计未设置 activeDeadlineSeconds 的 Pod 限制常驻服务类 Pod
PriorityClass 按 PriorityClass 名称筛选 Pod(需指定 scopeSelector) 对不同优先级的工作负载分别设限
Operator 开发提示:当你的控制器同时管理常驻服务 Pod 和一次性 Job Pod 时,建议使用 NotTerminating 和 Terminating 作用域分别设置配额,避免 Job 突发占用影响核心服务的资源保障。

2.3 默认配额与配额范围

Kubernetes 提供了两个辅助机制来简化配额管理:

2.3.1 LimitRange:默认配额与最小/最大约束

ResourceQuota 只限制总量,不限制单个 Pod 的资源声明。若希望为未显式设置 requests/limits 的 Pod 注入默认值,或限制单个容器的资源上下界,需使用 LimitRange 对象。

apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: operator-ns
spec:
  limits:
  - default:                    # 默认 limits
      cpu: 500m
      memory: 512Mi
    defaultRequest:             # 默认 requests
      cpu: 200m
      memory: 256Mi
    max:                        # 单个容器上限
      cpu: 2
      memory: 2Gi
    min:                        # 单个容器下限
      cpu: 50m
      memory: 64Mi
    type: Container
注意:LimitRange 的默认值仅在 Pod 创建时注入,不会修改已存在的 Pod。若 ResourceQuota 要求所有 Pod 必须设置 requests,而 LimitRange 未配置默认值,则未显式设置 requests 的 Pod 将被拒绝。

2.3.2 配额范围(ScopeSelector)

从 Kubernetes 1.15 开始,ResourceQuota 支持 scopeSelector 字段,允许基于 PriorityClass 等更精细的条件筛选资源。示例如下:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: high-priority-quota
  namespace: operator-ns
spec:
  hard:
    pods: "10"
    requests.cpu: "4"
    requests.memory: "8Gi"
  scopeSelector:
    matchExpressions:
    - operator: In
      scopeName: PriorityClass
      values:
      - high-priority

上述配额仅统计 PriorityClass 为 high-priority 的 Pod,实现按优先级隔离资源池。

2.4 ResourceQuota 完整示例与资源类型

以下是一个典型的 ResourceQuota 配置,涵盖计算资源、存储资源和对象数量:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: operator-quota
  namespace: operator-ns
spec:
  hard:
    # 计算资源
    requests.cpu: "4"
    requests.memory: "8Gi"
    limits.cpu: "8"
    limits.memory: "16Gi"
    # 存储资源
    requests.storage: "100Gi"
    persistentvolumeclaims: "10"
    # 对象数量
    pods: "20"
    services: "10"
    configmaps: "15"
    secrets: "15"
    replicationcontrollers: "5"
    resourcequotas: "1"

ResourceQuota 支持的资源类型可分为三类:

类别 资源键 说明
计算资源 requests.cpu / limits.cpu CPU 请求与限制(单位:m 或整数)
requests.memory / limits.memory 内存请求与限制(单位:Mi、Gi)
requests.ephemeral-storage 临时存储请求
limits.ephemeral-storage 临时存储限制
存储资源 requests.storage 所有 PVC 的存储请求总和
persistentvolumeclaims PVC 对象数量上限
<storage-class-name>.storageclass.storage.k8s.io/requests.storage 按 StorageClass 细分的存储配额
对象数量 pods、services、configmaps 对应 API 对象的最大数量
secrets、replicationcontrollers Secret 和 ReplicationController 数量上限
resourcequotas 命名空间内 ResourceQuota 对象数量(通常为 1)
count/<resource>.<group> 通用计数配额,如 count/deployments.apps
count/<resource>.<group> 支持 CRD 资源计数,如 count/operators.example.com

2.5 ResourceQuota 工作流程与校验机制

下图展示了 ResourceQuota 在 Pod 创建时的准入控制流程:

ResourceQuota 准入控制流程 用户/Operator 提交 Pod API Server 接收请求 ResourceQuota 准入控制器 配额校验:总量 ≤ Hard? 通过 → 创建资源 拒绝 → 403 Forbidden 说明:配额校验在 Mutating Admission Webhook(如 LimitRange 注入)之后执行, 确保 requests/limits 已填充完毕,避免因缺失值导致校验偏差。

2.6 Operator 开发中的配额设计要点

  • 提前声明配额:在 Operator 部署文档中明确要求管理员为命名空间创建 ResourceQuota,或由 Operator 启动时自动创建。
  • 处理配额拒绝错误:控制器应捕获 403 Forbidden 错误,并实现重试机制(如指数退避),等待资源释放或配额调整。
  • 结合 LimitRange 使用:为 Operator 管理的 Pod 设置合理的默认 requests/limits,避免因未设置值导致配额校验失败。
  • 监控配额使用率:通过 kubectl describe quota 或 Prometheus 指标(如 kube_resourcequota)监控配额使用情况,及时预警。
  • 作用域隔离:对于同时管理批处理任务和常驻服务的 Operator,使用 Terminating 和 NotTerminating 作用域分别设限,防止任务突发影响服务稳定性。
实战建议:在 Operator 的 Reconcile 逻辑中,建议将资源创建操作封装为幂等函数,并在失败时检查错误类型。若为 ResourceQuota 拒绝错误,可将该资源加入等待队列,定期重试,而非直接返回错误导致 Reconcile 循环频繁触发。