3、节点资源抽象:Node Capacity、Allocatable、Reserved、Eviction Thresholds 的计算逻辑与配置方法

在 Kubernetes 集群中,一个节点的物理资源(CPU、内存、磁盘、PID)并非全部可供 Pod 使用。Kubelet 通过一套严格的资源抽象模型,将原始硬件容量逐层扣除系统预留、Kubernetes 守护进程预留和驱逐阈值,最终得到 Pod 可用的 Allocatable 资源。理解这一计算链条是容量评估与资源配额规划的基础。

3.1 核心概念与计算逻辑

节点资源从物理总量到 Pod 可用量的转换遵循以下公式:

Allocatable = Node Capacity - Reserved - Eviction Thresholds

其中:
Reserved = System Reserved + Kube Reserved

各层含义如下:

概念 定义 典型值 / 来源
Node Capacity 节点硬件报告的原始资源总量(CPU 核数、内存大小、磁盘容量、PID 上限) 由操作系统 / 云厂商实例规格决定
System Reserved 为操作系统守护进程(sshd、systemd、内核等)预留的资源 通过 kubelet 参数 --system-reserved 配置
Kube Reserved 为 Kubernetes 系统组件(kubelet、容器运行时、CNI 等)预留的资源 通过 kubelet 参数 --kube-reserved 配置
Eviction Thresholds 触发 Pod 驱逐的硬性或软性资源水位线,从 Allocatable 中扣除 通过 kubelet 参数 --eviction-hard / --eviction-soft 配置
Allocatable 节点上可供工作负载 Pod 实际调度和使用的资源量 由上述公式计算得出,通过 kubectl describe node 查看
关键理解: Allocatable 是调度器判断 Pod 能否调度到该节点的唯一依据。如果 Pod 的 Request 总和超过节点的 Allocatable,调度器将拒绝调度。

3.2 计算流程与配置方法

Kubelet 在启动时按以下顺序计算并注册节点资源:

  1. 读取 Node Capacity:从 cgroups 或 /proc 文件系统获取 CPU、内存、磁盘、PID 的硬件总量。
  2. 扣除 System Reserved:根据 --system-reserved 参数值(如 cpu=500m,memory=1Gi)从 Capacity 中减去。
  3. 扣除 Kube Reserved:根据 --kube-reserved 参数值(如 cpu=200m,memory=512Mi)继续减去。
  4. 扣除 Eviction Thresholds:根据 --eviction-hard 参数(如 memory.available<100Mi)从剩余量中减去阈值对应的资源量。
  5. 注册 Allocatable:将最终结果写入 Node Status 的 status.allocatable 字段。
配置示例(kubelet 命令行参数):
--system-reserved=cpu=500m,memory=1Gi,pid=1000
--kube-reserved=cpu=200m,memory=512Mi,pid=500
--eviction-hard=memory.available<100Mi,nodefs.available<10%,nodefs.inodesFree<5%

3.3 驱逐阈值(Eviction Thresholds)的详细机制

驱逐阈值是节点资源抽象中容易被忽视但至关重要的部分。它决定了节点在资源紧张时何时开始驱逐 Pod,从而影响实际可用容量。

阈值类型 信号 说明
memory.available 节点可用内存 当可用内存低于阈值时触发驱逐
nodefs.available 节点文件系统可用空间 用于容器日志、镜像层等
nodefs.inodesFree 节点文件系统可用 inode 防止 inode 耗尽导致文件创建失败
imagefs.available 容器镜像文件系统可用空间 若与 nodefs 分离则独立监控
pid.available 节点可用 PID 数量 防止 PID 耗尽导致进程创建失败
重要: 驱逐阈值从 Allocatable 中扣除的是 阈值对应的资源量,而非触发驱逐时的实际剩余量。例如,设置 memory.available<100Mi 意味着 Allocatable 会减少 100Mi 内存,这部分内存被“预留”用于防止节点 OOM。

3.4 节点资源抽象全景图

下图展示了从 Node Capacity 到 Allocatable 的完整计算链路,以及各层预留的归属关系:

节点资源抽象计算链路 节点资源抽象:从 Capacity 到 Allocatable 的计算链路 Node Capacity(硬件总量) System Reserved(OS 预留) Kube Reserved(K8s 组件预留) Eviction Thresholds(驱逐阈值) Allocatable(Pod 可用量) 配置参数来源 --system-reserved cpu=500m,memory=1Gi --kube-reserved cpu=200m,memory=512Mi --eviction-hard memory.available<100Mi nodefs.available<10% --eviction-soft memory.available<200Mi --eviction-minimum-reclaim memory.available=50Mi

3.5 查看与验证方法

通过以下命令可以查看节点的实际资源分配情况:

# 查看节点 Allocatable 和 Capacity
kubectl describe node <node-name> | grep -A 5 "Capacity"

# 输出示例:
# Capacity:
#   cpu:                4
#   memory:             16387412Ki
#   ephemeral-storage:  102350Mi
# Allocatable:
#   cpu:                3
#   memory:             15287412Ki
#   ephemeral-storage:  92350Mi

# 查看 kubelet 配置(需在节点上执行)
ps aux | grep kubelet | grep -- '--system-reserved\|--kube-reserved\|--eviction-hard'
容量规划建议: 在评估集群容量时,应始终以 Allocatable 而非 Capacity 作为计算基准。建议为 System Reserved 和 Kube Reserved 设置合理的比例(通常各占 5%~10%),并根据节点规格动态调整驱逐阈值,避免过度预留导致资源浪费。

3.6 常见配置误区与避坑指南

  • 误区一: 认为 Capacity 就是 Pod 可用量。实际上,未配置预留时默认值可能为 0,导致节点在资源紧张时出现系统级故障。
  • 误区二: 驱逐阈值设置过高(如 memory.available<5%),导致 Allocatable 被过度扣除,造成资源浪费。
  • 误区三: 忽略 PID 和 inode 的预留。在运行大量 sidecar 或短生命周期 Pod 的集群中,PID 耗尽比内存耗尽更常见。
  • 误区四: 所有节点使用相同的预留配置。不同规格的节点(如 4C16G vs 32C128G)应使用不同的预留比例。
生产建议: 对于生产集群,建议在 kubelet 配置中显式设置 --system-reserved 和 --kube-reserved,并配合 --eviction-hard 和 --eviction-soft 形成分级驱逐策略。同时启用 --enforce-node-allocatable=pods,kube-reserved,system-reserved 来强制 cgroups 层面的资源隔离。