资源配额基础: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 创建时的准入控制流程:
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 循环频繁触发。