3. 资源规格(ResourceSpec):CPU、内存、GPU等资源的请求(Request)与限制(Limit)模型
资源规格是容器运行时控制面中描述“容器需要多少计算资源”的核心数据结构。在 Kubernetes 与 CRI 集成中,Request(请求) 和 Limit(限制) 构成了资源调度的双维度模型。理解这一模型,是掌握资源隔离、服务质量(QoS)分级和节点压力驱逐的基础。
3.1 双维度模型:Request 与 Limit 的语义
Kubernetes 将资源描述拆分为两个独立但关联的字段:
| 维度 | 语义 | 调度影响 | 运行时影响 |
|---|---|---|---|
| Request | 容器启动时保证获得的最小资源量 | 调度器以此值计算节点剩余容量,决定 Pod 能否调度 | CRI 运行时(如 containerd)通过 cgroup 的 cpu.shares 和 memory.limit_in_bytes 保证下限 |
| Limit | 容器运行时允许使用的资源上限 | 调度器不直接使用 Limit 做准入判断 | CRI 运行时通过 cgroup 的 cpu.cfs_quota_us 和 memory.limit_in_bytes 实施硬限制 |
3.2 CPU 资源模型:可压缩资源
CPU 属于可压缩资源(Compressible Resource)。当容器超出 Limit 时,会被限流(throttle),但不会被杀死。CRI 运行时通过 Linux CFS(Completely Fair Scheduler)实现 CPU 资源的请求与限制。
- Request(CPU shares): 设置
cpu.shares,相对权重。例如 Request=2 的容器比 Request=1 的容器获得 2 倍 CPU 时间。 - Limit(CPU quota): 设置
cpu.cfs_period_us和cpu.cfs_quota_us。例如 Limit=2(2000m),表示每 100ms 周期内最多使用 200ms CPU 时间。 - 单位: 1 个 CPU 核心 = 1000m(millicores)。
# 示例:Pod 中容器资源规格定义
resources:
requests:
cpu: "500m" # 保证 0.5 核
memory: "256Mi" # 保证 256 MiB
limits:
cpu: "1000m" # 上限 1 核
memory: "512Mi" # 上限 512 MiB
3.3 内存资源模型:不可压缩资源
内存属于不可压缩资源(Incompressible Resource)。当容器超出内存 Limit 时,内核 OOM Killer 会介入,直接终止容器进程。CRI 运行时通过 cgroup 的 memory.limit_in_bytes 和 memory.soft_limit_in_bytes 实施控制。
| 参数 | cgroup 映射 | 行为 |
|---|---|---|
| Request | memory.soft_limit_in_bytes(部分运行时) |
调度保证,但内核不强制回收;节点内存压力时优先回收超出 Request 的部分 |
| Limit | memory.limit_in_bytes |
硬限制,超过即触发 OOM Kill |
3.4 GPU 等扩展资源模型:不可压缩 + 显式声明
GPU、FPGA、NVMe 等扩展资源(Extended Resources)遵循不同的模型:
- 不可压缩: 超出 Limit 无法被限流,只能失败或重试。
- 显式声明: 必须通过
resources.requests和resources.limits显式指定,且 Request 必须等于 Limit(不允许 overcommit)。 - 设备插件机制: 通过 Kubernetes 设备插件(Device Plugin)上报资源,CRI 运行时通过
UpdateContainerResources接口传递设备分配信息。
# GPU 资源声明示例
resources:
requests:
nvidia.com/gpu: 1
limits:
nvidia.com/gpu: 1 # Request == Limit,强制相等
3.5 资源模型在 CRI 集成中的传递路径
下图展示了从 Pod Spec 到 CRI 运行时 cgroup 配置的完整资源传递链路:
3.6 QoS 等级与资源规格的关系
Kubernetes 根据 Request 和 Limit 的设置组合,将 Pod 划分为三个 QoS 等级,直接影响节点压力下的驱逐优先级:
| QoS 等级 | 条件 | 驱逐优先级 | 典型场景 |
|---|---|---|---|
| Guaranteed | 所有容器 Request == Limit(且均设置) | 最低(最后被驱逐) | 数据库、关键中间件 |
| Burstable | 至少一个容器 Request < Limit 或仅设置 Request | 中等 | Web 服务、批处理任务 |
| BestEffort | 所有容器均未设置 Request 和 Limit | 最高(最先被驱逐) | 低优先级日志收集、缓存 |
3.7 资源规格的 CRI 数据结构
在 CRI gRPC 接口中,资源规格通过 LinuxContainerResources 消息传递。以下是核心字段映射:
// CRI 接口定义(简化)
message LinuxContainerResources {
// CPU 资源
int64 cpu_period = 1; // 对应 Limit 的 period (微秒)
int64 cpu_quota = 2; // 对应 Limit 的 quota (微秒)
int64 cpu_shares = 3; // 对应 Request 的 shares (权重)
// 内存资源
int64 memory_limit_in_bytes = 4; // 对应 Limit
int64 memory_soft_limit_in_bytes = 5; // 对应 Request (部分运行时)
// 扩展资源(如 GPU)
map<string, int64> hugepage_limits = 6;
map<string, int64> unified = 7; // cgroup v2 统一字段
}
Kubelet 在调用 CreateContainer 或 UpdateContainerResources 时,会将 Pod Spec 中的 Request/Limit 转换为上述 CRI 结构体,再由运行时写入 cgroup 文件系统。
3.8 资源模型设计要点总结
- CPU 可压缩: 超出 Limit 时被限流,容器继续运行;Request 通过 shares 保证相对权重。
- 内存不可压缩: 超出 Limit 时触发 OOM Kill;Request 通过 soft limit 提供调度保证。
- GPU 等扩展资源: Request == Limit,不允许 overcommit;通过设备插件和 CRI 的
UpdateContainerResources传递。 - QoS 等级: 由 Request/Limit 组合决定,直接影响节点压力下的驱逐顺序。
- CRI 传递: Kubelet → CRI gRPC → 容器运行时 → cgroup,形成完整的资源控制闭环。