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 占用的空间)。