4. 资源配额基础:Kubernetes 资源配额(ResourceQuota、LimitRange)的概念、作用域与默认行为

在 Gateway API 的性能调优实践中,资源配额是保障集群稳定性与服务质量的第一道防线。Kubernetes 通过 ResourceQuota 和 LimitRange 两个原生资源对象,为命名空间级别的资源消耗设定硬性边界与默认约束。理解它们的作用域、默认行为及与 Gateway Pod 的关系,是诊断延迟异常、防止资源争抢的前提。

4.1 ResourceQuota:命名空间的资源硬边界

ResourceQuota 是一个作用于 命名空间(Namespace) 级别的资源配额控制器。它聚合命名空间内所有 Pod(包括 Gateway Proxy Pod)的资源请求(requests)与限制(limits),一旦总量超过配额,Kubernetes API Server 将拒绝创建新的 Pod 或调整资源。

4.1.1 核心作用域

作用域(Scope) 含义 典型场景
BestEffort 仅统计未设置 requests/limits 的 Pod 限制非关键型任务的突发增长
NotBestEffort 统计至少设置了 requests 或 limits 的 Pod Gateway 生产环境必须设置资源,适用此域
Terminating 统计设置了 activeDeadlineSeconds 的 Pod 批处理任务、短生命周期 Job
NotTerminating 统计未设置 activeDeadlineSeconds 的 Pod Gateway、长期运行服务
调优提示: 对于 Gateway API 的 Proxy Pod(如 Envoy、Contour),应始终使用 NotBestEffort + NotTerminating 组合域,确保资源配额只统计生产级、长期运行的代理实例,避免被 BestEffort 的测试 Pod 挤占配额。

4.1.2 资源配额示例

apiVersion: v1
kind: ResourceQuota
metadata:
  name: gateway-quota
  namespace: gateway-system
spec:
  hard:
    requests.cpu: "8"
    requests.memory: "16Gi"
    limits.cpu: "16"
    limits.memory: "32Gi"
    pods: "50"
    services: "10"
    count/ingresses.networking.k8s.io: "5"
  scopeSelector:
    matchExpressions:
      - operator: In
        scopeName: NotBestEffort
      - operator: In
        scopeName: NotTerminating

上述配额限制了 gateway-system 命名空间内所有非 BestEffort、非 Terminating 的 Pod 资源总和。当 Gateway 实例扩容时,如果累计 CPU 请求超过 8 核,扩容将失败并返回 403 Forbidden,直接反映为 Gateway 无法响应流量增长——这是延迟飙升的常见根因之一。

4.2 LimitRange:Pod 级别的默认值与边界

LimitRange 在命名空间内为每个 Pod 或容器设置 最小(min)、最大(max) 以及 默认(default) 的资源值。它不直接限制总量,而是约束单个 Pod 的资源声明范围,防止某个容器过度申请或忘记设置资源。

4.2.1 关键字段与行为

字段 作用 对 Gateway 的影响
default 当 Pod 未设置 limits 时,自动注入此值 避免 Gateway 容器因未设 limits 被 OOMKill
defaultRequest 当 Pod 未设置 requests 时,自动注入此值 保证 Gateway 获得基础调度保障
max 限制单个容器 limits 的上限 防止 Gateway 容器过度申请导致节点过载
min 限制单个容器 requests 的下限 确保 Gateway 容器至少有最低资源保障
maxLimitRequestRatio 限制 limits/requests 的最大比值 防止 Gateway 设置过高的突发比(如 10:1)

4.2.2 LimitRange 配置示例

apiVersion: v1
kind: LimitRange
metadata:
  name: gateway-limits
  namespace: gateway-system
spec:
  limits:
    - type: Container
      default:
        cpu: "500m"
        memory: "512Mi"
      defaultRequest:
        cpu: "250m"
        memory: "256Mi"
      max:
        cpu: "2"
        memory: "4Gi"
      min:
        cpu: "100m"
        memory: "128Mi"
      maxLimitRequestRatio:
        cpu: "4"
常见陷阱: 如果 LimitRange 的 max 小于 ResourceQuota 中单个 Pod 的隐含需求,或者 min 大于 ResourceQuota 剩余容量,Pod 将永远无法调度。这种“配额死锁”在 Gateway 多副本部署时尤为隐蔽,表现为部分副本 Pending 导致整体延迟升高。

4.3 资源配额与 Gateway 延迟的关联模型

下图展示了 ResourceQuota、LimitRange 与 Gateway Pod 生命周期之间的交互关系,以及配额不足如何传导为延迟异常。

ResourceQuota & LimitRange 与 Gateway 延迟关联模型 ResourceQuota 命名空间资源硬边界 LimitRange Pod 级别默认值与边界 Gateway Proxy Pod Envoy / Contour 实例 约束 注入默认值 配额耗尽 → 扩容失败 Pod 创建被 403 拒绝 LimitRange 冲突 → Pending min > 剩余配额 默认值不合理 → 资源浪费 CPU Throttling 加剧 Gateway 延迟飙升 请求排队 / 连接超时 / 502 诊断路径:检查 ResourceQuota 剩余量 → 检查 LimitRange 是否与 Pod 资源声明冲突 → 检查 Gateway Pod 是否因配额不足处于 Pending 状态。

4.4 默认行为与优先级

当 ResourceQuota 与 LimitRange 同时存在时,Kubernetes 遵循以下优先级规则:

  1. 显式声明 > 默认值: 如果 Pod 的容器已设置 requests/limits,LimitRange 的 default 不会覆盖。
  2. LimitRange 的 min/max 为硬约束: 即使 ResourceQuota 还有余量,Pod 的 requests 若低于 min 或高于 max,创建请求也会被拒绝。
  3. ResourceQuota 在准入阶段最后校验: 先通过 LimitRange 注入/校验,再累加至 ResourceQuota 统计,超出则拒绝。
  4. 未设置 scopeSelector 的 ResourceQuota 作用于所有 Pod: 包括 BestEffort 和 Terminating,可能导致非预期拒绝。
性能调优要点: 在 Gateway 命名空间中,建议将 ResourceQuota 的 requests.cpu 设置为预期峰值负载的 1.2~1.5 倍,同时通过 LimitRange 的 maxLimitRequestRatio 限制 CPU 突发比不超过 4:1,避免 Gateway 在流量突发时因 CPU Throttling 导致延迟抖动。

4.5 常见配额问题与延迟症状对照

问题类型 具体表现 延迟症状 诊断命令
ResourceQuota 耗尽 新 Pod 创建失败,返回 403 扩容延迟 → 请求排队 → P99 升高 kubectl describe quota -n gateway-system
LimitRange min 过高 Pod 始终 Pending,无法调度 部分副本离线 → 连接池不足 → 超时 kubectl describe pod <pod> | grep Events
LimitRange 默认值过小 Pod 被注入过低的 CPU 限制 CPU Throttling → 请求处理变慢 kubectl top pod -n gateway-system
scopeSelector 遗漏 BestEffort Pod 占用配额 Gateway 扩容时配额不足 kubectl get quota -o yaml