Kubernetes 节点资源预留
Kubernetes 节点资源预留完全指南
为什么需要节点资源预留
Kubernetes 节点上除了运行业务 Pod,还运行着众多系统守护进程(如 sshd、systemd-journald)以及 Kubernetes 自身的组件(如 kubelet、container runtime)。如果不做任何限制,当业务 Pod 申请过多资源时,这些关键进程可能因资源不足而频繁中断,导致节点进入 Not Ready 状态,甚至整台机器失去响应。
节点资源预留的本质是 从节点总容量中划出一部分固定的资源(CPU、内存、存储)给系统和 Kubernetes 组件专用,Pod 最多只能使用剩余的资源。这能有效避免调度器无节制地将 Pod 调度到节点上,从而保护节点稳定性。
节点总资源模型
在配置预留前,先理解节点上不同资源的划分层次:
- Node Capacity:节点的物理/虚拟总核数和总内存,由
kubectl describe node中的Capacity字段展示。 - Node Allocatable:节点上真正可供 Pod 使用的资源总量,即
Allocatable字段。 - 预留资源:Capacity - Allocatable 的差值,由以下三部分组成:
- System Reserved:操作系统级别的守护进程保留资源。
- Kube Reserved:Kubernetes 系统组件(
kubelet、container runtime、kube-proxy 等)保留资源。 - Eviction Thresholds:kubelet 用于触发 Pod 驱逐的内存阈值。
三者关系如下:
Allocatable = Node Capacity - System Reserved - Kube Reserved - Eviction Threshold
只有当 Pod 的 requests 总和 ≤ Node Allocatable,调度器才会把新的 Pod 分配到该节点。
配置资源预留(kubelet 参数指南)
资源预留通过 kubelet 启动参数配置,最终写入 /var/lib/kubelet/config.yaml 或启动命令行。常用参数有:
--system-reserved
为操作系统级守护进程保留资源,如 systemd、journald、containerd(如果不属于 Kubernetes 组件)等,格式为 resource=value 的逗号分隔值,例如:
--system-reserved=cpu=500m,memory=1Gi,ephemeral-storage=1Gi
注意:ephemeral-storage 是临时存储,自 1.18 版本开始稳定支持。如果不想预留存储,可省略。
--kube-reserved
为 Kubernetes 相关组件保留资源,包括 kubelet、container runtime(如 containerd)、CNI 插件、kube-proxy 等,例如:
--kube-reserved=cpu=1000m,memory=2Gi,ephemeral-storage=2Gi
--eviction-hard
定义内存和磁盘的硬驱逐阈值,当可用资源低于该值时,kubelet 会立即驱逐 Pod。典型配置:
--eviction-hard=memory.available<1Gi,nodefs.available<10%,imagefs.available<15%
这里 memory.available 的计算公式为:
memory.available = Node Capacity.memory - system-reserved.memory - kube-reserved.memory - Sum(Pod内存usage)
也就是说,eviction threshold 取值是从 Allocatable 中再切掉一部分内存,形成一个“安全缓冲”。如果把 --eviction-hard 中的内存阈值算作预留的一部分,那么 Allocatable 会进一步缩小。
实战示例:配置一台 8C 16G 节点的预留
假设节点物理资源为 8 核 CPU、16 GiB 内存,我们希望预留合理的值,同时留给 Pod 尽可能多的资源。
1. 确定各组件资源消耗
通过监控工具(如 top、systemd-cgtop)或压力测试估算:
- 操作系统守护进程大约需要 200m CPU、0.5 GiB 内存。
- Kube 组件(kubelet 150m、containerd 300m、kube-proxy 100m + 网络插件)合计约 600m CPU、1 GiB 内存。
- 为安全考虑,再额外预留一个内存驱逐阈值 1 GiB。
2. 创建 kubelet 配置文件
编辑 /var/lib/kubelet/config.yaml(若使用 kubeadm 安装,通常文件已存在,直接修改即可):
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
enforceNodeAllocatable:
- pods
systemReserved:
cpu: "200m"
memory: "512Mi"
kubeReserved:
cpu: "600m"
memory: "1Gi"
evictionHard:
memory.available: "1Gi"
nodefs.available: "10%"
imagefs.available: "15%"
如果使用命令行参数,则传递:
--system-reserved=cpu=200m,memory=512Mi
--kube-reserved=cpu=600m,memory=1Gi
--eviction-hard=memory.available<1Gi,nodefs.available<10%,imagefs.available<15%
3. 重启 kubelet
systemctl restart kubelet
systemctl status kubelet
4. 验证 Allocatable 值
kubectl describe node <node-name> | grep -A 5 Allocatable
预期输出类似:
Allocatable:
cpu: 7200m # 8000 - 200 - 600
memory: 14008384Ki # 16Gi - 512Mi - 1Gi - 1Gi(eviction) ≈ 13.5 GiB
此时 Pod 的总 requests 不能超过 7.2 核和约 13.5 GiB 内存,确保了系统和 Kubernetes 组件拥有充足的资源。
最佳实践与注意事项
- 从实际出发,逐步调优:初始预留值可参考社区推荐(如 GKE 默认值为 CPU 60m + 额外每核 1.4m,内存 2.15 GiB + 额外每 GiB 5 Mi),但最好根据自身集群的监控数据调整。
- 不要过度预留:过度预留会浪费节点资源,增加成本。尽量通过长期观察
node_memory_MemAvailable_bytes、node_cpu_seconds_total等指标确定合理值。 - 临时存储预留:如果节点上日志、容器层等消耗大量磁盘,务必配置
ephemeral-storage的预留和驱逐阈值,否则磁盘写满会导致整个节点不可用。 - 使用
--reserved-cpus实现 CPU 独占:在需要极致性能的场景,可以通过--reserved-cpus指定预留的 CPU 核号(需搭配 CPU Manager 的 static 策略),将这些核完全从调度池中移除,系统进程和 Kubernetes 组件将运行在这些特定核上。 - 版本差异:确保 kubelet 版本 ≥ 1.18(
ephemeral-storage支持更完善),且驱逐阈值的计算在 v1.22+ 略有变化,注意查阅对应版本文档。 - 验证节点状态:配置完成后,检查 kubelet 日志
journalctl -u kubelet -f,确保没有因预留配置错误导致启动失败。
常见问题排查
节点 Allocatable 没有变化?
- 确认 kubelet 是否正确重启,检查配置文件路径是否正确。
- 如果使用
kubeadm部署,修改/var/lib/kubelet/config.yaml后需执行systemctl restart kubelet;某些版本可能还需更新/etc/default/kubelet中的参数引用。
Pod 因资源预留被驱逐,如何查看驱逐事件?
kubectl describe node <node-name> | grep -i 'eviction'
或者直接查看 kubelet 日志中 eviction 相关记录。
如何临时禁用资源预留?
将 systemReserved 和 kubeReserved 设置为空或全部设为 0,并移除 evictionHard(不推荐生产环境使用)。
总结
节点资源预留是 Kubernetes 集群稳定性的基石之一。通过合理配置 --system-reserved、--kube-reserved 和 --eviction-hard,你可以清晰划分系统、Kubernetes 和业务 Pod 之间的资源界限,避免“挤占”导致的雪崩效应。记住:Allocatable 才是调度器看到的可用资源,在规划 Pod 资源请求时,务必着眼于此数值,而非简单的物理资源总量。
想要深入了解更多调度、资源管理话题,欢迎继续查看我们的其他免费教程。