2. Kubernetes 资源管理基础:Pod资源模型、Request与Limit机制、服务质量QoS等级、资源争抢与超卖问题

在深入准入控制与资源画像之前,必须建立对Kubernetes原生资源管理模型的精确理解。Pod是调度的最小单元,其资源声明方式直接决定了调度决策、节点压力以及服务质量。本节将拆解Pod资源模型的核心要素,并揭示资源争抢与超卖问题的根源。

2.1 Pod资源模型:CPU与内存的声明范式

Kubernetes将物理资源抽象为两大类可度量资源:可压缩资源(CPU)与不可压缩资源(内存)。CPU可以按时间片进行分时复用,超限时仅表现为性能下降;内存一旦耗尽,进程将被OOM Killer终止。这种本质差异决定了资源管理策略的分野。

每个Pod内的容器通过 resources.requests 和 resources.limits 字段声明资源需求。资源单位遵循严格的规范:

资源类型 单位 表示方式 说明
CPU 核心数(vCPU) 整数(2)或毫核(1500m) 1核 = 1000m,最小精度1m
内存 字节 E/P/T/G/M/KiB或Ei/Pi/Ti/Gi/Mi/Ki 1Gi = 1024³字节,1G = 1000³字节
临时存储 字节 同上 用于emptyDir、日志等本地写入
实践要点:生产环境中CPU请求建议使用毫核(m)为单位,避免浮点数精度问题。内存建议使用二进制单位(Mi/Gi),与容器运行时(cgroup v2)的内存计数方式保持一致。

2.2 Request与Limit机制:调度保证与资源上限

Request与Limit构成了Kubernetes资源管控的双重语义:Request是调度承诺,Limit是运行时约束。两者之间的差值定义了容器可以临时突发的资源空间。

  • Request(请求量):调度器依据所有Pod的Request总和决定节点能否容纳新Pod。kubelet将Request值写入cgroup的 cpu.shares 和 memory.soft_limit_in_bytes,作为资源分配的权重基准。
  • Limit(上限):kubelet将Limit值写入cgroup的 cpu.cfs_quota_us 和 memory.limit_in_bytes,强制限制容器的资源使用上限。CPU Limit通过CFS带宽控制实现,内存Limit通过OOM机制强制执行。

当Limit未设置时,容器可以无限使用节点空闲资源,但一旦节点发生资源竞争,未设置Limit的容器将面临被优先驱逐的风险。

关键公式:调度可行性条件:sum(Requests of all Pods) ≤ Node Allocatable。注意,调度器仅检查Request,不检查Limit。这意味着即使所有Pod的Limit总和远超节点容量,只要Request总和在节点可分配范围内,调度仍然成功。
# 一个典型的生产级Pod资源声明示例
apiVersion: v1
kind: Pod
metadata:
  name: resource-demo
spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:
        cpu: "500m"        # 调度保证:0.5核
        memory: "256Mi"    # 调度保证:256MiB
      limits:
        cpu: "1000m"       # 运行时上限:1核
        memory: "512Mi"    # 运行时上限:512MiB

2.3 服务质量QoS等级:三类优先级模型

Kubernetes根据Pod中所有容器的Request与Limit设置组合,将Pod划分为三个服务质量等级。QoS等级决定了节点资源紧张时的驱逐顺序与OOM评分。

QoS等级 判定条件 OOM得分 驱逐优先级 典型场景
Guaranteed 所有容器均设置Request=Limit,且不为0 2(最低) 最低(最后被驱逐) 数据库、关键中间件
Burstable 至少一个容器设置了Request,且至少一个容器Request≠Limit 根据内存使用率动态计算(2~1000) 中等 Web服务、微服务
BestEffort 所有容器均未设置Request和Limit 1000(最高) 最高(最先被驱逐) 批处理、非关键任务
重要警告:BestEffort Pod在内存压力下会被优先杀死,且没有任何资源保证。生产环境中应避免将核心服务以BestEffort方式运行。即使是非关键任务,也建议设置极低的Request(如cpu: 10m, memory: 32Mi)使其进入Burstable等级,获得基本的调度保障。

下图展示了QoS等级在节点资源耗尽时的驱逐决策流程:

节点资源耗尽时QoS驱逐决策流程 节点内存/CPU压力 是否存在 BestEffort Pod? 是 驱逐 BestEffort Pod 否 检查 Burstable Pod 按OOM得分从高到低驱逐 节点恢复稳定状态

2.4 资源争抢与超卖问题:根源与风险

资源争抢与超卖是Kubernetes集群中最常见的性能隐患。理解其成因是设计资源预留策略的前提。

2.4.1 超卖的成因

Kubernetes允许超卖的根本原因在于:调度器仅基于Request做决策,而Limit可以远大于Request。当集群管理员或开发者设置过低的Request(为了通过调度)却设置过高的Limit(为了应对突发流量)时,节点上所有Pod的Limit总和可能远超节点实际容量。

  • CPU超卖:多个Pod的CPU Limit总和超过节点总CPU核数。由于CPU是可压缩资源,超卖仅导致CPU Throttling(限流),不会直接引发进程死亡,但会显著增加P99延迟。
  • 内存超卖:多个Pod的内存Limit总和超过节点总内存。内存是不可压缩资源,一旦实际使用量超过节点容量,OOM Killer将介入,按照QoS等级和OOM得分杀死容器。

2.4.2 资源争抢的典型表现

现象 根因 影响范围 排查手段
Pod频繁重启(CrashLoopBackOff) 内存Limit过低或节点内存超卖导致OOM 单个Pod kubectl describe pod 查看Last State
应用响应延迟飙升 CPU Limit导致CFS Throttling 同节点多个Pod 容器内 /sys/fs/cgroup/cpu.stat 的 nr_throttled
节点状态为MemoryPressure 节点可用内存低于阈值(默认100Mi) 整个节点 kubectl describe node 查看Conditions
调度失败(Unschedulable) 节点剩余可分配资源不足 新创建Pod kubectl describe pod 查看Events
核心矛盾:Request设置过低 → 调度器允许更多Pod部署到同一节点 → 实际内存使用量超过节点容量 → OOM Killer驱逐低优先级Pod。这种“调度成功但运行时失败”的现象,正是超卖问题的直接体现。资源画像驱动的预留方法,正是要解决Request与真实需求之间的偏差。

下图展示了超卖场景下资源争抢的演进路径:

超卖场景下资源争抢演进路径 阶段1:Request设置过低 调度器允许更多Pod部署 阶段2:节点资源超卖 Limit总和 > 节点容量 阶段3:实际使用超限 内存耗尽 / CPU Throttling 触发节点资源压力条件 结果A:OOM驱逐 低QoS Pod被杀死 结果B:性能劣化 延迟增加,吞吐下降 需要资源画像驱动的预留策略

2.5 从资源管理到准入控制:问题的延伸

上述分析揭示了原生Kubernetes资源管理的三个关键缺陷:

  1. Request与真实需求脱节:开发者倾向于设置保守的Request以通过调度,导致节点过度承诺。
  2. QoS等级粒度粗糙:仅三个等级无法表达微服务间复杂的优先级依赖关系。
  3. 缺乏历史行为反馈:调度器不感知Pod的历史资源使用模式,无法动态调整预留。

这正是准入控制框架下资源画像驱动方法的切入点——通过在Pod创建时注入基于历史画像计算出的精确资源预留,从源头消除超卖风险,同时避免资源浪费。