3. Kubernetes 资源配额(ResourceQuota)详解:定义、作用域、常用字段
ResourceQuota 是 Kubernetes 内置的准入控制机制,用于限制命名空间(Namespace)级别的聚合资源消耗。它通过一组硬性限制(Hard Limits)来约束命名空间内所有 Pod、PVC 等对象的总资源使用量,防止单个团队或应用“抢占”集群的全部资源,是实现多租户资源隔离与成本控制的核心工具。
3.1 核心定义与工作原理
ResourceQuota 本质上是一个 API 对象(v1/ResourceQuota),由 kube-apiserver 的准入控制器 ResourceQuota 在对象创建/更新时强制执行。其工作流程如下:
- 定义配额:管理员在命名空间内创建 ResourceQuota 对象,声明 CPU、内存、存储、对象数量等上限。
- 请求校验:当用户在该命名空间创建 Pod、PVC、Service 等资源时,准入控制器计算当前命名空间已使用量 + 新请求量。
- 准入/拒绝:若总和超过配额上限,请求被拒绝并返回错误信息;否则允许创建,并更新配额状态。
- 状态监控:ResourceQuota 的
status字段实时反映当前使用量,可通过kubectl describe quota查看。
关键原则:ResourceQuota 是“尽力而为”的硬限制,不预留资源。它只阻止超配创建,不驱逐已运行的 Pod。若配额被调低,已存在的超配 Pod 不会被终止,但新 Pod 无法创建。
3.2 作用域(Scope)与匹配规则
ResourceQuota 支持通过 scopes 字段限定配额生效的范围,实现更精细的资源控制。作用域决定了哪些对象会被配额统计。
| 作用域名称 | 匹配对象 | 典型场景 |
|---|---|---|
BestEffort |
QoS 等级为 BestEffort 的 Pod(未设置 requests/limits) | 限制“尽力而为”类 Pod 的总数或 CPU 使用 |
NotBestEffort |
QoS 等级非 BestEffort 的 Pod(设置了 requests 或 limits) | 保障有 QoS 保证的 Pod 的资源配额 |
Terminating |
设置了 activeDeadlineSeconds 的 Pod |
限制批处理作业(Job)的聚合资源 |
NotTerminating |
未设置 activeDeadlineSeconds 的 Pod |
限制长期运行服务(Deployment)的资源 |
PriorityClass |
指定了特定 PriorityClass 的 Pod | 按优先级隔离资源,高优任务独占配额 |
CrossNamespacePodAffinity |
使用了跨命名空间 Pod 亲和性的 Pod | 控制跨命名空间调度的影响范围 |
实践建议:在集群升级场景中,建议为
NotTerminating 和 BestEffort 分别设置配额,避免升级过程中临时 Pod 挤占关键服务资源。
3.3 常用字段与配置示例
ResourceQuota 的 spec.hard 字段支持三类资源维度:计算资源、存储资源和对象数量。以下是一个完整的生产级配置示例:
apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: team-alpha
spec:
hard:
# 计算资源(单位:m 表示毫核,Mi 表示兆字节)
requests.cpu: "10" # 所有 Pod 的 CPU 请求总和不超过 10 核
requests.memory: "20Gi" # 所有 Pod 的内存请求总和不超过 20 GiB
limits.cpu: "20" # 所有 Pod 的 CPU 限制总和不超过 20 核
limits.memory: "40Gi" # 所有 Pod 的内存限制总和不超过 40 GiB
# 存储资源
requests.storage: "500Gi" # 所有 PVC 的存储请求总和不超过 500 GiB
persistentvolumeclaims: "10" # PVC 对象总数不超过 10 个
# 对象数量
pods: "50" # 活跃 Pod 总数不超过 50 个
services: "10" # Service 对象总数不超过 10 个
configmaps: "20" # ConfigMap 对象总数不超过 20 个
secrets: "20" # Secret 对象总数不超过 20 个
replicationcontrollers: "10" # RC 对象总数不超过 10 个
services.nodeports: "5" # NodePort 类型 Service 不超过 5 个
services.loadbalancers: "2" # LoadBalancer 类型 Service 不超过 2 个
3.4 字段分类详解
常用字段按资源类型分为三大类,每类字段的命名规则和单位如下:
| 类别 | 字段前缀/名称 | 单位 | 说明 |
|---|---|---|---|
| 计算资源 | requests.cpu |
核(整数或小数,如 0.5) | 所有 Pod 的 CPU 请求总和上限 |
requests.memory |
字节(Ki/Mi/Gi) | 所有 Pod 的内存请求总和上限 | |
limits.cpu |
核 | 所有 Pod 的 CPU 限制总和上限 | |
limits.memory |
字节 | 所有 Pod 的内存限制总和上限 | |
| 存储资源 | requests.storage |
字节 | 所有 PVC 的存储请求总和上限 |
persistentvolumeclaims |
整数 | PVC 对象数量上限 | |
<storage-class>.storageclass.storage.k8s.io/requests.storage |
字节 | 按 StorageClass 细分的存储配额 | |
| 对象数量 | pods |
整数 | 活跃 Pod 数量上限(含 Running、Pending 等) |
services |
整数 | Service 对象数量上限 | |
configmaps |
整数 | ConfigMap 对象数量上限 | |
secrets |
整数 | Secret 对象数量上限 | |
services.nodeports |
整数 | NodePort 类型 Service 数量上限 | |
services.loadbalancers |
整数 | LoadBalancer 类型 Service 数量上限 |
3.5 多配额对象与作用域组合
一个命名空间可以创建多个 ResourceQuota 对象,每个对象可以指定不同的作用域。Kubernetes 会累加所有匹配的配额限制,取最严格的约束生效。
3.6 常见陷阱与避坑指南
- 未设置 requests/limits 导致配额失效:若 Pod 未设置
requests字段,则requests.cpu和requests.memory配额不会统计该 Pod。建议配合 LimitRange 设置默认值。 - 配额与 LimitRange 冲突:LimitRange 设置单个 Pod 的默认 requests/limits,ResourceQuota 设置总和上限。两者需协同规划,避免 LimitRange 默认值过大导致配额迅速耗尽。
- 存储配额不限制临时存储:
requests.storage仅统计 PVC,不统计 emptyDir 或 hostPath 等临时存储。若需限制临时存储,需使用ephemeral-storage字段。 - 对象配额不包含已删除对象:ResourceQuota 仅统计当前活跃对象。已删除的 Pod 或 PVC 不会占用配额,但处于 Terminating 状态的 Pod 仍会计数。
- 跨命名空间配额无法直接实现:ResourceQuota 是命名空间级别的,无法跨命名空间聚合。若需全局配额,需借助 Kyverno 等策略引擎或外部调度器。
升级场景特别提醒:在集群升级过程中,若同时运行旧版本和新版本 Pod(例如通过滚动更新),ResourceQuota 的
pods 配额可能成为瓶颈。建议在升级前临时调高 pods 配额,或使用 Kyverno 策略自动检测并调整。