K8s Master 节点磁盘空间不足导致磁盘使用率过高的排查与长效治理
2026-08-11 00:53:03 # Kubernetes

问题现象与背景原因

Master 节点磁盘使用率持续升高直至打满,是常见的”慢性病”。典型现象:

  • 节点状态出现 DiskPressure 条件,kubelet 触发驱逐(Eviction),把部分甚至全部 Pod 赶走;
  • 控制面组件异常:etcd 因磁盘写不进去而心跳超时、apiserver 报 write: no space left on device
  • 登录节点发现 //var 分区 100% 使用率,df -h 飘红。

根因通常不是单一文件,而是几类”空间黑洞”叠加:

  1. 容器日志无轮转:docker 默认 json-file 驱动不限制大小,应用疯狂打日志会把 /var/lib/docker/containers/var/log/containers 撑爆;
  2. 镜像 / 废弃层堆积:长期不清理,无用镜像、悬空层占用数 GB;
  3. etcd 数据膨胀或碎片:频繁写入导致 DB 文件变大;
  4. 系统日志 /var/log 爆满journald、内核日志未轮转;
  5. kubelet 残留:已删除 Pod 的空目录、孤儿卷未回收。

排查过程(思路与定位方法)

先定位”哪块盘、被谁吃满”:

1
2
3
4
5
6
7
8
9
10
# 1. 看整体磁盘占用
df -h

# 2. 逐层下钻,找出大户(从 / 开始)
sudo du -sh /* 2>/dev/null | sort -h | tail -20
sudo du -sh /var/* 2>/dev/null | sort -h | tail -20
sudo du -sh /var/lib/docker/* 2>/dev/null | sort -h | tail
sudo du -sh /var/lib/containerd/* 2>/dev/null | sort -h | tail
sudo du -sh /var/lib/etcd/* 2>/dev/null | sort -h | tail
sudo du -sh /var/log/* 2>/dev/null | sort -h | tail

确认是否是日志问题:

1
2
3
4
5
6
# docker 容器日志体积
sudo du -sh /var/lib/docker/containers/* 2>/dev/null | sort -h | tail
# journald 占用
sudo journalctl --disk-usage
# 大文件 top10(大于 100M)
sudo find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null | sort -k5 -h | tail -10

确认 etcd 数据是否过大:

1
2
3
4
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key endpoint status -w table
# 关注 DB SIZE 字段(正常几百 MB,异常可达数 GB)

解决方法(清理策略 + 长效方案)

一、紧急清理(止血)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 清理未使用的镜像、容器、网络(docker)
sudo docker system prune -a --volumes
# containerd 等效
sudo crictl rmi --prune

# 2. 截断 / 清理超大容器日志(不要直接 rm,先 truncate)
sudo truncate -s 0 /var/lib/docker/containers/*/*-json.log

# 3. 清理 journald 旧日志,保留最近 7 天
sudo journalctl --vacuum-time=7d
# 或限制总大小
sudo journalctl --vacuum-size=500M

# 4. 清理 kubelet 残留(谨慎,确认 Pod 已删除)
kubectl get pv | grep Released # 确认后可删除孤儿卷

若磁盘已 100% 导致节点 NotReady,先 kubectl drain 腾挪 Pod,再清理:

1
2
3
kubectl drain <master节点> --ignore-daemonsets --delete-emptydir-data --force
# 清理完成后
kubectl uncordon <master节点>

二、etcd 碎片整理(如 DB 过大)

1
2
3
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key defrag

三、长效架构方案(避免复发)

  1. 组件独立磁盘:etcd 独占一块高性能 SSD,docker/containerd 数据目录挂独立盘,与系统盘分离;
  2. 日志轮转 + 大小限制:docker 守护进程配置 json-filemax-size / max-file
1
2
3
4
{
"log-driver": "json-file",
"log-opts": { "max-size": "100m", "max-file": "3" }
}

containerd 在 /etc/containerd/config.toml 配置 MaxLogFileSize 限制单日志文件大小;
3. journald 限大小/etc/systemd/journald.confSystemMaxUse=500M
4. 自动清理 cron:定期 docker system prune + 日志截断脚本;
5. 监控告警:node-exporter + 磁盘使用率告警,在 DiskPressure 之前介入;
6. 考虑托管控制面 / 外部 etcd:把 etcd 交给云厂商或独立部署,降低自建 Master 的磁盘风险。

操作命令速查

1
2
3
4
5
6
df -h                                      # 看磁盘占用
sudo du -sh /var/lib/docker/* | sort -h # 找 docker 大户
sudo docker system prune -a --volumes # 清理无用镜像/卷
sudo journalctl --vacuum-time=7d # 清理 journald
sudo truncate -s 0 /var/lib/docker/containers/*/*-json.log # 截断日志
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data --force # 紧急腾挪

经验总结

  • 磁盘满不是”删个文件”就完事,要分清是日志、镜像还是 etcd,对症清理。
  • 治本靠架构:独立盘 + 日志轮转 + 自动清理 + 监控告警,四件套缺一不可。
  • 不要直接 rm -rf 正在写入的日志文件,用 truncate -s 0 更安全,避免句柄泄漏。
  • Master 磁盘问题会直接拖垮控制面,优先级高于普通节点,应纳入最高频巡检项。