2. Kubernetes 资源管理基础:Pod 与容器的资源请求(Requests)与限制(Limits)概念、QoS 类别

在 Kubernetes 集群中,资源管理是调度与运行时稳定的基石。每个 Pod 由一组容器组成,而每个容器都可以声明其所需的计算资源——CPU 和内存。这些声明通过 Requests(请求) 和 Limits(限制) 两个字段表达,并最终决定了 Pod 的 QoS(服务质量)类别。kubelet 正是依据这些信息与容器运行时(如 containerd、CRI-O)交互,完成容器的创建、资源分配与驱逐决策。

2.1 Requests 与 Limits 的定义与作用

字段 含义 调度依据 运行时行为
Requests 容器启动时保证获得的最小资源量 kube-scheduler 根据节点剩余可分配资源进行调度 cgroup 的 cpu.shares(CPU)和 memory.limit_in_bytes(内存软限制)
Limits 容器运行时不能超过的资源上限 不参与调度决策 cgroup 的 cpu.cfs_quota_us(CPU 硬限制)和 memory.limit_in_bytes(内存硬限制)
关键区别: Requests 是“保证值”,Limits 是“天花板”。当节点资源紧张时,kubelet 会优先保证 Requests 的满足,而超出 Limits 的容器会被 OOM Kill 或 CPU 节流。

2.2 资源单位与配置示例

  • CPU: 以 m(毫核)为单位,1 CPU = 1000m。例如 500m 表示 0.5 个 CPU 核心。
  • 内存: 使用 Mi(Mebibytes)、Gi(Gibibytes)等二进制单位。例如 256Mi 表示 256 Mebibytes。
apiVersion: v1
kind: Pod
metadata:
  name: resource-demo
spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:
        cpu: "250m"
        memory: "128Mi"
      limits:
        cpu: "500m"
        memory: "256Mi"
实践要点: 生产环境中建议始终设置 Requests 与 Limits。仅设置 Limits 而不设置 Requests 会导致调度器低估实际需求,可能引发节点过载。

2.3 QoS 类别:Guaranteed / Burstable / BestEffort

Kubernetes 根据 Pod 中所有容器的 Requests 与 Limits 设置情况,将 Pod 划分为三种 QoS 类别。kubelet 在节点资源压力下,按照 QoS 优先级进行驱逐:BestEffort > Burstable > Guaranteed。

QoS 类别判定流程与驱逐优先级 Guaranteed 所有容器 requests == limits CPU 和内存均设置 Burstable 至少一个容器 requests < limits 或仅设置 requests BestEffort 所有容器均未设置 requests 和 limits kubelet 驱逐优先级(从高到低) 1. BestEffort(红色)— 最先被驱逐 2. Burstable(橙色)— 按内存使用率排序 3. Guaranteed(绿色)— 最后被驱逐

2.4 三种 QoS 类别的详细对比

QoS 类别 设置条件 CPU 行为 内存行为 驱逐优先级
Guaranteed 所有容器 requests == limits(CPU 和内存均设置) 使用 CFS 配额,不会节流到 requests 以下 内存上限严格等于 limits,OOM 优先级最低 最低(最安全)
Burstable 至少一个容器 requests < limits,或仅设置 requests 可突发使用空闲 CPU,但受 CFS 配额限制 内存可超用至 limits,超限时 OOM Kill 中等
BestEffort 所有容器均未设置 requests 和 limits 使用空闲 CPU,无保证,可能被节流 无内存限制,节点内存不足时最先被杀死 最高(最先被驱逐)
重要提醒: 即使 Pod 的 QoS 类别为 Guaranteed,如果其内存使用超过 limits,仍然会被 OOM Killer 终止。Limits 是硬边界,不是建议值。

2.5 kubelet 与 CRI 的资源交互视角

当 kubelet 创建 Pod 时,它会将 Requests 和 Limits 转换为 CRI 的 LinuxContainerResources 结构体,并通过 RunPodSandbox 和 CreateContainer 接口传递给容器运行时。运行时再将其映射为 cgroup 参数:

// CRI 资源结构体示例(简化)
message LinuxContainerResources {
  int64 cpu_shares = 1;          // 对应 requests.cpu
  int64 cpu_period = 2;          // 默认 100000 us
  int64 cpu_quota = 3;           // 对应 limits.cpu
  int64 memory_limit_in_bytes = 4; // 对应 limits.memory
  int64 memory_swap_limit_in_bytes = 5; // 通常与 memory_limit 相同
}
容量调优关键: 理解 Requests/Limits 与 cgroup 的映射关系,是后续章节中分析 CPU 节流、内存 OOM、以及 kubelet 驱逐策略的基础。例如,cpu_shares 控制 CPU 时间片的分配权重,而 cpu_quota 决定容器能否突发使用更多 CPU。

2.6 最佳实践建议

  • 生产环境: 始终为所有容器设置 Requests 和 Limits,避免 BestEffort Pod 影响关键业务。
  • 性能敏感型应用: 使用 Guaranteed QoS,确保 CPU 和内存的确定性。
  • 弹性负载: 使用 Burstable QoS,允许容器在空闲时使用更多资源,但需监控内存超用风险。
  • 监控指标: 关注 container_cpu_cfs_throttled_seconds_total 和 container_oom_events_total,判断资源限制是否合理。