HDFS Non DFS Used 磁盘告警排查:从原理到清理预防实战

发布时间:2026/10/16 7:26:30
HDFS Non DFS Used 磁盘告警排查:从原理到清理预防实战 1. 一次磁盘告警引发的排查Non DFS Used 到底是什么凌晨两点监控平台弹出一条告警某集群 DataNode 节点磁盘使用率突破 90% 阈值。按照常规思路我第一反应是数据写入量激增于是登录节点执行df -h查看磁盘占用发现数据盘确实快满了。但接下来的一幕让我有点意外——打开 HDFS 的 Web UI看到 DFS Used 只占了不到 60%剩余空间却显示为 Non DFS Used 占了大头。这个 Non DFS Used 是 HDFS 运维里一个非常经典但又容易被忽视的概念。简单说它指的是 DataNode 数据目录所在磁盘上不属于 HDFS 管理范围的那部分空间占用。HDFS 自己算账的逻辑是这样的磁盘总容量减去 DFS UsedHDFS 实际存储的数据块再减去 Reserved系统保留空间剩下的就是 Non DFS Used。公式写出来就是Non DFS Used 磁盘总容量 - DFS Used - Reserved Space - 剩余可用空间换句话说只要磁盘上存在任何 HDFS 之外的文件比如日志、临时文件、被删除但句柄未释放的文件、甚至是其他程序写入的数据都会被归入 Non DFS Used。这个指标本身不是错误但它一旦异常膨胀就意味着 DataNode 可用的写入空间被蚕食严重时直接导致写入失败、数据块副本丢失甚至节点被踢出集群。这篇文章适合所有负责 HDFS 集群运维的工程师、大数据平台开发者以及正在被磁盘满了但 HDFS 显示没满这类问题困扰的同行。我会把这次排查的完整过程拆开讲清楚Non DFS Used 的计算原理、常见成因、排查手段、清理方案以及后续如何建立预防机制。内容基于真实运维场景整理涉及的命令和参数都可以直接拿去用。2. Non DFS Used 的计算逻辑与常见成因拆解2.1 HDFS 是如何统计这块空间的要理解 Non DFS Used得先搞清楚 DataNode 上报磁盘信息的机制。DataNode 定期向 NameNode 发送心跳时会附带一份StorageReport里面包含capacity、dfsUsed、remaining、nonDfsUsed等字段。NameNode 的 Web UI 和dfsadmin report命令展示的数据就来源于此。关键在于nonDfsUsed的计算方式。在较新的 Hadoop 版本中DataNode 通过DF命令或等效的系统调用获取整个磁盘分区的使用情况然后用分区总容量减去 HDFS 数据目录实际占用的字节数得到的就是 Non DFS Used。这里有个容易踩的坑如果多个数据目录共享同一个磁盘分区HDFS 会把整个分区的非 HDFS 占用都算进来而不是只算某个目录。举个例子假设/data分区挂载了 1TB 磁盘HDFS 的dfs.datanode.data.dir配置为/data/dfs/dn同时这个分区上还跑着 YARN 的本地临时目录/data/yarn/local。那么 YARN 产生的所有临时文件、容器日志、Shuffle 数据全部会被计入 Non DFS Used。这就是为什么很多集群明明 HDFS 数据不多Non DFS Used 却高得吓人。2.2 六种最常见的空间占用来源结合我这些年处理过的案例Non DFS Used 异常膨胀的原因基本逃不出下面这几类成因类别典型表现排查难度日志文件堆积DataNode/NodeManager 日志未轮转单文件达数十 GB低被删除但未释放的文件lsof显示 deleted 状态进程仍持有句柄中YARN 本地临时目录容器工作目录、Shuffle 数据残留低其他服务共用磁盘同一分区部署了非 HDFS 组件低文件系统保留空间ext4 默认 5% 保留给 root低快照或副本残留存储快照、回收站未清理中其中被删除但未释放的文件是最隐蔽的一类。Linux 的文件删除机制是只有当所有持有该文件句柄的进程都关闭文件后磁盘空间才会真正释放。如果某个进程比如一个卡死的 DataNode 或外部脚本一直持有大文件的句柄即使rm删除了文件df依然显示空间被占用而du却统计不到。这种幽灵占用经常让人抓狂。2.3 为什么这个指标值得单独关注很多人觉得 Non DFS Used 只是个参考值不影响 HDFS 运行。这个认知是危险的。DataNode 在决定是否接受新数据块写入时会检查可用空间是否低于配置的阈值dfs.datanode.du.reserved。如果 Non DFS Used 吃掉了大量空间实际可用于 HDFS 写入的空间就会缩水触发DiskOutOfSpaceException导致写入失败。更严重的情况是当 Non DFS Used 持续增长DataNode 可能因为磁盘满而无法写入新的数据块副本NameNode 检测到副本数不足后会触发副本复制但其他节点如果也有同样问题就会形成连锁反应。我见过一次因为日志把磁盘写满导致整个机架的数据块副本同时丢失的案例恢复起来相当痛苦。3. 实战排查从告警到定位真凶的完整过程3.1 第一步确认 Non DFS Used 的真实数值登录问题节点后不要急着删文件。先用几个命令交叉验证把账算清楚# 查看磁盘整体使用情况 df -h /data # 查看 HDFS 数据目录实际占用 du -sh /data/dfs/dn # 通过 hdfs 命令查看集群视角的统计 hdfs dfsadmin -report | grep -A 10 DataNodedf显示的是文件系统层面的占用du显示的是目录实际占用。如果两者差距巨大基本可以确定存在被删除但未释放的文件。这时候用lsof找出持有句柄的进程# 查找所有 deleted 状态但仍被占用的文件 lsof | grep deleted | grep /data # 按占用大小排序快速定位大文件 lsof | grep deleted | awk {print $7, $9} | sort -rn | head -20这一步的输出会告诉你哪个进程、哪个文件在占着茅坑不拉屎。常见的是 DataNode 自身的日志文件被外部工具轮转后进程没有重新打开新文件导致旧文件句柄一直挂着。3.2 第二步逐层排查目录占用如果df和du的数值基本吻合说明空间确实被实际文件占用了那就需要逐层定位。我的习惯是从分区根目录开始用du按层级下钻# 查看一级目录占用按大小排序 du -h --max-depth1 /data | sort -rh # 对占用最大的目录继续下钻 du -h --max-depth1 /data/yarn | sort -rh这次排查中我发现/data/yarn/local目录占了将近 200GB。进一步查看发现里面堆满了usercache下的容器工作目录很多是几个月前失败的作业残留。YARN 的本地目录清理依赖yarn.nodemanager.localizer.cache.cleanup.interval-ms和yarn.nodemanager.localizer.cache.target-size-mb两个参数如果配置不当或者 NodeManager 长时间未重启残留就会越积越多。3.3 第三步检查文件系统保留空间还有一个容易被忽略的点是文件系统的保留块。ext4 默认会保留 5% 的空间给 root 用户这部分空间在df里算作已使用但普通进程无法写入。对于一块 4TB 的盘5% 就是 200GB相当可观。# 查看文件系统保留比例 tune2fs -l /dev/sdX | grep -i reserved # 调整保留比例生产环境谨慎操作建议保留 1%-2% tune2fs -m 1 /dev/sdX对于专门用于 HDFS 的数据盘把保留比例降到 1% 是常见做法但要注意这会影响系统在磁盘满时的应急能力需要权衡。3.4 第四步确认 HDFS 自身的 Reserved 配置别忘了 HDFS 自己也有一层保留空间配置dfs.datanode.du.reserved默认值是 10GB 左右。这个值会从可用空间中扣除不参与 HDFS 写入。如果这个值设置得过大也会让 Non DFS Used 看起来偏高。检查hdfs-site.xml中的配置property namedfs.datanode.du.reserved/name value10737418240/value !-- 10GB -- /property这个值的设定要根据磁盘容量和业务写入速度来定。太小了容易写满太大了浪费空间。我的经验是对于 4TB 以上的盘保留 20-30GB 比较稳妥给系统留出应急缓冲。4. 清理方案与操作避坑指南4.1 安全清理 YARN 本地目录确认是 YARN 残留后不要直接rm -rf整个目录那样可能误删正在运行的容器数据。正确做法是先停止 NodeManager或者通过 YARN 提供的清理机制处理# 优雅方式重启 NodeManager触发自动清理 yarn-daemon.sh stop nodemanager yarn-daemon.sh start nodemanager # 手动清理时只删除超过一定天数的目录 find /data/yarn/local/usercache -type d -mtime 7 -exec rm -rf {} \;注意手动清理前务必确认没有正在运行的作业否则会导致容器失败。建议在业务低峰期操作并提前通知相关团队。4.2 处理被删除但未释放的文件对于lsof找到的 deleted 文件处理方式取决于持有句柄的进程如果是 DataNode 自身持有最安全的做法是重启 DataNode。重启前先执行hdfs dfsadmin -refreshNodes确认节点状态然后优雅停止。如果是外部脚本或工具持有先尝试正常终止该进程。如果进程卡死无法终止再考虑强制 kill但要评估对业务的影响。极端情况下可以用 /proc/PID/fd/FD的方式清空文件内容但这只适用于普通文件且需要 root 权限。# 查看进程持有的具体文件描述符 ls -l /proc/PID/fd | grep deleted # 清空文件内容谨慎使用 : /proc/PID/fd/FD_NUMBER4.3 日志轮转配置优化日志堆积是最常见的成因也是最容易预防的。检查 DataNode 和 NodeManager 的日志配置确保启用了按大小和时间的轮转!-- log4j.properties 关键配置 -- log4j.appender.RFA.MaxFileSize256MB log4j.appender.RFA.MaxBackupIndex10同时配合系统的logrotate设置合理的保留天数和压缩策略。我一般会把 HDFS 相关日志的保留周期设为 7-14 天超过的自动压缩归档到冷存储。这样既能满足排查需求又不会让磁盘被日志撑爆。4.4 清理操作的检查清单每次清理前我都会过一遍这个清单避免手抖确认当前没有正在运行的写入作业或已通知相关方确认要删除的目录不属于 HDFS 数据目录确认删除操作不会影响其他共用该磁盘的服务删除前记录当前磁盘使用率便于对比效果删除后立即用df -h和 HDFS UI 确认 Non DFS Used 是否下降观察 24 小时确认没有异常增长5. 预防机制让 Non DFS Used 不再失控5.1 监控指标的精细化配置光靠磁盘使用率告警是不够的需要把 Non DFS Used 单独拎出来监控。在监控系统中添加如下指标采集nonDfsUsed绝对值及其占磁盘总容量的比例nonDfsUsed的日环比增长率DFS Used 与 Non DFS Used 的比值变化趋势我一般会设置两级阈值Non DFS Used 占比超过 20% 触发警告超过 30% 触发严重告警。这样能在问题恶化前就介入处理。5.2 磁盘规划的最佳实践从架构层面最有效的预防手段是磁盘隔离。不要让 HDFS 数据目录和其他服务共用同一个分区。理想情况下HDFS 数据盘单独挂载只放dfs.datanode.data.dirYARN 本地目录放在独立的盘或分区日志目录单独挂载避免日志写满影响数据盘如果资源有限无法完全隔离至少要在dfs.datanode.du.reserved中预留足够的缓冲空间并严格控制共用服务的写入量。5.3 定期巡检脚本我写了一个简单的巡检脚本每周跑一次输出各节点的 Non DFS Used 排名和异常目录#!/bin/bash # 巡检 Non DFS Used 异常节点 for node in $(cat datanode_list.txt); do echo $node ssh $node df -h /data | tail -1; du -h --max-depth1 /data 2/dev/null | sort -rh | head -5 done这个脚本能快速发现哪些节点的非 HDFS 占用在增长以及增长来自哪个目录。配合定时任务可以做到早发现早处理。5.4 版本升级带来的变化值得一提的是Hadoop 3.x 版本对 Non DFS Used 的统计做了一些优化引入了更精确的nonDfsUsed计算方式减少了因多目录共享分区导致的误报。如果还在用 2.x 版本升级到 3.x 能省不少心。不过升级前要做好兼容性测试特别是涉及存储格式和 API 变更的部分。6. 几个真实踩坑案例的复盘6.1 案例一日志轮转脚本的副作用某次集群扩容后新节点的 Non DFS Used 在三天内从 5% 涨到 40%。排查发现是运维团队部署的日志轮转脚本有 bug轮转后没有通知 DataNode 重新打开日志文件导致旧日志句柄一直被持有。lsof显示有十几个 deleted 状态的日志文件加起来超过 300GB。重启 DataNode 后空间立即释放。这个案例的教训是任何涉及文件句柄的操作都要考虑对运行中进程的影响。6.2 案例二YARN 缓存配置的坑另一个集群的 Non DFS Used 缓慢增长每周增加约 50GB。查下来是 YARN 的本地化缓存清理间隔设置得太长默认 10 分钟但被改成了 24 小时加上target-size-mb设置过大导致缓存文件长期不清理。调整参数后Non DFS Used 稳定在 10% 以内。这里的关键是理解每个参数的实际含义不要盲目照搬网上的配置。6.3 案例三快照导致的隐性占用有个节点 Non DFS Used 异常高但du和lsof都找不到明显的大文件。最后发现是存储层做了快照快照数据占用了大量空间而du默认不统计快照。用lvs和vgs查看逻辑卷信息后确认了问题。处理方式是清理过期快照并调整快照策略。这个案例提醒我们排查要穿透到存储层不能只看文件系统层面。7. 写在最后的一些个人体会处理 Non DFS Used 这类问题最忌讳的就是一上来就删文件。我见过太多因为着急清理而误删数据、导致集群故障的案例。正确的姿势永远是先算清楚账再定位来源最后才动手清理。df、du、lsof这三个命令的组合能解决 90% 以上的磁盘占用排查问题。另外Non DFS Used 本身不是敌人它是 HDFS 给我们的一个信号——提醒我们磁盘上还有其他东西在占用空间。与其把它当成需要消灭的指标不如把它当成一个健康检查项定期关注它的变化趋势。只要它稳定在一个合理范围内就说明集群的磁盘管理是健康的。最后分享一个小技巧在 DataNode 的hdfs-site.xml中可以配置多个数据目录并把它们分散到不同的物理磁盘上。这样即使某块盘出现 Non DFS Used 异常也不会影响整个节点的写入能力。这个配置在集群规划阶段就要考虑好后期调整成本会高很多。