2. Kubernetes 节点资源模型:CPU、内存、磁盘、网络、PID 的资源预留机制
在 Kubernetes 集群中,节点(Node)是承载 Pod 的物理或虚拟主机。节点资源模型定义了操作系统与 kubelet 如何划分、预留和调度 CPU、内存、磁盘、网络与 PID 等关键资源。合理的资源预留是保障节点稳定性、避免系统 OOM 或 Pod 驱逐的前提,也是容量规划与镜像拉取加速的基础。
2.1 节点资源预留的总体架构
Kubernetes 节点上的资源分为三层:系统预留(System Reserved)、kubelet 预留(Kubelet Reserved)和Pod 可用(Allocatable)。kubelet 在启动时根据配置计算 Allocatable 值,调度器据此判断节点能否容纳新 Pod。
Allocatable = Node Capacity - System Reserved - Kubelet Reserved - Eviction Thresholds
2.2 各资源维度的预留机制
不同资源在节点上的预留方式与参数各不相同。下表总结了 CPU、内存、磁盘、网络与 PID 的预留配置项与典型值。
| 资源维度 | 预留参数 | 默认值 | 驱逐阈值参数 | 典型配置建议 |
|---|---|---|---|---|
| CPU | --system-reserved=cpu=100m |
0 | 无(CPU 不驱逐) | 100m~500m(根据节点核数) |
| 内存 | --system-reserved=memory=512Mi |
0 | --eviction-hard=memory.available<100Mi |
系统预留 512Mi~2Gi;驱逐阈值保留 100Mi~500Mi |
| 磁盘(根分区) | --system-reserved=ephemeral-storage=1Gi |
0 | --eviction-hard=nodefs.available<10% |
预留 1Gi~10Gi;驱逐阈值 5%~10% |
| 磁盘(镜像分区) | 无直接预留参数 | — | --eviction-hard=imagefs.available<15% |
镜像分区驱逐阈值 10%~15% |
| 网络 | 无原生预留参数 | — | 无原生驱逐阈值 | 通过 CNI 带宽管理或 QoS 间接控制 |
| PID | --system-reserved=pid=1000 |
0 | --eviction-hard=pids.available<10% |
系统预留 500~2000;驱逐阈值 5%~10% |
2.3 CPU 与内存预留详解
2.3.1 CPU 预留
CPU 预留通过 --system-reserved=cpu=... 和 --kubelet-reserved=cpu=... 设置。预留的 CPU 不会分配给 Pod,但 kubelet 仍会统计其使用量。CPU 是可压缩资源,不会触发驱逐,但过度预留会导致 Pod 可调度核数减少。
2.3.2 内存预留
内存是不可压缩资源,预留不足会导致系统 OOM Killer 杀死关键进程。kubelet 通过 --eviction-hard=memory.available<100Mi 设置硬驱逐阈值,当节点可用内存低于该值时开始驱逐 Pod。
--system-reserved 与 --kubelet-reserved 之和设得过高,否则 Allocatable 会远小于实际可用内存,造成资源浪费。建议预留总量不超过节点内存的 15%。
2.4 磁盘与镜像存储预留
磁盘预留分为两个维度:节点文件系统(nodefs,即 / 分区)和镜像文件系统(imagefs,即容器镜像存储分区)。
- nodefs 预留: 通过
--system-reserved=ephemeral-storage=...设置,驱逐阈值使用--eviction-hard=nodefs.available<10%。 - imagefs 预留: 没有直接的预留参数,但可以通过
--eviction-hard=imagefs.available<15%设置驱逐阈值,防止镜像存储写满导致拉取失败。
2.5 网络与 PID 预留
2.5.1 网络预留
Kubernetes 原生没有网络预留参数。网络资源的隔离通常依赖 CNI 插件的带宽管理(如 kubernetes.io/egress-bandwidth 注解)或节点级别的 tc/iptables 策略。在容量规划中,建议为系统进程预留 10%~20% 的节点带宽,避免 Pod 流量挤占监控与日志上报通道。
2.5.2 PID 预留
PID 预留通过 --system-reserved=pid=1000 和 --eviction-hard=pids.available<10% 控制。当节点 PID 耗尽时,新进程(包括容器进程)无法创建,可能导致节点不可用。
| 节点规格 | 系统预留 PID | kubelet 预留 PID | 驱逐阈值 | Pod 可用 PID |
|---|---|---|---|---|
| 4 vCPU / 8GB | 500 | 200 | 10% | ~3000 |
| 16 vCPU / 64GB | 1000 | 500 | 5% | ~18000 |
| 64 vCPU / 256GB | 2000 | 1000 | 5% | ~57000 |
2.6 资源预留配置示例
以下是一个生产级 kubelet 配置片段(KubeletConfiguration YAML),展示了完整的资源预留参数:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
evictionHard:
memory.available: "100Mi"
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"
pids.available: "10%"
evictionSoft:
memory.available: "300Mi"
nodefs.available: "15%"
evictionSoftGracePeriod:
memory.available: "1m30s"
nodefs.available: "2m"
kubeReserved:
cpu: "200m"
memory: "512Mi"
ephemeral-storage: "1Gi"
pid: "500"
systemReserved:
cpu: "300m"
memory: "1Gi"
ephemeral-storage: "2Gi"
pid: "1000"
kubeReservedCgroup: "/kubelet.slice"
systemReservedCgroup: "/system.slice"
enforceNodeAllocatable:
- pods
- system-reserved
- kubelet-reserved
enforceNodeAllocatable 列表中的 system-reserved 和 kubelet-reserved 需要对应的 cgroup 路径存在且正确,否则 kubelet 会拒绝启动。
2.7 资源预留对镜像拉取加速的影响
资源预留直接影响镜像拉取加速的两个关键环节:
- 磁盘预留不足 → 频繁 GC → 镜像层被删除 → 拉取延迟增加。 建议将 imagefs 驱逐阈值设为 15%~20%,并预留足够的 ephemeral-storage。
- CPU/内存预留不足 → kubelet 或容器运行时被 OOM Kill → 镜像拉取中断。 确保 kubelet 和 containerd/CRI-O 有充足的内存预留。
2.8 常见问题与避坑指南
- 预留值设置过高: 导致
Allocatable过小,Pod 调度失败。建议监控节点实际系统与 kubelet 资源占用,按峰值 + 20% 缓冲设置。 - cgroup 路径不匹配: 设置
systemReservedCgroup和kubeReservedCgroup后,必须确保 cgroup 树中存在对应路径,否则 kubelet 报错退出。 - 忽略 imagefs 驱逐阈值: 默认 imagefs 驱逐阈值可能过低(如 5%),导致镜像 GC 过于激进。建议调高至 15%~20%。
- 网络与 PID 预留被忽视: 高密度 Pod 场景下,PID 耗尽比内存耗尽更隐蔽。务必设置
pids.available驱逐阈值。
✅ 确认
--system-reserved 覆盖 sshd、监控、日志等关键进程✅ 确认
--kubelet-reserved 覆盖 kubelet + 容器运行时✅ 设置合理的 imagefs 驱逐阈值(≥15%)
✅ 设置 PID 驱逐阈值(5%~10%)
✅ 验证
enforceNodeAllocatable 包含 pods、system-reserved、kubelet-reserved✅ 监控
node_allocatable_* 指标,确保预留比例在预期范围内