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 在启动时按以下顺序计算并注册节点资源:
- 读取 Node Capacity:从 cgroups 或 /proc 文件系统获取 CPU、内存、磁盘、PID 的硬件总量。
- 扣除 System Reserved:根据
--system-reserved参数值(如cpu=500m,memory=1Gi)从 Capacity 中减去。 - 扣除 Kube Reserved:根据
--kube-reserved参数值(如cpu=200m,memory=512Mi)继续减去。 - 扣除 Eviction Thresholds:根据
--eviction-hard参数(如memory.available<100Mi)从剩余量中减去阈值对应的资源量。 - 注册 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 的完整计算链路,以及各层预留的归属关系:
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 层面的资源隔离。