4. 资源配额(ResourceQuota)基础

ResourceQuota 是 Kubernetes 内置的准入控制机制,用于限制命名空间(Namespace)级别的资源消耗总量。它防止单个团队或项目过度占用集群资源,是集群管理员实现多租户资源隔离的核心工具。在 Kyverno 策略与集群升级场景中,ResourceQuota 的准确配置直接决定了升级过程中 Pod 能否正常调度、资源是否被预留。

4.1 ResourceQuota 核心概念

ResourceQuota 以命名空间为作用域,通过声明式 YAML 定义该命名空间内所有 Pod 可使用的资源上限。当用户尝试创建或更新 Pod 时,Kubernetes 准入控制器会检查当前命名空间的已使用资源加上新 Pod 的请求资源是否超过配额上限,若超过则拒绝操作。

关键原则:ResourceQuota 是“硬限制”(Hard Limit),而非“软限制”(Soft Limit)。一旦达到配额上限,后续创建请求会被立即拒绝,不会触发驱逐或告警(除非配合外部监控)。

4.2 作用域(Scope)

ResourceQuota 支持按作用域(Scope)细分配额限制,使管理员能针对不同状态的 Pod 设置差异化配额。下表列出 Kubernetes 内置的 ResourceQuota 作用域:

作用域名称 匹配条件 典型用途
BestEffort Pod 未设置任何资源请求(requests)和限制(limits) 限制“尽力而为”类 Pod 的总数或 CPU/内存总量
NotBestEffort Pod 设置了至少一个资源请求或限制 对正常业务 Pod 进行资源总量控制
Terminating Pod 设置了 activeDeadlineSeconds 限制批处理或定时任务类 Pod 的资源占用
NotTerminating Pod 未设置 activeDeadlineSeconds 限制常驻服务类 Pod 的资源占用
PriorityClass Pod 关联了指定的 PriorityClass 名称 按优先级等级隔离资源配额(需指定 scopeSelector)
实践建议:在集群升级前,建议使用 NotBestEffort 和 NotTerminating 作用域组合来限制常规工作负载,避免因升级过程中临时创建的 BestEffort Pod 挤占关键业务资源。

4.3 配额类型

ResourceQuota 支持三类资源配额:计算资源、存储资源 和 对象数量。每类配额在 YAML 中通过 spec.hard 字段下的不同键名来定义。

4.3.1 计算资源配额

计算资源配额控制命名空间内所有 Pod 的 CPU 和内存总量。支持以下键名:

  • requests.cpu — 所有 Pod 的 CPU 请求总和上限(单位:核心数或 millicores)
  • requests.memory — 所有 Pod 的内存请求总和上限(单位:字节、Ki、Mi、Gi)
  • limits.cpu — 所有 Pod 的 CPU 限制总和上限
  • limits.memory — 所有 Pod 的内存限制总和上限
apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: team-alpha
spec:
  hard:
    requests.cpu: "10"
    requests.memory: "20Gi"
    limits.cpu: "20"
    limits.memory: "40Gi"

4.3.2 存储资源配额

存储资源配额控制命名空间内所有 PersistentVolumeClaim(PVC)的存储总量。支持以下键名:

  • requests.storage — 所有 PVC 的存储请求总和上限
  • persistentvolumeclaims — PVC 对象数量上限
  • <storage-class-name>.storageclass.storage.k8s.io/requests.storage — 按 StorageClass 细分的存储请求上限
  • <storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims — 按 StorageClass 细分的 PVC 数量上限
apiVersion: v1
kind: ResourceQuota
metadata:
  name: storage-quota
  namespace: team-alpha
spec:
  hard:
    requests.storage: "500Gi"
    persistentvolumeclaims: "10"
    ssd.storageclass.storage.k8s.io/requests.storage: "200Gi"
    ssd.storageclass.storage.k8s.io/persistentvolumeclaims: "5"

4.3.3 对象数量配额

对象数量配额控制命名空间内 Kubernetes 核心对象的数量上限。常见对象类型包括:

配额键名 控制对象 典型上限
pods Pod 总数(含所有状态) 100
services Service 总数 50
configmaps ConfigMap 总数 100
secrets Secret 总数 100
replicationcontrollers ReplicationController 总数 20
resourcequotas ResourceQuota 对象总数 1(通常每个命名空间只定义一个)
apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-quota
  namespace: team-alpha
