3. 节点资源管理:节点容量、可分配资源、资源预留、节点状态对调度的影响

节点资源管理是 Kubernetes 调度决策的底层基础。调度器在将 Pod 绑定到节点之前,必须精确评估节点的真实承载能力。如果只关注节点总容量而忽略预留与状态,极易引发资源超分、Pod 驱逐甚至节点级故障。本节从四个核心维度展开:节点容量(Capacity)、可分配资源(Allocatable)、资源预留(Reservation)以及节点状态(Node Condition),并分析它们如何联动影响调度结果。

3.1 节点容量与可分配资源模型

每个节点在注册到集群时,kubelet 会上报其硬件资源总量,即 Node.Status.Capacity。然而,操作系统、kubelet 本身、容器运行时以及系统守护进程(如 sshd、systemd-journald)会占用一部分资源,这部分资源不能被 Pod 使用。因此,Kubernetes 定义了 Node.Status.Allocatable,其计算公式为:

Allocatable = Capacity - Reserved - EvictionThreshold

调度器在预选阶段直接读取 Allocatable 而非 Capacity,确保 Pod 请求不会侵占系统预留资源。下表对比了两种资源视图的关键差异:

属性 Capacity(容量) Allocatable(可分配)
数据来源 kubelet 上报的硬件总量 Capacity 减去预留与驱逐阈值
调度依据 仅用于信息展示 调度器预选与优选的核心输入
包含系统开销 不包含 已扣除 OS、kubelet、运行时开销
典型场景 集群容量规划、成本核算 Pod 调度、资源配额、HPA 计算
实践要点:使用 kubectl describe node 查看 Capacity 与 Allocatable 的差异。如果发现 Allocatable 远低于 Capacity(例如 CPU 差异超过 10%),应检查 kubelet 的 --system-reserved 和 --kube-reserved 配置是否合理。

3.2 资源预留机制:System Reserved 与 Kube Reserved

Kubernetes 通过 kubelet 启动参数提供两层资源预留:

  • System Reserved:为操作系统守护进程(sshd、systemd、监控代理等)预留的资源。通过 --system-reserved=cpu=500m,memory=1Gi 配置。
  • Kube Reserved:为 Kubernetes 组件(kubelet、容器运行时、kube-proxy)预留的资源。通过 --kube-reserved=cpu=200m,memory=512Mi 配置。
  • Eviction Threshold:kubelet 在资源耗尽前触发 Pod 驱逐的硬性阈值,例如 --eviction-hard=memory.available<100Mi。

这三部分预留共同决定了 Allocatable 的最终值。如果预留配置过大,节点利用率会偏低;配置过小,则系统组件可能因资源竞争导致节点不稳定。

常见陷阱:许多集群未配置 --system-reserved 和 --kube-reserved,导致 kubelet 默认使用 Capacity 作为 Allocatable。此时如果节点上运行了监控 DaemonSet 或日志采集器,实际可用资源会低于调度器预期,引发资源竞争和 Pod 驱逐。

3.3 节点状态对调度的影响

节点状态由一组 NodeCondition 表示,调度器在预选阶段会检查这些条件。只有所有条件满足调度要求时,节点才会进入候选列表。核心条件包括:

条件名称 正常状态 异常影响 调度行为
Ready True False 或 Unknown 节点被标记为 NoSchedule,新 Pod 不会调度
DiskPressure False True 节点被标记为 NoSchedule,防止新 Pod 加剧磁盘压力
MemoryPressure False True 节点被标记为 NoSchedule,但已有 Pod 不受影响
PIDPressure False True 节点被标记为 NoSchedule,避免 PID 耗尽
NetworkUnavailable False True 节点被标记为 NoSchedule,网络插件未就绪

调度器通过 node.Status.Conditions 与 node.Spec.Taints 协同工作。即使节点状态正常,如果存在 NoSchedule 或 NoExecute 污点,调度器也会跳过该节点,除非 Pod 有对应的容忍度。

3.4 资源预留与节点状态的联动关系

资源预留配置不当会直接触发节点状态异常。例如:

  • MemoryPressure 触发链:--eviction-hard 阈值设置过高 → 节点内存利用率超过阈值 → kubelet 设置 MemoryPressure=True → 调度器停止调度新 Pod → 已有 Pod 可能被驱逐。
  • DiskPressure 触发链:--system-reserved 未包含日志目录 → 系统日志占满根分区 → kubelet 设置 DiskPressure=True → 节点进入 NoSchedule 状态。
  • PIDPressure 触发链:--pod-max-pids 默认值 4096 在密集 Pod 场景下容易耗尽 → 节点设置 PIDPressure=True → 调度阻塞。
排查建议:当集群出现大量 Pending Pod 时,优先检查节点状态:kubectl get nodes -o wide 查看 STATUS 列,再通过 kubectl describe node <node> 查看 Conditions 段。如果发现 MemoryPressure 或 DiskPressure,应检查 kubelet 的预留配置和驱逐阈值。

3.5 节点资源管理对调度决策的完整影响链路

下图展示了从节点硬件上报到调度器最终决策的完整数据流:

节点资源管理对调度决策的影响链路 节点资源管理 → 调度决策影响链路 节点硬件资源(CPU / Memory / Disk / PID) kubelet 上报 Node.Status.Capacity 预留扣除:Allocatable = Capacity - Reserved - EvictionThreshold ├── --system-reserved(OS 守护进程) ├── --kube-reserved(K8s 组件) └── --eviction-hard(驱逐阈值) 节点状态评估(Node Conditions) Ready / MemoryPressure / DiskPressure / PIDPressure / NetworkUnavailable 调度器决策:预选(Allocatable + Conditions)→ 优选 任一条件异常 → NoSchedule 预留不足 → 节点状态恶化

3.6 风险控制与最佳实践

基于上述分析,在节点资源管理层面应建立以下风险控制策略:

  1. 统一预留基线:为所有节点设置一致的 --system-reserved 和 --kube-reserved 参数,避免因节点规格不同导致 Allocatable 差异过大。
  2. 驱逐阈值调优:根据节点内存规格设置合理的 --eviction-hard,建议保留 5%~10% 的内存作为安全缓冲。
  3. 节点状态监控告警:对 MemoryPressure、DiskPressure、PIDPressure 设置 Prometheus 告警,在节点进入 NoSchedule 前提前干预。
  4. 调度器配置校验:在集群部署时使用 kubeadm config print init-defaults 检查 kubelet 默认预留值,确保与节点实际负载匹配。
  5. 定期审计:通过 kubectl get nodes -o json | jq '.items[].status.allocatable' 定期审计集群 Allocatable 分布,发现异常节点及时修复。
快速验证命令:
kubectl describe node <node> | grep -A5 "Allocatable" 查看节点可分配资源;
kubectl get nodes -o custom-columns=NAME:.metadata.name,STATUS:.status.conditions[?(@.type=="Ready")].status 批量检查节点就绪状态。