2. 资源配额(Resource Quota)基础:Kubernetes ResourceQuota 对象、作用范围与常用资源类型

在 GitOps 交付流水线中,资源配额(Resource Quota)是防止单个团队或应用“抢占”集群全部资源的首要防线。ResourceQuota 是 Kubernetes 内置的准入控制机制,它在 Namespace 级别 对聚合资源消耗进行硬性限制。理解其对象模型、作用域和资源类型,是后续进行配额校准与瓶颈分析的前提。

2.1 ResourceQuota 对象模型

ResourceQuota 是一个 Kubernetes API 对象,通过声明式 YAML 定义。其核心结构包含 spec.hard(硬限制)和可选的 spec.scopes(作用范围选择器)。

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: team-alpha
spec:
  hard:
    requests.cpu: "4"
    requests.memory: "8Gi"
    limits.cpu: "8"
    limits.memory: "16Gi"
    persistentvolumeclaims: "5"
    pods: "20"
    services: "10"
    count/deployments.apps: "5"
  scopes:
    - NotTerminating
    - BestEffort
关键理解: ResourceQuota 是 累加型 约束。它统计 Namespace 下所有符合 scope 条件的 Pod 的 requests 和 limits 总和,而非单个 Pod 的限制。当总和达到 hard 阈值时,API Server 会拒绝创建新的 Pod。

2.2 作用范围:Namespace 级别

ResourceQuota 的作用域严格限定在 单个 Namespace 内。这意味着:

  • 隔离性: 不同 Namespace 的配额相互独立,互不影响。
  • 默认行为: 如果 Namespace 下没有 ResourceQuota 对象,则不对资源使用做任何限制(除非集群级别有 LimitRange 或全局策略)。
  • 多配额共存: 一个 Namespace 可以定义多个 ResourceQuota 对象,Kubernetes 会取所有配额中 最严格 的限制生效(即所有 hard 字段的并集,相同资源取最小值)。
作用范围 说明 典型场景
Terminating 仅统计 activeDeadlineSeconds 被设置的 Pod 批处理任务、CI/CD Job
NotTerminating 仅统计 activeDeadlineSeconds 未设置的 Pod 长期运行的服务(Deployment、StatefulSet)
BestEffort 仅统计 QoS 等级为 BestEffort 的 Pod 低优先级、可被驱逐的测试负载
NotBestEffort 仅统计 QoS 等级非 BestEffort 的 Pod 生产级服务(Guaranteed / Burstable)
常见陷阱: 如果 ResourceQuota 设置了 scopes,则未匹配 scope 的 Pod 将不受该配额约束。例如,只设置 NotTerminating 范围的配额,则 Job 创建的 Pod(Terminating)不会计入该配额,可能导致资源超卖。

2.3 常用资源类型

ResourceQuota 支持三类资源维度:计算资源、存储资源 和 对象计数。在 GitOps 交付场景中,这三类资源必须同时校准,否则会出现“CPU 配额充足但 Pod 数已达上限”的瓶颈。

2.3.1 计算资源(CPU & 内存)

计算资源是配额校准的核心。Kubernetes 区分 requests(调度保证)和 limits(上限约束)。

  • requests.cpu / requests.memory: 所有 Pod 的 request 总和上限。直接影响调度决策。
  • limits.cpu / limits.memory: 所有 Pod 的 limit 总和上限。影响节点资源争抢和 OOM 风险。
校准要点: 在 GitOps 仓库中,应同时为每个 Namespace 设置 requests 和 limits 配额。仅设置 limits 而不设置 requests,会导致调度器无法准确感知资源压力,引发“调度成功但运行失败”的故障。

2.3.2 存储资源

存储配额控制的是 PVC 的总容量和数量,而非单个 PV 的大小。

资源名称 含义 单位
requests.storage 所有 PVC 请求的存储容量总和上限 Gi, Ti
persistentvolumeclaims Namespace 中允许的 PVC 对象总数 整数
storage-class-name.storageclass.storage.k8s.io/requests.storage 针对特定 StorageClass 的存储容量上限 Gi, Ti

2.3.3 对象计数(Object Counts)

对象计数用于防止 API Server 因对象过多而性能下降。在 GitOps 场景中,Deployment 和 ConfigMap 的计数 是最容易忽略的瓶颈。

# 标准对象计数格式
count/deployments.apps: "10"
count/configmaps: "20"
count/secrets: "20"
count/services: "10"
count/persistentvolumeclaims: "5"

# 自定义资源计数(CRD)
count/jobs.batch: "15"
count/cronjobs.batch: "5"
GitOps 实践建议: 在 Helm Chart 或 Kustomize 的 overlay 中,将 ResourceQuota 作为 基础设施模板 的一部分,与应用部署清单一同提交到 Git 仓库。这样,配额变更会经过 MR 审查,避免运维人员直接修改集群导致配额失控。

2.4 ResourceQuota 作用机制 SVG 图

下图展示了 ResourceQuota 在 Kubernetes 准入控制链中的位置,以及它如何拦截超出配额的资源请求。

ResourceQuota 准入控制流程 用户 / CI 提交 API Server 接收 准入控制链 (ResourceQuota 插件) 配额检查通过 配额检查拒绝 写入 etcd 返回 403 Forbidden 说明: ResourceQuota 作为准入控制插件,在对象持久化之前执行。它统计 Namespace 内现有资源总和 + 新请求资源,若超过 hard 限制则拒绝请求。

2.5 资源类型与配额字段映射表

下表汇总了 GitOps 交付中最常涉及的资源类型及其对应的 ResourceQuota 字段,帮助你在编写配额 YAML 时快速查找。

资源类别 ResourceQuota 字段 单位 典型值(团队级)
CPU requests.cpu m(毫核) 4000m (4 核)
limits.cpu m 8000m (8 核)
内存 requests.memory Mi, Gi 8Gi
limits.memory Mi, Gi 16Gi
临时存储 requests.ephemeral-storage Gi 20Gi
limits.ephemeral-storage Gi 40Gi
持久存储 persistentvolumeclaims 整数 10
requests.storage Gi 100Gi
对象计数 count/deployments.apps 整数 10
count/configmaps 整数 30
count/secrets 整数 30
count/services 整数 15

2.6 多配额叠加效果 SVG 图

当一个 Namespace 中存在多个 ResourceQuota 对象时,Kubernetes 会合并所有 hard 限制,取每个资源维度的最小值作为最终生效阈值。下图展示了这种叠加逻辑。

多 ResourceQuota 叠加生效逻辑 Quota A cpu: 4 memory: 8Gi pods: 20 Quota B cpu: 6 memory: 16Gi pods: 15 生效限制 cpu: min(4,6) = 4 memory: min(8,16) = 8Gi pods: min(20,15) = 15 叠加规则: 1. 同一 Namespace 下多个 ResourceQuota 的 hard 字段会合并。 2. 对于相同的资源类型(如 cpu),取所有配额中的 最小值 作为最终限制。 3. 不同资源类型互不影响,例如 Quota A 的 cpu 限制不会影响 Quota B 的 memory 限制。 4. 如果某个资源只在一个 Quota 中定义,则直接使用该值。
GitOps 校准提示: 在 GitOps 仓库中,建议为每个 Namespace 只维护 一个 ResourceQuota 对象,避免多配额叠加导致预期外的“更严格限制”。如果必须使用多配额(例如平台团队和业务团队各自管理一部分),请务必在 MR 描述中注明叠加后的生效值,并定期使用 kubectl describe quota 验证实际生效阈值。