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 生命周期之间的交互关系,以及配额不足如何传导为延迟异常。
4.4 默认行为与优先级
当 ResourceQuota 与 LimitRange 同时存在时,Kubernetes 遵循以下优先级规则:
- 显式声明 > 默认值: 如果 Pod 的容器已设置 requests/limits,LimitRange 的 default 不会覆盖。
- LimitRange 的 min/max 为硬约束: 即使 ResourceQuota 还有余量,Pod 的 requests 若低于 min 或高于 max,创建请求也会被拒绝。
- ResourceQuota 在准入阶段最后校验: 先通过 LimitRange 注入/校验,再累加至 ResourceQuota 统计,超出则拒绝。
- 未设置 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 |