3、ResourceQuota 对象详解:API 定义、作用域、资源类型与限制机制
ResourceQuota 是 Kubernetes 内置的准入控制与容量治理原语,它为命名空间级别的资源消耗设定硬性边界。对于 Operator 开发者而言,理解 ResourceQuota 的完整语义是避免“配额拒绝导致 Operator 失控”的前提。本章从 API 定义、作用域、资源类型、硬限制与软限制四个维度展开,并给出 Operator 场景下的典型配置模板。
3.1 ResourceQuota 的 API 定义
ResourceQuota 属于 v1 核心 API 组,其完整结构如下:
apiVersion: v1
kind: ResourceQuota
metadata:
name: operator-quota
namespace: operator-system
spec:
hard:
requests.cpu: "4"
requests.memory: "8Gi"
limits.cpu: "8"
limits.memory: "16Gi"
persistentvolumeclaims: "5"
pods: "20"
count/deployments.apps: "3"
count/statefulsets.apps: "2"
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values:
- system-cluster-critical
| 字段 | 类型 | 说明 |
|---|---|---|
spec.hard |
map[string]Quantity | 资源硬限制键值对,超过即拒绝创建/更新 |
spec.scopes |
[]ResourceQuotaScope | 按资源状态(Terminating/NotTerminating/BestEffort/NotBestEffort)过滤配额 |
spec.scopeSelector |
ScopeSelector | 基于 PriorityClass 等更精细的匹配规则(v1.12+) |
Operator 开发提示: 在 Operator 的 RBAC 清单中必须包含对 ResourceQuota 的
get、list、watch 权限,否则控制器无法感知配额状态,可能导致无限重试。
3.2 作用域(Scopes)与 ScopeSelector
作用域决定了 ResourceQuota 生效的资源子集。Kubernetes 内置以下标准作用域:
| 作用域名称 | 匹配条件 | Operator 典型场景 |
|---|---|---|
Terminating |
spec.activeDeadlineSeconds >= 0 |
批处理任务 Pod 的配额隔离 |
NotTerminating |
spec.activeDeadlineSeconds 未设置 |
Operator 管理的常驻 Pod |
BestEffort |
未设置 requests/limits 的 Pod | 低优先级调试 Pod |
NotBestEffort |
至少设置了 requests 或 limits | Operator 生产工作负载 |
PriorityClass |
通过 scopeSelector 匹配 |
区分控制面与数据面配额 |
常见陷阱: 多个 ResourceQuota 作用于同一命名空间时,Kubernetes 会取所有配额的交集(最严格约束)。Operator 如果同时部署了
BestEffort 和 NotBestEffort 两个配额,务必确认 Pod 的 QoS 分类,否则可能意外触发拒绝。
3.3 支持的资源类型
ResourceQuota 可管理的资源分为三大类:计算资源、存储资源和对象计数资源。Operator 在声明配额时必须覆盖其管理的所有资源类型。
| 类别 | 资源名称 | 说明 | Operator 建议值 |
|---|---|---|---|
| 计算 | requests.cpu |
所有 Pod CPU 请求总和 | 集群节点可分配 CPU 的 60% |
requests.memory |
所有 Pod 内存请求总和 | 集群节点可分配内存的 60% | |
limits.cpu |
所有 Pod CPU 限制总和 | 集群节点可分配 CPU 的 80% | |
limits.memory |
所有 Pod 内存限制总和 | 集群节点可分配内存的 80% | |
| 存储 | requests.storage |
所有 PVC 存储请求总和 | 存储后端总容量的 50% |
persistentvolumeclaims |
PVC 对象数量 | Operator 预期 PVC 数的 1.5 倍 | |
storageclass.storage.k8s.io/requests.storage |
按 StorageClass 细分的存储配额 | 按实际存储类分配 | |
| 对象计数 | count/deployments.apps |
Deployment 数量 | Operator 管理副本数 + 1 |
count/statefulsets.apps |
StatefulSet 数量 | 有状态组件数 + 1 | |
count/jobs.batch |
Job 数量 | 并发任务数上限 | |
count/configmaps |
ConfigMap 数量 | 配置版本数 + 冗余 |
容量规划要点: Operator 的 Reconciler 循环中应定期调用
kubectl get quota -n <ns> -o json 并解析 status.used 字段,当使用率超过 80% 时触发预扩容或告警,避免配额耗尽导致 Operator 工作流中断。
3.4 硬限制(Hard)与软限制(Soft)
ResourceQuota 支持两种限制模式,但 Kubernetes 原生仅实现了硬限制的强制准入控制。软限制需要配合外部策略引擎(如 Gatekeeper)或 Operator 自身逻辑来实现。
| 特性 | 硬限制(Hard) | 软限制(Soft) |
|---|---|---|
| 强制行为 | 超过即拒绝创建/更新,返回 403 Forbidden | 仅记录警告事件,不强制拒绝 |
| API 字段 | spec.hard |
spec.soft(预留,当前版本未实现强制) |
| Operator 影响 | Reconciler 必须处理 AlreadyExists 或 Forbidden 错误 |
可作为 Operator 内部容量水位指标 |
| 典型用途 | 防止资源泄露、保障租户隔离 | 预警告警、优雅降级触发 |
| 实现方式 | kube-apiserver 准入插件 | 需自定义准入 Webhook 或 Operator 逻辑 |
3.5 Operator 场景下的 ResourceQuota 配置模板
以下是一个面向 Operator 生产环境的完整 ResourceQuota 配置,覆盖了计算、存储和对象计数三类资源,并使用了 scopeSelector 区分控制面与数据面 Pod:
apiVersion: v1
kind: ResourceQuota
metadata:
name: operator-production-quota
namespace: my-operator-system
spec:
hard:
# 计算资源
requests.cpu: "8"
requests.memory: "16Gi"
limits.cpu: "16"
limits.memory: "32Gi"
# 存储资源
requests.storage: "100Gi"
persistentvolumeclaims: "10"
# 对象计数
count/deployments.apps: "5"
count/statefulsets.apps: "3"
count/configmaps: "20"
count/secrets: "20"
count/services: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values:
- system-cluster-critical # 控制面 Pod 使用此 PriorityClass
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: operator-data-quota
namespace: my-operator-system
spec:
hard:
requests.cpu: "32"
requests.memory: "64Gi"
limits.cpu: "64"
limits.memory: "128Gi"
persistentvolumeclaims: "50"
scopeSelector:
matchExpressions:
- operator: NotIn
scopeName: PriorityClass
values:
- system-cluster-critical # 数据面 Pod 不包含该 PriorityClass
最佳实践: 在 Operator 的 Helm Chart 中,将 ResourceQuota 的
hard 值暴露为 values.yaml 参数,并设置合理的默认值。同时,在 Operator 的 config/rbac 目录下添加对 ResourceQuota 的 get、list、watch 权限,确保控制器可以读取配额状态。