spec:
  hard:
    pods: "50"
    services: "10"
    configmaps: "20"
    secrets: "20"

4.4 ResourceQuota 与 Pod 资源请求的关系

当命名空间设置了 ResourceQuota 后,Kubernetes 要求该命名空间内的每个 Pod 必须显式设置资源请求(requests)。如果 Pod 未设置 requests,则创建请求会被拒绝。这一行为确保了配额计算的可预测性。

升级风险提示:在集群升级过程中,如果目标命名空间已配置 ResourceQuota,但升级控制器(如 Deployment 的滚动更新)创建的临时 Pod 未设置资源请求,会导致升级卡住。建议在升级前使用 Kyverno 策略强制所有 Pod 设置 requests 和 limits。

4.5 ResourceQuota 架构关系图

下图展示了 ResourceQuota 在 Kubernetes 控制平面中的位置及其与 API Server、准入控制器、命名空间和 Pod 的关系:

ResourceQuota 架构关系图 ResourceQuota 架构关系图 API Server ResourceQuota 准入控制器 Namespace: team-alpha ResourceQuota 对象 Pod 集合 requests + limits 工作流程 用户创建 Pod → API Server → ResourceQuota 准入控制器 → 检查命名空间配额 → 通过则创建,拒绝则返回错误

4.6 多配额类型组合示例

实际生产环境中,通常将计算、存储和对象配额合并到一个 ResourceQuota 对象中,以便统一管理。以下是一个综合示例:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-alpha-quota
  namespace: team-alpha
spec:
  hard:
    # 计算资源
    requests.cpu: "8"
    requests.memory: "16Gi"
    limits.cpu: "16"
    limits.memory: "32Gi"
    # 存储资源
    requests.storage: "200Gi"
    persistentvolumeclaims: "20"
    # 对象数量
    pods: "40"
    services: "10"
    configmaps: "30"
    secrets: "30"
    replicationcontrollers: "10"
  scopeSelector:
    matchExpressions:
      - operator: In
        scopeName: PriorityClass
        values:
          - high-priority
Kyverno 联动场景:在集群升级前,可以使用 Kyverno 策略自动校验每个命名空间的 ResourceQuota 是否覆盖了所有关键资源类型(如 CPU、内存、Pod 数量),并生成校准报告。这避免了升级过程中因配额不足导致的 Pod 创建失败。

4.7 配额使用情况查看

管理员可以通过 kubectl describe resourcequota 命令查看当前命名空间的配额使用情况,输出会显示已使用量和上限:

kubectl describe resourcequota team-alpha-quota -n team-alpha

Name:            team-alpha-quota
Namespace:       team-alpha
Resource         Used  Hard
--------         ---   ---
requests.cpu     3.5   8
requests.memory  7Gi   16Gi
limits.cpu       6.2   16
limits.memory    14Gi  32Gi
pods             18    40
services         5     10
configmaps       12    30
secrets          8     30

该输出是集群升级前资源校准的重要依据。如果 Used 接近 Hard,则升级过程中新 Pod 可能无法调度,需要提前调整配额或清理资源。

4.8 配额校准与升级准备

在集群升级场景中,ResourceQuota 校准应遵循以下步骤:

  1. 收集现状:使用 kubectl get resourcequota --all-namespaces 列出所有命名空间的配额配置。
  2. 分析使用率:对每个命名空间,计算 Used / Hard 比率,标记使用率超过 80% 的配额项。
  3. 评估升级影响:升级过程中,Deployment 滚动更新会创建临时 Pod,导致资源使用量短暂上升。确保配额有 20% 以上的余量。
  4. 调整配额:对余量不足的命名空间,临时提高配额上限,或要求业务方清理闲置资源。
  5. 验证:使用 Kyverno 策略模拟升级场景,验证配额调整后的 Pod 创建是否正常。
常见陷阱:ResourceQuota 不限制已运行 Pod 的资源使用量(仅限制创建时)。如果升级过程中现有 Pod 因资源不足被驱逐,但新 Pod 因配额限制无法创建,会导致服务中断。建议在升级前使用 kubectl top pod 检查实际资源使用量,确保配额设置合理。