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

image

现象

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目录里面,但此目录又没有挂载出来 程序又没有清理,导致空间一直上涨。

解决方案:

  1. 先止血:在k8s中将容器实例缩为0,完全释放实例占用的资源和镜像,再将实例数扩起来。

  2. 删除异常Pod,阻止级联创建:kubectl delete掉此服务状态为Failed的所有pod。

  3. 后续修复:为 join-services 容器明确声明一个合理的临时存储请求值,让调度器能够做出正确的调度决策。

    强制声明 ephemeral-storage 配额,不允许任何容器以 0 request 运行,添加 resources.requests 字段。

    1. 基于当前观察到的实际使用量 27.3 GiB,建议限制到10G就告警,防止影响其它pod。

    2. 你也可以考虑设置 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 自动清理过期资源。

  • 避免滥用 emptyDiremptyDir 数据量大,建议改用持久化存储(如 PVC)或优化数据写入逻辑。

监控与告警

监控 ephmeral-storage 使用使用 Prometheus + Grafana 监控节点的 ephemeral-storage 使用情况,设置阈值告警(例如 80% 时触发警告)。

posted @ 2026-07-23 08:36  欢醉  阅读(43)  评论(0)    收藏  举报