3. 资源模型与 QoS:Requests/Limits 机制、三种 QoS 类别与资源超卖原理
Kubernetes 的资源模型是调度与隔离的基石。理解 Requests(请求量)与 Limits(上限)的语义差异,以及由此衍生的三种 QoS(服务质量)类别,是进行容量规划与准入控制的前提。本节将拆解资源模型的核心概念,并揭示节点资源超卖的底层逻辑。
3.1 Requests 与 Limits:承诺与边界
每个容器在 Pod 定义中可声明两类资源约束:
| 属性 | 语义 | 调度影响 | 运行时影响 |
|---|---|---|---|
| Requests | 容器保证能获得的最小资源量 | 调度器依据节点剩余可分配资源(Allocatable - ΣRequests)决定是否调度 | CPU 使用 CFS 配额保证;内存由 OOM 优先级保护 |
| Limits | 容器允许使用的最大资源上限 | 不影响调度决策(仅用于准入校验) | CPU 通过 CFS 配额硬限制;内存超过 Limits 触发 OOM Kill |
关键区分:Requests 是调度承诺,Limits 是运行时边界。未设置 Limits 时,容器可以无限使用节点空闲资源,但一旦节点发生内存压力,未设 Limits 的容器可能被优先驱逐。
3.2 三种 QoS 类别:从 Guaranteed 到 BestEffort
K8s 根据 Pod 内所有容器的 Requests/Limits 配置组合,将 Pod 划分为三个 QoS 等级。等级决定了节点资源竞争时的驱逐优先级与 OOM 分数。
| QoS 类别 | 配置条件 | CPU 行为 | 内存行为 | 驱逐优先级 |
|---|---|---|---|---|
| Guaranteed | 每个容器 Requests == Limits(CPU 和内存均需设置) | 获得 CFS 配额保证,不会被节流(除非超限) | OOM 分数最低,内存不足时最后被杀死 | 最低(最安全) |
| Burstable | 至少一个容器 Requests < Limits,或仅设置 Requests | 可突发使用空闲 CPU,但受 CFS 配额限制 | OOM 分数中等,内存压力时可能被驱逐 | 中等 |
| BestEffort | 所有容器均未设置 Requests 和 Limits | 无任何保证,完全依赖空闲资源 | OOM 分数最高,内存不足时最先被杀死 | 最高(最先被驱逐) |
常见误区:很多团队将所有 Pod 设为 Guaranteed 以追求稳定性,但这会严重降低节点资源利用率。合理的策略是:关键业务 Pod 使用 Guaranteed,批处理/离线任务使用 BestEffort,普通微服务使用 Burstable。
3.3 资源超卖原理:如何安全地“多塞”Pod
资源超卖(Overcommit)是指节点上所有 Pod 的 Requests 总和超过节点实际可分配资源。K8s 默认允许超卖,但依赖 QoS 机制来管理风险。
超卖公式:超卖比 = Σ(Pod Requests) / Node Allocatable
当超卖比 > 1.0 时,节点处于超卖状态。
当超卖比 > 1.0 时,节点处于超卖状态。
超卖的核心逻辑:
- CPU 超卖安全:CPU 是可压缩资源,超卖时通过 CFS 配额节流,不会导致进程崩溃,只会降低性能。
- 内存超卖危险:内存是不可压缩资源,超卖时一旦实际使用量超过节点容量,必须通过 OOM Killer 杀死容器来释放内存。
- QoS 保护链:BestEffort → Burstable → Guaranteed 的驱逐顺序,确保关键业务在内存压力下存活。
3.4 超卖策略与准入控制实践
在生产环境中,超卖不是“能不能”的问题,而是“如何控制”的问题。以下策略可帮助团队在利用率和稳定性之间取得平衡:
- 设置超卖比例上限:通过准入控制器(如自定义 ValidatingAdmissionWebhook)限制节点超卖比不超过 1.5x(CPU)和 1.2x(内存)。
- 区分资源类型:CPU 可超卖至 2x-3x,内存建议不超过 1.2x,且必须配合 Guaranteed Pod 的内存预留。
- 使用 PriorityClass 配合 QoS:高优先级 Pod 即使 QoS 为 Burstable,也应通过 PriorityClass 确保在驱逐顺序中靠后。
- 监控实际使用率:超卖决策不能仅依赖 Requests,需结合 Prometheus 采集的容器实际 CPU/Memory 使用量动态调整。
# 示例:ValidatingAdmissionWebhook 检查 Pod 超卖比例
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: overcommit-check
webhooks:
- name: overcommit.overcommit.example.com
rules:
- operations: ["CREATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
clientConfig:
service:
name: overcommit-webhook
namespace: kube-system
path: /validate-overcommit
admissionReviewVersions: ["v1"]
sideEffects: None
最佳实践:在集群中部署 Descheduler 或 Node Resource Manager,定期根据实际资源使用率重新平衡 Pod,避免超卖导致的热点节点。同时,为关键业务 Pod 设置 Guaranteed QoS + 高 PriorityClass,形成双重保护。
3.5 三种 QoS 的典型配置示例
# Guaranteed QoS:Requests == Limits
apiVersion: v1
kind: Pod
metadata:
name: guaranteed-pod
spec:
containers:
- name: app
image: nginx
resources:
requests:
memory: "512Mi"
cpu: "1"
limits:
memory: "512Mi"
cpu: "1"
# Burstable QoS:Requests < Limits
apiVersion: v1
kind: Pod
metadata:
name: burstable-pod
spec:
containers:
- name: app
image: nginx
resources:
requests:
memory: "256Mi"
cpu: "0.5"
limits:
memory: "1Gi"
cpu: "2"
# BestEffort QoS:无资源设置
apiVersion: v1
kind: Pod
metadata:
name: besteffort-pod
spec:
containers:
- name: app
image: busybox
command: ["sleep", "3600"]
3.6 超卖风险与缓解措施
| 风险场景 | 触发条件 | 影响 | 缓解措施 |
|---|---|---|---|
| 内存超卖导致 OOM | 节点内存实际使用 > 100% | BestEffort/Burstable Pod 被杀死 | 设置内存超卖比 ≤ 1.2;为关键 Pod 设置 Guaranteed |
| CPU 节流导致延迟 | CPU 实际使用持续超过 CFS 配额 | 应用响应时间增加,吞吐下降 | 监控 CPU Throttling 指标;调整 Requests 或增加节点 |
| 节点资源碎片 | 大量小 Pod 分散调度,导致大 Pod 无法调度 | 资源利用率低,调度失败 | 使用 Pod Topology Spread Constraints;启用 Descheduler |
| QoS 降级 | 运维误修改资源声明 | Pod 被重新分类,驱逐优先级变化 | 使用准入控制器强制 QoS 类别;审计资源变更 |
容量优化核心公式:
节点有效容量 = Allocatable × (1 - 系统预留比例) - Σ(Guaranteed Pod Limits) - Σ(Burstable Pod Requests × 突发系数)
其中突发系数建议取 0.7-0.9,根据历史监控数据动态调整。
节点有效容量 = Allocatable × (1 - 系统预留比例) - Σ(Guaranteed Pod Limits) - Σ(Burstable Pod Requests × 突发系数)
其中突发系数建议取 0.7-0.9,根据历史监控数据动态调整。