Tip

当 K8s 节点磁盘空间不足时,Pod 虽然显示 Running,但实际已经“瘫痪”或频繁重启。这是因为 K8s 的 节点压力驱逐(Node Pressure Eviction) 机制会介入,且容器运行时(如 containerd)在写文件时也会报错。

故障现象

  • Pod 状态异常Pending(调度失败)、CrashLoopBackOff(启动后立即退出)、Evicted(被驱逐)。

  • 事件告警:执行 kubectl describe pod 会看到 Failed to create pod sandbox: no space left on device 或 Node has disk pressure

  • 节点状态kubectl describe node 会显示 DiskPressure 状态为 True

  • 业务报错:容器内应用写日志时报 No space left on device,或数据库报 Read-only file system(磁盘写失败后内核可能将分区挂载为只读)。

问题处理

情况A: 容器运行时目录(/var/lib/containerd)占满

常见原因:未清理的旧镜像、退出的容器文件、容器写的大量日志(未配置轮转)。

  • 紧急恢复(释放空间)

    # 1. 清理未使用的镜像和容器(推荐,安全)
    docker system prune -f      # 若用 Docker
    crictl rmi --prune          # 若用 containerd(K8s 1.24+ 默认)
    # 2. 如果空间依然紧张,清理所有停止的容器(谨慎)
    docker container prune -f
  • 根治配置:修改 kubelet 的 imageGCHighThresholdPercent(默认 85%),当磁盘使用率达到该值自动回收旧镜像。

  • 日志治理:在 Pod 的 spec.containers 中添加 volumeMounts 挂载 EmptyDir,并配置日志轮转(如 logrotate),或在容器启动命令中重定向输出到 /dev/null

恢复状况(自动恢复)

Kubelet 进程本身没有卡死的情况

  • 表现:节点上的 DiskPressure 条件会在几分钟内(默认 --eviction-pressure-transition-period 为 5 分钟)变为 False

  • 自动动作:Kubelet 会移除节点的污点(NoSchedule),调度器会自动允许新的 Pod 调度上来。

情况B: 系统根目录(/)占满

原因:宿主机系统日志(/var/log)、kubelet 日志、或挂载点被误写(如将数据写到了未挂载盘的目录)。

  • 紧急处理
    # 找到大文件目录(耗时可能较长)
    du -sh /* 2>/dev/null | sort -rh | head -10
     
    # 常见清理点:清理系统日志
    journalctl --vacuum-size=500M   # 仅保留 500MB 系统日志
  • 预防:确保所有写大量数据的目录(如日志、持久化存储)都挂载了独立的数据盘,并通过 --root-dir 参数将 kubelet 目录指向数据盘。

恢复状况(需手动恢复)

Tip

容器运行时假死:如果磁盘曾经 100%,containerd/docker 的 socket(套接字)可能因写入失败而挂起。即使清理了空间,kubectl get nodes 可能依然显示 NotReady

  • 手动操作:必须重启容器运行时(systemctl restart containerd)和 Kubelet(systemctl restart kubelet),节点状态才会恢复。

情况C: 临时存储(Ephemeral Storage)耗尽

场景:Pod 使用了 emptyDir 或容器可写层(OverlayFS)写入了大量缓存,触发 K8s 的 本地临时存储限制(默认 10% 节点容量)。

  • 现象:Pod 被驱逐,事件显示 Pod ephemeral local storage usage exceeds the total limit

  • 紧急扩容

    # 修改 Pod 资源限制(需重建 Pod)
    # 在 spec.containers.resources 中增加:
    limits:
      ephemeral-storage: "2Gi"
  • 临时救命:如果业务无法重建,可进入容器 du -sh /cache/* 删除无用临时文件,并重启容器(删除文件后需重启才能释放 OverlayFS 占用的空间)。