HDFS 运维与故障排查 SOP
HDFS 运维与故障排查 SOP
引言
写到这里,HDFS 系列已经走过了架构、读写路径、元数据、副本管理、一致性租约、小文件治理等篇。每一篇里我都会零散地提到一些”运维要点”,但一直没把它们攒成一套体系。这一篇就是来收尾的——把分散在各篇的运维点,汇总成一套可落地的观测体系 + 故障排查 SOP。
为什么 HDFS 的运维值得单独成篇?因为 HDFS 出问题,几乎从来不是”某个文件读不到”这么局部的事。它是元数据中枢,NameNode 一抖,全集群的所有作业一起抖;它是存储底座,DataNode 一批下线,所有上层引擎一起报错。换句话说,HDFS 的故障天然是全集群级的,这种级别的故障,靠临场翻日志、靠肌肉记忆去定位,是会出大事的。我在某集群(约 200 节点、3 PB 出头)值班的这几年,吃过的最大教训就是:没有 SOP 的运维,就是把集群稳定性押在值班同学当天的状态上。
这篇文章的目标,是给同样在维护 HDFS 的同学一份能直接抄走的”观测 + 排查”框架。前半部分讲怎么”看见”——观测体系与日常巡检;后半部分讲怎么”处置”——七类高频故障的 SOP,每个都给出现象、定位步骤、处理命令。最后附一份值班 checklist。
一、观测体系:HDFS 运维的眼睛
运维的第一性原则是:在你被电话叫醒之前,监控要先告诉你哪里坏了。HDFS 的观测,核心是两套 JMX:NameNode JMX 和 DataNode JMX。下面这张表是我值班时每天会扫一眼、出事时会逐项核对的 NameNode 关键指标。
1.1 NameNode JMX 关键指标
| 指标(JMX) | 含义 | 关注点 |
|---|---|---|
FilesTotal / BlocksTotal |
文件总数 / 块总数 | 增长趋势异常 = 小文件爆炸或业务异常 |
UnderReplicatedBlocks |
副本数不足的块 | 持续 > 0 且上升 = DN 下线/坏盘 |
PendingReplicationBlocks |
等待副本复制的块 | 持续不消化 = 限速过严或 DN 跟不上 |
ScheduledReplicationBlocks |
已调度但未完成 | 配合 Pending 看 re-replication 速率 |
StaleDataNodes |
心跳过期的 DN | > 0 立即告警,可能即将进入 dead |
DeadNodes |
已判定死亡 DN | 任何非预期增长都是 P1 |
CapacityUsed / CapacityTotal |
已用 / 总容量 | 用率 > 85% 必须扩容 |
VolumeFailuresTotal |
全集群失败卷数 | 反映坏盘情况 |
TransactionsSinceLastCheckpoint |
距上次 Checkpoint 的事务数 | 持续上涨 = SNN/Standby 没在干活 |
LastWrittenTransactionId |
最新写事务 ID | Standby 跟不上时差距拉大 |
MillisSinceLastLoadedEdits |
距上次加载 edits 间隔 | HA 切换后关注 |
FSNamesystemState / Safemode |
是否安全模式 | 非预期进入 = P0 |
RpcQueueTimeNumOps / RpcQueueTimeAvgTime |
RPC 队列长度与平均延迟 | 延迟 > 50ms 需关注 |
GCCount / GCTimeMillis |
GC 次数与耗时 | Full GC 是 NN 头号杀手 |
HeapMemoryUsage |
堆内存使用 | used/committed > 80% 准备调优 |
这张表不是摆设。我给每一个指标都配了对应的 Prometheus 告警规则,下面会给出阈值。需要强调的是,单点指标不可怕,趋势才可怕——UnderReplicatedBlocks 在一次重启后短暂跳到几万很正常(块报告还没全上报),但如果它单调递增且一小时不回落,那就是真的有节点在掉。
1.2 DataNode JMX 关键指标
DataNode 的 JMX 相对简单,但有几个不能漏:
| 指标 | 含义 | 关注点 |
|---|---|---|
VolumeFailures |
本节点失败卷数 | > 0 触发换盘流程 |
FsyncNanosAvgTime |
fsync 平均耗时 | 持续高 = 磁盘 IO 瓶颈 |
DatanodeNetworkErrors |
网络错误计数 | 反映网卡/交换机问题 |
XceiverCount |
并发数据连接数 | 异常高 = 大量并发写或 Hedged Read |
CacheUsed / CacheCapacity |
集中式缓存 | 启用了 hadoop.cache.data 时关注 |
HeartbeatsAvgTime |
心跳 RPC 平均耗时 | 高 = NN 侧 RPC 拥堵 |
BlocksCached / BlocksRead |
缓存命中情况 | 评估缓存策略效果 |
XceiverCount 这个指标容易被忽略,但它其实很关键。它本质上是这个 DN 上正在处理的 IO 工作线程数。当某个 DN 的 XceiverCount 持续显著高于其他节点,往往意味着这是个热点(数据倾斜或 balancer 在猛打它),也可能是 Hedged Read 失控。我在小文件篇、读路径篇都提到过它的副作用。
1.3 采集方案:JMX Exporter + Prometheus + Grafana
生产上我用的方案是 jmx_exporter(Java Agent 方式)+ Prometheus + Grafana,这是社区最主流的组合。
1 | # NN 启动时挂上 jmx_exporter agent |
nn.yml 里要做白名单过滤,否则 JMX 几千个指标会把 Prometheus 打爆。关键告警规则(PromQL)参考:
1 | # 1. Under-replicated blocks 持续上升 |
这套阈值不是抄来的,是我在某集群调出来的。阈值调优的核心原则是:先调到不漏 P1,再压噪声。一开始宁可多报,慢慢根据误报收。
二、日常巡检清单
监控是被动等你,巡检是主动去找。我习惯每天早上开工前花十分钟做一遍这套巡检。
- NN UI 概览:
http://nn:9870/dfshealth.html,扫一眼集群状态、Live/Dead DN 数、Safemode 是否亮、容量条。 -
hdfs fsck / -files -blocks | tail:看 missing/corrupt 块数,正常应该是 0。任何CORRUPT/MISSING都是 P1。 - Under-replicated 趋势:Grafana 上看
UnderReplicatedBlocks过去 24h,正常应该是一条贴近 0 的平线。 - Stale / Dead DN:NN UI 上 Live Nodes 列表里
Last Contact异常的、Stale 标记的,记下来跟进。 - NN GC 日志:
grep "Full GC" /var/log/hadoop/hdfs/*-namenode-*.log,看最近 24h 是否有 Full GC。 - Checkpoint 状态:NN UI 看
Transactions Since Last Checkpoint,正常应该被 Standby 周期性消化掉,不应该无限上涨。 - Standby NN 同步:
Last Written Transaction IdActive 和 Standby 的差距,差距大说明同步跟不上。 - 磁盘水位:DN 上
df -h看 HDFS 卷,单卷满了会触发 volume failure。 - 关键目录 quota:业务方常年的坑就是往一个目录死命写,定期核
hadoop fs -count -q。
这十条每天过一遍,绝大多数问题能在用户报障之前发现。运维的体面,来自你比用户先知道。
三、高频故障 SOP
下面是这篇文章的核心。每个故障按”现象 → 定位 → 处理”三段写,都是我在生产环境真打过的仗。
3.1 NameNode Full GC / 卡顿
这是 HDFS 最经典、也是杀伤力最大的故障。NN 一卡,整个集群所有 RPC 都排队,作业大面积超时。
现象:NN UI 打不开或极慢;客户端报 Failed to connect to NN / Retrying connect to NN;上层 Spark/Flink 作业大批量失败;jstat -gcutil <pid> 看到 Old 区接近满,Full GC 频繁。
定位:
1 | # 1. 确认 Full GC |
根因判断:Full GC 的根因 90% 是堆内对象过多。在 NN 这儿,”对象”主要就是 INode(文件/目录元数据)。常见三种:
- 小文件爆炸:业务往集群灌了大量小文件,INode 数突破亿级。详见我那篇小文件治理。
- 超大目录:单目录下百万级子项,NN 在 list/操作时一次构造大量对象。
- RPC 堆积:长 RPC 把线程占住,新请求堆积,对象不释放。
处理:
- 短期止血:重启 NN(HA 切换)。注意先
hdfs haadmin -failover再处理原 Active。 - 中期减对象:
- 找出小文件大户:
hdfs fsck / -files -blocks -locations | awk '{print $3}' | sort -n | tail,或用hadoop oiv解析 FsImage 统计(小文件篇有完整脚本)。 - 推业务方合并、Har 归档、或迁 OSS/S3。
- 找出小文件大户:
- 长期扩容堆:调大
HADOOP_HEAPSIZE/-Xmx,但注意 NN 堆不建议超过 64GB(指针压缩、GC 停顿),超了就该考虑 Federation 了(见我那篇 HA/Federation)。 - 调 GC:从 CMS / ParallelGC 切 G1GC,停顿更可控。
-XX:+UseG1GC -XX:MaxGCPauseMillis=200。
3.2 大量 under-replicated blocks
这是故障率仅次于 Full GC 的问题,本质是”副本跟不上”。
现象:NN UI 上 Under Replicated Blocks 持续为正且上升;Grafana 告警 HdfsUnderReplicatedBlocksSurge;严重时 PendingReplicationBlocks 也堆积;某些文件读出来报 BlockMissingException。
定位:
1 | # 1. 看 under-replicated 块的来源 |
根因:通常是 DataNode 侧出了问题。一批 DN 同时下线(机架断电、交换机故障)、一批磁盘同时坏(同批次磁盘到寿命)、或 decommission 流程在跑但速度跟不上业务写入速度。
处理:
- 先恢复 DN:如果是节点宕了,优先把 DN 拉起来;下线的 DN 恢复后块会自动补全。
- 放开 re-replication 限速:默认参数比较保守,集群大时补不动。
1
2
3
4
5# hdfs-site.xml,调大 re-replication 速度
dfs.namenode.replication.work.multiplier.per.iteration=8
dfs.namenode.replication.max-streams=16
dfs.namenode.replication.max-streams-hard-limit=32
# <!-- 校准:请按真实经历核实/替换,过大可能压垮 DN 网络 --> - 批量触发:必要时用
hdfs dfsadmin -setSpaceQuota调整触发条件,或重启 NN 让它重新扫描(重启有风险,权衡用)。 - 监控消化速率:盯
ScheduledReplicationBlocks是否在下降,下降说明在补,只是慢;不下降说明限速卡死,继续放大参数。
3.3 DataNode 死亡 / 坏盘
DN 故障分两类:节点级死亡(心跳没了)和磁盘级失败(volume 挂了但 DN 还在)。
现象(节点死亡):NN UI 上该 DN 进入 Dead 列表;该节点上所有块进入 under-replicated;作业读这些块报错。
定位(节点死亡):
1 | # 1. 进程在不在 |
处理(节点死亡):根据日志根因处理。OOM 调 DN 堆;磁盘满清日志;网络修好后重启 DN。关键:恢复后 DN 上来的块报告会很猛,注意观察 NN RPC。
现象(坏盘):DN 还在 Live,但 VolumeFailures 上升;该 DN 上部分块变 under-replicated。
定位(坏盘):
1 | # 1. 在 DN 上看哪些 volume failed |
处理(换盘流程):
- 确认坏盘:
smartctl -a /dev/sdX看硬件错误。 - 物理换盘(运维同事)。
- 重建文件系统:
mkfs.xfs /dev/sdX1; mount /dev/sdX1 /data/dn/3。 - 目录归属要正确:DN 会扫描所有
dfs.datanode.data.dir配置的目录。 - 重启 DN:
hdfs --daemon stop datanode; hdfs --daemon start datanode。 - 观察该 volume 上的块逐渐补全。
关于 dfs.datanode.failed.volumes.tolerated:默认是 0,即任何一块盘坏了 DN 直接退出。生产上我建议设成 1(12 盘节点),允许坏一块盘继续服役,避免一块盘带走整个节点。具体详见副本管理篇。
3.4 Safemode 不退出
现象:NN 启动后或运行中卡在 Safemode;客户端报 Name node in safe mode,写操作全失败;NN UI 上 Safemode 为 ON。
定位:
1 | # 1. Safemode 原因 |
根因:Safemode 的退出条件是 已上报块的节点比例 >= dfs.safemode.threshold.pct(默认 0.999f)。不退出的常见原因:有 DN 还没起来(块没全上报)、块报告太慢、或真的丢了块(低于阈值)。
处理:
- 等:如果只是 DN 还在陆续起来,等就行。NN UI 看
datanode heartbeat数量在涨就是正常的。 - 查丢失块:
hdfs fsck / -files -blocks | grep -c "MISSING",如果有大量 missing,说明真丢数据了,先修这个。 - 手动退出(高风险):
hdfs dfsadmin -safemode leave。这是核武器,慎用。手动退出意味着你接受”可能丢块”的现状,后续读这些块会失败。除非你已确认块都在、只是上报慢,否则别用。 - 调阈值:
dfs.safemode.threshold.pct调低,但这是治标,根因还是块上报慢。
3.5 慢节点拖垮作业
这是最隐蔽的一类故障,业务方特别容易投诉但 HDFS 侧很难抓。
现象:业务反馈”作业偶尔卡很久”;NN/DN 监控都正常;某些 task 的 locality 报告里某个 DN 反复出现高延迟。
定位:
1 | # 1. 找慢节点——看 DN 的 RPC / IO 延迟 |
处理:
- Hedged Read:客户端配置
dfs.client.hedged.read.threshold.millis=50,读慢了自动发副本读,规避慢节点。注意这个参数的副作用我在读路径篇讲过,会放大 DN 压力。 - 隔离慢节点:把它加入
dfs.hosts.exclude做 decommission,或临时下线修盘。 - 换盘:确认是单盘老化就换。
- 网络排查:有时不是磁盘是网卡,
ethtool -S <nic> | grep -i error看错包计数。
3.6 误删恢复
这条是给业务方救命的,运维同学务必熟记。
现象:业务方误删了重要目录,焦急求助。
定位与处理:
1 | # 1. 第一直觉:查回收站 |
回收站机制:HDFS 回收站默认 fs.trash.interval=0(关闭),生产必须开,建议设成 1440(分钟,即 24h)或更长。回收站里的文件到点会被 expunge 清掉。
如果回收站已清空:靠 Snapshot。前提是你提前给关键目录开了快照:
1 | # 开启快照(事前) |
关键教训:回收站和快照都是事前手段,事后补不了。运维要做的,是在业务方出事之前就把这两个开关打开。
3.7 NN 启动慢
NN 重启慢本身不一定是故障,但HA 切换时慢一秒都致命,所以要把它纳入观测。
现象:NN 重启后进入 Safemode 很久才退出;FsImage 加载耗时长;块报告风暴。
定位:
1 | # 1. 看 NN 启动各阶段耗时 |
根因与处理:
- FsImage 太大:本质还是元数据多(小文件/大目录)。治理小文件是长期方案;短期可调大
dfs.namenode.max.objects(默认 0 不限制),但要明白这会放大堆压力。 - 块报告风暴:NN 一起来,所有 DN 同时上报全量块报告,RPC 被打爆。Hadoop 3.x 有块报告分批(
dfs.namenode.blockreport.full.report.length),可以调;也可以滚动重启 DN,错开上报时间。 - CheckPoint 没跟上:NN 启动要回放 edits,edits 太长启动就慢。确保 Standby 在周期性合并,或手动
hdfs dfsadmin -saveNamespace(会触发 Safemode,慎选窗口期)。
四、容量与扩缩容
容量管理是 HDFS 运维的常规动作,但容易踩坑。
4.1 扩容上线流程
新节点上线 SOP:
- 机器到位,装好 OS、Java、Hadoop 二进制,配置同步。
- 配
dfs.datanode.data.dir、dfs.namenode.name.dir等参数,与现网一致。 - 把新节点加入
dfs.hosts(白名单)。 - 启动 DN:
hdfs --daemon start datanode。 - 验证:NN UI 看到新 DN 进入 Live;
hdfs dfsadmin -report看到容量增加。 - 关键:跑 balancer,让新节点真正承担数据。否则业务写入还是往老节点堆。详见副本管理篇。
4.2 Decommission 下线流程
下线节点 SOP(比上线更危险,因为要在保证副本数的前提下搬走数据):
1 | # 1. 加入 exclude 文件 |
坑点:
- Decommission 是有副本数保证的搬运,速度受
dfs.datanode.balance.bandwidthPerSec限制,慢。 - EC(纠删码)文件的 decommission 逻辑和 3 副本不同,可能卡住。见副本管理篇。
- 绝对不能直接 kill DN 进程了事,那会导致大量 under-replicated blocks,等于制造故障。
4.3 Balancer 跟进
扩缩容后必跑 balancer。详见副本管理篇,这里只提醒一句:balancer 的带宽不要调太大,默认 1MB/s 太保守,但调到 100MB/s 以上会冲击业务 IO。我一般调到 50MB/s。
五、安全运维
启用了 Kerberos 的集群,会多出一类”安全类故障”。
5.1 Kerberos ticket 续约失效
现象:长跑作业(如 Spark/Flink 跑几小时)突然报认证失败 GSSException: No credentials provided;客户端报 ticket expired。
根因:Hadoop 的机制是 login 时拿一个 TGT,然后靠 krb5.conf 的 renew_lifetime 自动续约。续约失效常见原因:
- KDC 的
max_renewable_life设得不够长。 - ticket 续约到了最大生命周期(默认 7 天) 还没跑完。
- keytab 过期或 principal 被禁。
处理:
- 长跑作业用 keytab +
UserGroupInformation.loginUserFromKeytabAndReturnUGI,定期 re-login。 - 检查
krb5.conf的renew_lifetime与 KDC 的maxrenewlife。 - DN/NN 服务侧用 keytab + 自动续约,配
hadoop.kerberos.keytab.login相关参数。
5.2 Delegation Token 过期
现象:MapReduce/Spark 长任务报 org.apache.hadoop.security.token.SecretManager$InvalidToken: token expired。
根因:HDFS Delegation Token 默认有效期 24h(dfs.namenode.delegation.token.max-lifetime),长任务跑超了。
处理:作业配置里启用 token 续约(YARN 的 RM 有 TokenRenewer);或调大 max-lifetime;或长跑流式作业改用 keytab 直接认证,不依赖 token。
5.3 ACL 变更审计
现象:误把权限给了不该给的人,或权限被改导致业务报 AccessControlException。
处理:
1 | # 看权限 |
生产建议:audit log 一定要开,配合 Ranger 做细粒度权限,关键目录变更留痕。详见我那篇 Kerberos & Ranger。
六、应急工具箱
把常用命令攒成一个 cheat sheet,值班时直接翻。
6.1 hdfs fsck —— 定位 missing/corrupt
1 | # 全集群健康检查 |
6.2 hdfs oiv / oev —— 离线分析镜像
1 | # 把 FsImage 转成可读 |
这俩在小文件治理(统计 FsImage 找小文件大户)和元数据排障时是核武器。
6.3 jstack / jmap —— JVM 现场诊断
1 | # 线程栈 |
6.4 hdfs debug —— 块级调试
1 | # 看某个块落在哪些 DN 上 |
七、值班 Checklist
最后附一份我自己值班用的 checklist,出事时照着这个走,能保证不漏关键步骤。
- 第一反应:确认是否真的 P0。看 NN UI 能否打开、Safemode 是否亮、Dead DN 是否激增。
- 通报:P0 故障第一时间在工作群通报”已介入,预计 X 分钟同步进展”,避免业务方反复电话。
- 抓现场:jstack、jmap、NN/DN 日志、fsck 输出,第一时间抓,错过就没了。
- 止血优先:能切换 HA 就切换,能重启就重启,先恢复服务再追根因。
- 定位根因:对照上面七类 SOP 逐项排查。
- 处理:按 SOP 执行,每一步都留命令记录。
- 验证恢复:fsck 干净、under-replicated 归零、业务方确认正常。
- 复盘:48h 内出复盘文档,根因 / 时间线 / 改进项,改进项落到 SOP 和监控。
附:NN Full GC 应急排查命令序列
1 | # === 步骤1:确认 Full GC 与影响 === |
附:大量 under-replicated blocks 处理命令序列
1 | # === 步骤1:确认 under-replicated 规模与来源 === |
小结
HDFS 的运维,本质是两件事:让你先看见,让你能处置。
观测体系是眼睛。NameNode / DataNode 的 JMX 指标,配上 Prometheus + Grafana 和一套调过的告警阈值,能把绝大多数故障掐灭在用户感知之前。日常巡检是肌肉记忆,十分钟换一份从容。
故障 SOP 是肌肉。NN Full GC、under-replicated blocks、DN 死亡坏盘、Safemode 卡死、慢节点、误删、启动慢——这七类几乎覆盖了 HDFS 生产故障的全部高频场景。每一类都按”现象 → 定位 → 处理”走一遍,配合文末的两段命令序列和应急工具箱,值班时就不慌。
最后想说一句,运维的尽头是工程化。真正成熟的运维,不是个人英雄主义地救火,而是把每一次故障都沉淀成 SOP、监控、checklist,让下一个值班同学不用重新踩一遍坑。希望这一篇能成为你值班屏幕角落里那页常驻的参考。
HDFS 系列到这里就告一段落了。从架构、读写、元数据、副本、一致性、小文件到这篇运维收尾,一套比较完整的 HDFS 知识体系算是搭起来了。后续如果有机会,会再写写 HDFS 跨集群迁移、EC 落地这些进阶话题。我们下个系列见。
