3. ResourceQuota 进阶:配额作用域、优先级类与配额关联、硬限制与软限制
ResourceQuota 的基础用法只能按 Namespace 做总量控制,但在多租户、多优先级、多工作负载类型的生产集群中,这种粗粒度配额远远不够。Kubernetes 提供了 ScopeSelector(配额作用域)、PriorityClass(优先级类) 与配额关联机制,以及 硬限制(Hard) 与 软限制(Soft) 的差异化策略,让资源配额从“一刀切”进化为“精细化治理”。
3.1 配额作用域(ScopeSelector)
ScopeSelector 允许 ResourceQuota 只匹配特定“作用域”内的 Pod 或资源对象,从而实现按资源生命周期、服务质量等级(QoS)或优先级进行差异化配额控制。
3.1.1 内置作用域类型
| 作用域名称 | 匹配对象 | 典型场景 |
|---|---|---|
BestEffort |
QoS 等级为 BestEffort 的 Pod | 限制低优先级、无资源预留的“尽力而为”型任务 |
NotBestEffort |
QoS 等级非 BestEffort 的 Pod(Guaranteed 或 Burstable) | 保障有资源预留的生产级 Pod 的配额 |
Terminating |
activeDeadlineSeconds 被设置的 Pod |
批处理、Job 类有生命周期的任务 |
NotTerminating |
activeDeadlineSeconds 未被设置的 Pod |
长期运行的服务(Deployment、StatefulSet) |
PriorityClass |
指定优先级类的 Pod(需配合 scopeSelector.matchExpressions) |
按优先级类隔离配额池 |
3.1.2 使用 ScopeSelector 的 YAML 示例
以下 ResourceQuota 只对 非 BestEffort 且 非 Terminating 的 Pod 生效,即只限制长期运行且有资源预留的服务 Pod:
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: production
spec:
hard:
requests.cpu: "20"
requests.memory: "40Gi"
limits.cpu: "40"
limits.memory: "80Gi"
scopeSelector:
matchExpressions:
- operator: In
scopeName: NotBestEffort
- operator: In
scopeName: NotTerminating
3.2 优先级类(PriorityClass)与配额关联
PriorityClass 是 Kubernetes 调度优先级的核心对象。通过将 PriorityClass 与 ResourceQuota 的 ScopeSelector 关联,可以实现 按优先级分配资源配额,确保高优先级工作负载不会被低优先级任务挤占资源。
3.2.1 优先级类定义示例
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "高优先级生产服务"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low-priority
value: 100
globalDefault: false
description: "低优先级批处理任务"
3.2.2 按优先级类隔离配额
通过 scopeSelector 的 PriorityClass 作用域,可以为不同优先级类创建独立的配额池:
apiVersion: v1
kind: ResourceQuota
metadata:
name: high-priority-quota
namespace: production
spec:
hard:
pods: "50"
requests.cpu: "10"
requests.memory: "20Gi"
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["high-priority"]
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: low-priority-quota
namespace: production
spec:
hard:
pods: "200"
requests.cpu: "30"
requests.memory: "60Gi"
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["low-priority"]
priorityClassName,否则不会被任何 PriorityClass 作用域的配额匹配。未设置优先级类的 Pod 默认使用集群的 globalDefault PriorityClass(如果存在),否则不会被匹配。
3.3 配额硬限制与软限制
ResourceQuota 支持两种限制模式:硬限制(Hard) 和 软限制(Soft)。硬限制是阈值,超过即拒绝;软限制允许超过,但会触发告警或驱逐机制。
3.3.1 硬限制(Hard)
硬限制是 ResourceQuota 的默认模式。当 Namespace 内的资源使用量达到或超过硬限制时,Kubernetes API Server 会拒绝创建新的 Pod 或资源对象,并返回 403 Forbidden 错误。
- 适用场景: 资源容量上限、租户隔离、成本控制。
- 行为: 立即拒绝,不可协商。
- 示例:
pods: "100"表示最多允许 100 个 Pod。
3.3.2 软限制(Soft)
软限制允许资源使用量超过阈值,但会记录事件并触发 配额驱逐(Quota Eviction)。Kubernetes 会定期检查软限制,如果超过阈值且持续时间超过 gracePeriod,则会驱逐 Pod 以回收资源。
- 适用场景: 突发流量容忍、资源弹性、渐进式告警。
- 行为: 允许超过,但超过后进入“宽限期”,宽限期结束后驱逐 Pod。
- 配置: 使用
spec.scopes或scopeSelector配合spec.hard和spec.soft字段。
3.3.3 硬限制与软限制对比
| 特性 | 硬限制(Hard) | 软限制(Soft) |
|---|---|---|
| 阈值行为 | 超过即拒绝 | 超过允许,但触发驱逐 |
| 宽限期 | 无 | 可配置(gracePeriod) |
| 适用资源 | 所有配额资源 | 仅支持 requests.* 和 limits.* |
| 驱逐机制 | 无 | 超过宽限期后驱逐 Pod |
| 典型用途 | 硬性资源上限 | 弹性资源池、突发流量缓冲 |
3.3.4 软限制配置示例
apiVersion: v1
kind: ResourceQuota
metadata:
name: soft-quota
namespace: elastic
spec:
hard:
requests.cpu: "10"
requests.memory: "20Gi"
soft:
requests.cpu: "8"
requests.memory: "16Gi"
scopeSelector:
matchExpressions:
- operator: In
scopeName: NotBestEffort
--soft-eviction-grace-period 调整)内资源使用量未回落到软限制以下,kubelet 将开始驱逐 Pod,直到资源使用量低于软限制。
3.4 综合架构:ScopeSelector + PriorityClass + 硬/软限制
将上述三个概念组合,可以构建一个完整的、多层次的配额治理体系。以下 SVG 图展示了这种组合架构:
3.5 生产实践建议
- 分层设计: 为每个 Namespace 创建至少 2-3 个 ResourceQuota,分别覆盖高优先级服务、低优先级任务和批处理作业。
- 软限制宽限期: 高优先级服务的软限制宽限期应较短(如 1-5 分钟),以便快速回收资源;低优先级任务可设置较长宽限期(如 15-30 分钟),容忍突发流量。
- 监控与告警: 使用
kubectl describe resourcequota或 Prometheus 监控配额使用率,对软限制触发事件设置告警。 - 避免冲突: 同一个 Pod 只能被一个 ResourceQuota 的 ScopeSelector 匹配。如果多个配额的作用域重叠,Pod 创建会失败。建议使用互斥的作用域组合。
LimitRange 与 ResourceQuota 使用。LimitRange 设置 Pod 和容器的默认资源请求/限制以及最小/最大值,ResourceQuota 设置 Namespace 总量上限。两者配合可以实现“容器级别约束 + Namespace 级别总量控制”的完整治理。