2. Kubernetes 资源配额基础:ResourceQuota 对象定义、作用域与核心字段
在 Kubernetes 多租户或生产集群中,资源配额(ResourceQuota)是保障集群稳定性、防止资源争抢的核心机制。它通过声明式策略限制命名空间(Namespace)级别的资源消耗总量,确保单个团队或应用不会耗尽集群资源。本章将深入解析 ResourceQuota 的对象定义、作用域以及核心字段的配置语义。
2.1 ResourceQuota 对象定义与作用域
ResourceQuota 是一个 Kubernetes 原生 API 对象,作用于 Namespace 级别。一旦在某个 Namespace 中创建 ResourceQuota,该 Namespace 下的所有 Pod 都必须遵循配额约束,否则创建请求将被 API Server 拒绝。
- 作用域(Scope): 配额可以针对所有 Pod,也可以限定到特定类别(如 BestEffort、NotTerminating、Terminating)。
- 累加性: 配额统计的是 Namespace 内所有 Pod 的资源请求(requests)和限制(limits)的总和。
- 不可覆盖: 如果 Pod 未设置资源请求或限制,而配额要求必须设置,则 Pod 创建失败。
以下是一个典型的 ResourceQuota 定义示例,它限制了 Namespace 内 CPU 和内存的总量,并强制所有 Pod 必须设置资源请求:
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: team-a
spec:
hard:
requests.cpu: "4"
requests.memory: "8Gi"
limits.cpu: "8"
limits.memory: "16Gi"
scopeSelector:
matchExpressions:
- operator: In
scopeName: NotBestEffort
requests 和 limits,避免出现 BestEffort Pod 占用过量资源。使用 scopeSelector 可以精细控制配额生效范围,例如只对非 BestEffort Pod 施加限制。
2.2 核心字段详解
ResourceQuota 的 spec.hard 字段定义了资源上限,支持以下核心资源类型:
| 字段名 | 类型 | 说明 | 示例值 |
|---|---|---|---|
requests.cpu |
字符串 | 所有 Pod 的 CPU 请求总和上限 | "4"(4 核) |
requests.memory |
字符串 | 所有 Pod 的内存请求总和上限 | "8Gi" |
limits.cpu |
字符串 | 所有 Pod 的 CPU 限制总和上限 | "8"(8 核) |
limits.memory |
字符串 | 所有 Pod 的内存限制总和上限 | "16Gi" |
count/pods |
字符串 | Namespace 中允许的 Pod 数量上限 | "100" |
count/services |
字符串 | Namespace 中允许的 Service 数量上限 | "50" |
count/configmaps |
字符串 | Namespace 中允许的 ConfigMap 数量上限 | "20" |
count/secrets |
字符串 | Namespace 中允许的 Secret 数量上限 | "20" |
count/persistentvolumeclaims |
字符串 | Namespace 中允许的 PVC 数量上限 | "10" |
limits.cpu 而不设置 requests.cpu,Kubernetes 会默认将 requests.cpu 视为与 limits.cpu 相等。这可能导致资源预留过高,降低集群利用率。建议始终显式设置 requests 和 limits。
2.3 ResourceQuota 作用域与 ScopeSelector
ResourceQuota 支持通过 scopeSelector 或 scopes 字段将配额限定到特定类别的 Pod。常用作用域包括:
- BestEffort: 匹配未设置资源请求和限制的 Pod(QoS 等级为 BestEffort)。
- NotBestEffort: 匹配设置了资源请求或限制的 Pod(QoS 等级为 Burstable 或 Guaranteed)。
- Terminating: 匹配设置了
activeDeadlineSeconds的 Pod。 - NotTerminating: 匹配未设置
activeDeadlineSeconds的 Pod。
以下示例展示了如何为 BestEffort Pod 单独设置配额,防止其占用过多内存:
apiVersion: v1
kind: ResourceQuota
metadata:
name: best-effort-quota
namespace: team-a
spec:
hard:
requests.memory: "1Gi"
limits.memory: "2Gi"
scopes:
- BestEffort
2.4 ResourceQuota 资源分配与约束流程
下图展示了 ResourceQuota 在 Pod 创建过程中的校验与约束流程:
2.5 多维度配额组合实践
在实际工程中,通常需要组合多个 ResourceQuota 对象来实现精细化的资源管控。以下是一个典型的多维度配额配置示例:
# 1. 全局计算资源配额
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: team-a
spec:
hard:
requests.cpu: "10"
requests.memory: "20Gi"
limits.cpu: "20"
limits.memory: "40Gi"
---
# 2. 对象数量配额
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-quota
namespace: team-a
spec:
hard:
count/pods: "50"
count/services: "10"
count/configmaps: "30"
count/secrets: "30"
count/persistentvolumeclaims: "20"
---
# 3. 存储资源配额
apiVersion: v1
kind: ResourceQuota
metadata:
name: storage-quota
namespace: team-a
spec:
hard:
requests.storage: "500Gi"
persistentvolumeclaims: "20"
- 分层设置: 将计算资源、对象数量和存储资源拆分为独立的 ResourceQuota,便于审计和调整。
- 预留缓冲: 配额上限建议设置为实际需求的 1.2~1.5 倍,避免因突发流量导致 Pod 创建失败。
- 监控告警: 使用
kubectl describe resourcequota或 Prometheus 监控配额使用率,当使用率超过 80% 时触发告警。
2.6 ResourceQuota 与 LimitRange 的协同
ResourceQuota 控制的是 Namespace 级别的资源总量,而 LimitRange 控制的是单个 Pod 或容器的资源默认值及范围。两者协同工作,形成完整的资源管控体系:
| 特性 | ResourceQuota | LimitRange |
|---|---|---|
| 作用范围 | Namespace 级别(总量) | Pod/Container 级别(单个) |
| 核心功能 | 限制资源总和上限 | 设置资源默认值及最小/最大值 |
| 典型场景 | 防止团队过度使用资源 | 确保每个 Pod 有合理的资源基线 |
| 冲突处理 | Pod 创建时校验总量是否超限 | Pod 创建时校验单个值是否在范围内 |
requests.memory: 256Mi 和 limits.memory: 512Mi,再通过 ResourceQuota 限制 Namespace 总内存为 requests.memory: 32Gi。这样既能保证单个容器不会过大,又能控制整体资源消耗。
通过本章的学习,您应掌握 ResourceQuota 的对象定义、核心字段含义、作用域选择以及多维度组合配置方法。这是后续进行资源配额性能调优和 OPA 规则集成的基础。