k8s调度容器失败The node had condition: [DiskPressure]

现象
k8s调度pod时异常,会导致生成上百个失败的pod。
pod分配异常:
The node had condition: [DiskPressure].
The node was low on resource: ephemeral-storage. Container join-services was using 27938016Ki, which exceeds its request of 0.
节点报异常:
(combined from similar events): wanted to free 2571046912 bytes, but freed 0 bytes space with errors in image deletion: [rpc error: code = Unknown desc = Error response from daemon: conflict: unable to remove repository reference "192.168.0.2:5000/rabbitmq:3.8.6-management" (must force) - container bfb421637474 is using its referenced image 64a1f920fb0d
问题分析:
Kubernetes 调度 Pod 失败,报错信息明确指出:节点的临时存储资源不足。调度策略为重启时先增后减实例。
在运行的容器 join-services 实际已经使用了约 27.3 GiB (27938016 KiB),但它在 Pod 的资源配置 (resources) 中没有声明任何临时存储的请求值 (request = 0)。
临时存储 (ephemeral-storage): 指节点上用于存放容器日志、emptyDir 卷、容器可写层(容器运行时产生的临时文件)的磁盘空间。Pod 使用 emptyDir 类型的卷时,数据会写入节点的临时存储(默认路径为 /var/lib/kubelet/pods/<pod-id>/volumes/kubernetes.io~emptydir/<volume-name>)
请求值 (request): Kubernetes 调度器在决定将 Pod 放在哪个节点上时,会考虑 Pod 声明的资源请求量。调度器会确保节点的剩余资源(包括 CPU、内存和临时存储)能够满足 Pod 的请求量。
原因:
-
由于
join-services容器没有声明临时存储请求 (requests.ephemeral-storage: 0),调度器在调度时认为该容器不需要任何临时存储。 -
然而,该容器在运行时实际消耗了大量临时存储(约 27.3 GiB)。
-
当调度器尝试将 Pod 调度到一个节点时,它检查该节点是否有足够的资源来满足 Pod 的 请求(即 0)。节点当然满足 0 的请求。
-
但当 Kubelet 真正在该节点上启动容器时,容器需要写入大量临时文件(总计 27.3 GiB),却发现节点的可用临时存储空间不足以容纳这些实际写入,导致启动失败并报出此错误。
-
kubelet 尝试清理镜像释放 2.5GB,但目标镜像被运行中容器引用导致GC 失败,0 bytes freed,磁盘空间无法释放。大量 Pod 处于
Pending/Failed状态并持续重试,导致产生上百个失败 Pod 记录,可能触发 controller 级联创建。 -
那为什么这个实例会占用27G如此大的临时空间?因为服务里面打了大量的服务日志和上传的临时文件全在/tmp目录里面,但此目录又没有挂载出来 程序又没有清理,导致空间一直上涨。
解决方案:
-
先止血:在k8s中将容器实例缩为0,完全释放实例占用的资源和镜像,再将实例数扩起来。
-
删除异常Pod,阻止级联创建:kubectl delete掉此服务状态为Failed的所有pod。
-
后续修复:为
join-services容器明确声明一个合理的临时存储请求值,让调度器能够做出正确的调度决策。强制声明 ephemeral-storage 配额,不允许任何容器以 0 request 运行,添加
resources.requests字段。-
基于当前观察到的实际使用量 27.3 GiB,建议限制到10G就告警,防止影响其它pod。
-
你也可以考虑设置
limits来防止容器无限制地消耗临时存储,导致节点问题(可选但推荐)。
-
修改后的 YAML 示例片段:
apiVersion: apps/v1
kind: Deployment # 也可能是 StatefulSet, DaemonSet 等
metadata:
name: deployment-name
spec:
template:
spec:
containers:
- name: join-services # 你的问题容器名称
image: image:tag
resources: # 添加或修改这个 resources 块
requests:
ephemeral-storage: "5Gi" # 关键:添加临时存储请求
limits: # 可选但推荐:设置临时存储上限
ephemeral-storage: "10Gi" # 例如设置为 10Gi,比请求量稍高
# ... 其他容器配置 (如 ports, volumeMounts, env 等) ...
# ... 其他 Pod 配置 (如 volumes, initContainers 等) ...
额外建议:
-
清理空间: 程序定期清理日志和临时文件。
-
挂载:将占用的文件挂载到宿主机空间,定期用脚本清理。定期清理策略编写脚本定期清理日志和 emptyDir 数据,或使用 Kubernetes 的
TTLController自动清理过期资源。 -
避免滥用 emptyDir若
emptyDir数据量大,建议改用持久化存储(如 PVC)或优化数据写入逻辑。
监控与告警
监控 ephmeral-storage 使用使用 Prometheus + Grafana 监控节点的 ephemeral-storage 使用情况,设置阈值告警(例如 80% 时触发警告)。
公众号【一个码农的日常】 技术群:319931204 1号群: 437802986 2号群: 340250479
出处:http://zhangs1986.cnblogs.com/
码云:https://gitee.com/huanzui
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号