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 → 调度阻塞。
kubectl get nodes -o wide 查看 STATUS 列,再通过 kubectl describe node <node> 查看 Conditions 段。如果发现 MemoryPressure 或 DiskPressure,应检查 kubelet 的预留配置和驱逐阈值。
3.5 节点资源管理对调度决策的完整影响链路
下图展示了从节点硬件上报到调度器最终决策的完整数据流:
3.6 风险控制与最佳实践
基于上述分析,在节点资源管理层面应建立以下风险控制策略:
- 统一预留基线:为所有节点设置一致的
--system-reserved和--kube-reserved参数,避免因节点规格不同导致 Allocatable 差异过大。 - 驱逐阈值调优:根据节点内存规格设置合理的
--eviction-hard,建议保留 5%~10% 的内存作为安全缓冲。 - 节点状态监控告警:对
MemoryPressure、DiskPressure、PIDPressure设置 Prometheus 告警,在节点进入NoSchedule前提前干预。 - 调度器配置校验:在集群部署时使用
kubeadm config print init-defaults检查 kubelet 默认预留值,确保与节点实际负载匹配。 - 定期审计:通过
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 批量检查节点就绪状态。