ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Hadoop集群DataNode只显示一个?从心跳到ClusterID的排查指南

Hadoop集群DataNode只显示一个?从心跳到ClusterID的排查指南 部署完 Hadoop 集群打开 NameNode 的 Web 界面兴冲冲想看看几个 DataNode 节点整整齐齐列在页面上。结果刷新一看只有一个 DataNode 孤零零挂在那里集群里其他机器就像消失了一样。这个场景我见过太多次了从三台机的小集群到几十台的中型集群只要是刚搭好的 Hadoop十个问题里有七八个都出在这。很多人第一反应就是配置写错了其实真相比你想的要宽得多。节点进程没起来、集群 ID 对不上、防火墙把端口闷了、甚至 hostname 解析错位任何一个环节都会让你在界面上看到这种缺胳膊少腿的节点列表。这篇文章不绕弯子直接按我的排查思路走一遍从现象、日志、配置文件一步一步往下捋给你一套能直接抄作业的排查方案。1. 先确认你看到的只有一个 Datanode是哪种情况1.1 打开对的界面看对的信息Hadoop 的图形化界面通常指两个地方一个是 NameNode 自己的 Web UI默认端口是 9870Hadoop 3.x老版本是 50070另一个是 YARN 的 ResourceManager 界面端口是 8088。你要查 DataNode 是死是活得去 NameNode 那个页面看。在 NameNode 的 Web UI 上有一个Datanodes标签页进去之后是一个列表。列表中每一行代表一个 DataNode字段包括节点主机名、IP 地址、最后心跳时间、存储容量、当前状态Live 还是 Dead。默认情况下页面上方还有一个Show 10 / 20 / 50 / 100的显示条数切换如果你节点多可能被折叠了但这明显不是你遇到的只有一个的情况。更常见的误解是把Overview页里的 Live Nodes 数量当成全部。Overview 页只显示一个汇总数字比如 Live Nodes: 3如果这个数字是 1那说明在 NameNode 看来确实只有一个节点活着。如果这个数字是 3但列表里只能看到一个那才需要怀疑是不是界面查询的问题——但说实话我很少遇到后者。1.2 显示出来和节点存活是两回事这是排查思路里最核心的一句NameNode 不是扫描到集群里有哪些机器就显示哪些机器而是靠 DataNode 主动上报心跳来登记节点。DataNode 进程启动后会拿着自己的地址和存储信息去向 NameNode 注册注册成功后每隔几秒发送一次心跳。只有心跳正常的节点才会出现在 Web UI 的 Live 列表里。换句话说你在界面上看到几个节点就等于 NameNode 收到了几个节点的心跳。看到只有一个通常只有两种解释其他节点的 DataNode 进程压根没起来或者起来了但没办法和 NameNode 完成注册。这时候第一步永远只有一个跑到其他节点上去看看这个进程到底在不在。2. 从进程和日志入手判断 Datanode 到底是没启动还是连不上2.1 逐台节点检查 Java 进程在集群中除了 NameNode 之外的每一台机器上执行这个命令jpsjps 是 JDK 自带的小工具专门显示当前用户启动的 Java 进程。如果在某台机器上看到了DataNode这个进程名说明进程活着。如果没有说明这个节点的 DataNode 根本没起来或者起来之后又自己退了。你会看到几种典型输出只有Jps本身进程完全不存在说明 DataNode 压根没启动过。有DataNode但启动时间很短说明它反复崩溃重启。有DataNode且一直在运行但 Web UI 就是看不到那问题多半出在注册或者网络层面要看日志。如果进程不在直接看日志比猜原因靠谱得多。DataNode 日志默认在$HADOOP_HOME/logs目录下通常有两个文件需要关注ls -lt $HADOOP_HOME/logs/会看到类似hadoop-hadoop-datanode-node2.log和hadoop-hadoop-datanode-node2.out这样的文件。.log是程序自己的日志输出.out是 JVM 启动时的标准输出和错误输出。排查启动问题先看.out再看.log的最后几百行。2.2 日志里见真章常见的启动失败原因打开日志如果看到以下这几类关键词基本就能定位了。第一类ClusterID 不匹配。这类日志通常长这样java.io.IOException: Incompatible clusterIDs in ... NameNode clusterID CID-xxxxxxxx DataNode clusterID CID-yyyyyyyy这是新集群部署中出镜率最高的启动失败原因后面我会单独拿出一节来讲因为它太经典了。第二类磁盘或目录权限问题。java.io.IOException: Failed to create storage directory: /data/hadoop/hdfs/datanodeDataNode 需要往dfs.datanode.data.dir指向的目录写数据如果这个目录不存在、权限不对、或者磁盘满了DataNode 就会直接退出。我先说排查命令df -h ls -ld /data/hadoop/hdfs/datanode whoami注意启动 Hadoop 的用户通常是 hadoop 用户必须对这个目录有写权限。很多人图省事直接chown -R hadoop:hadoop解决这也是对的。第三类端口被占或网络地址绑定失败。java.net.BindException: Cannot assign requested address java.net.BindException: Address already in use前者常见于机器的 hostname 解析有问题绑定了错误的 IP 地址后者就是端口冲突。DataNode 的通信端口默认是 9864Hadoop 3.x旧版本 50010如果被其他进程占了同样起不来。看完日志把问题分成了两类——进程没起来和进程起来了但连不上——接下来我们要确定 NameNode 侧到底怎么判断一个节点是活的。2.3 心跳超时才是界面看不见的直接原因DataNode 每 3 秒会向 NameNode 发送一次心跳NameNode 如果连续超过一定时间没收到心跳就会把该节点标记为 Dead。节点一旦被标记为 Dead虽然理论上还能在 Web UI 的列表里看到但状态会变成灰色或者直接不显示在 Live 列表里。很多人看到的只有一个节点其实就是其他节点全 Dead 了。这个超时时间由下面两个参数决定property namedfs.namenode.heartbeat.recheck-interval/name value300000/value /property property namedfs.namenode.stale.datanode.interval/name value30000/value /propertystale.datanode.interval默认 30 秒表示超过 30 秒没收到心跳就标记为 stale过期而heartbeat.recheck-interval的默认值单位是毫秒默认 5 分钟它决定 NameNode 把心跳超时节点标记为 Dead 的周期。两者配合实际上如果一个节点连续约 10 分 30 秒都不发心跳NameNode 才会彻底判定它失联。所以如果节点进程刚启动几分钟就去看界面可能因为注册过程慢或者心跳间隔还没到暂时看不到更多情况下是节点长时间连不上 NameNode被标记成了 Dead。如果是这种情况先去节点上看日志看看有没有周期性出现网络异常java.io.IOException: Failed on local exception: java.net.ConnectException: Connection refused如果看到这条问题基本就在网络层——要么是 NameNode 的 RPC 端口默认 8020 或 9000不通要么是节点机器到 NameNode 的这条链路被防火墙挡了。检查方法很简单在 DataNode 那台机器上手动连通性测试一把telnet namenode主机名 9000或者用 ncnc -vz namenode主机名 9000如果连不通说明数据节点根本没法到达 NameNode 的注册端口那心跳自然断掉界面当然看不到它。这个问题看似简单但排查起来容易绕远路因为很多同学只关注 Hadoop 配置忽略了防火墙和主机名解析。3. 集群 ID 不一致是界面只显示一个节点的头号杀手3.1 ClusterID 到底是谁生成、怎么对上的这是整个排查中最容易踩的坑也是我见过最多的一种情况。先理解一个背景NameNode 在第一次执行hdfs namenode -format的时候会生成一个唯一的 clusterID这个 ID 是一串类似CID-abc12345-xxxx-xxxx的字符串会被写进 NameNode 的数据目录下的VERSION文件里。而 DataNode 节点在首次启动时也会在自己的数据目录里生成自己的VERSION文件并且记录一个 clusterID。DataNode 向 NameNode 注册时会把 clusterID 一起送过去。NameNode 发现两边 ID 不一致就会拒绝对接。这个 ID 不一致是怎么出现的最常见的路径是你先把所有节点都初始化了一遍后来因为某种原因比如 NameNode 的元数据丢了或者你重新格式化了一次 NameNodeNameNode 生成了一串全新的 clusterID。但 DataNode 的数据目录还是老的 ID两边就对不上了。日志里你会看到的报错就是 Incompatible clusterIDs。3.2 怎么对齐 ClusterID三种处理办法办法一新集群直接清掉 DataNode 的持久化数据重建。如果你是刚搭建的集群DataNode 上本来就没有什么业务数据最干脆的操作就是把 DataNode 的dfs.datanode.data.dir目录下的内容清掉让它以一个全新的身份重新启动注册。# 在每一台 DataNode 节点上执行 sudo rm -rf /data/hadoop/hdfs/datanode/current # 如果目录下还有其他旧数据也一并确认是否需要清理 # 重启 DataNode 即可注意这不是只删日志而是把数据目录清空。重启后 DataNode 会拿着当前 NameNode 的 clusterID 重新初始化两边就对齐了。办法二手动修改 VERSION 文件保留数据。在不想丢数据的场景下可以手动去改 DataNode 的VERSION文件。先找到文件cat /data/hadoop/hdfs/datanode/current/VERSION这个文件里有一行clusterIDCID-xxxxxxx。然后去 NameNode 上把 NameNode 数据目录dfs.namenode.name.dir指向的目录下的VERSION文件里的clusterID取出来然后把 DataNode 这边的 clusterID 改成一样的。# 在 DataNode 节点上编辑 vi /data/hadoop/hdfs/datanode/current/VERSION # 将 clusterID 改一致后保存退出然后重启 DataNode这是一个前提条件所有 DataNode 的 VERSION 文件、NameNode 的 VERSION 文件clusterID 必须完全一致。你可以写个循环脚本批量改但一定要小心别把namespaceID这行弄混了它跟 clusterID 不是一回事数据节点的 namespaceID 可以和 NameNode 不同。办法三把 NameNode 元数据恢复到和 DataNode 一致的 clusterID。如果反过来你更想保留 DataNode 数据、但 NameNode 重新格式化了那就得更麻烦一点。因为 NameNode 格式化之后 clusterID 变了你需要用hdfs namenode -bootstrapStandby或者从已有元数据恢复的方式来重建 clusterID而不是直接一次性格式化。对于新搭建的同学我更推荐你回到办法一别在这上面折腾。这里还有一条很重要的经验格式化 NameNode 之前一定要想清楚 DataNode 的 clusterID 会被甩在后面。很多人在调试过程中顺手就格式化了一遍 NameNode结果 DataNode 全部连不上还以为配置坏了。4. 配置文件与网络问题的经典坑4.1 hostname 解析localHost 和节点映射的坑很多人在 hdfs-site.xml 里用 localhost 或者 127.0.0.1 配置了 NameNode 地址结果只在本机上的 DataNode 能连上其他节点的 DataNode 全都在迷茫地找localho...这个问题太典型了。在完全分布式集群里core-site.xml的fs.defaultFS必须写 NameNode 的真实主机名或局域网 IP而不是 localhost。DataNode 启动时会去连这个地址如果写成 localhost那它连的就是自己那台机器上的 NameNode显然连不上进程反复报错界面上自然只有本地节点存活。正确的做法是先规划好 hostname 映射。在集群的每一台机器上编辑/etc/hosts把所有的节点主机名和 IP 都写进去192.168.1.10 namenode 192.168.1.11 datanode1 192.168.1.12 datanode2 192.168.1.13 datanode3然后检查core-site.xmlproperty namefs.defaultFS/name valuehdfs://namenode:9000/value /property注意这个配置在每一台节点上都要一致而且千万不能出现hdfs://localhost:9000这种写法。我在实际项目里因为某台机器上残留了/etc/hosts里的一行127.0.0.1 namenode导致该节点把 NameNode 解析到了自己身上折腾了好久才发现。另外有一个隐藏的坑/etc/hostname和/etc/hosts里的主机名不一致时也可能导致 DataNode 上报的身份错乱。启动前可以统一执行一遍hostname uname -a在每台节点上确认主机名是否和规划一致。如果主机名不一致DataNode 上报的地址也会乱界面上显示的节点主机名会出乱码或者奇怪的别名。4.2 防火墙、端口、以及 start-dfs.sh 的启动清单除了 hostname防火墙是另一个高发原因。常见的 Hadoop 端口如下表服务默认端口说明NameNode RPC8020 / 9000DataNode 注册、心跳、元数据操作NameNode HTTP UI98703.x/ 500702.x图形界面DataNode 数据传输98643.x/ 500102.xDataNode 之间和客户端的数据流DataNode HTTP UI9864单节点数据查看YARN ResourceManager UI8088资源管理界面前两个端口是你排查这个问题的核心。DataNode 需要能连上 NameNode 的 RPC 端口如果你用了 firewalld可以这样开放sudo firewall-cmd --permanent --add-port8020/tcp sudo firewall-cmd --permanent --add-port9870/tcp sudo firewall-cmd --reload但要注意不是只放 NameNode 这台机器的端口DataNode 与 NameNode 之间的所有端口链路都得通畅包括 DataNode 自己上报时需要的端口。更简单的做法是在测试环境临时关掉防火墙先用最短路径验证问题sudo systemctl stop firewalld关闭后如果节点立刻能显示出来那就是防火墙的锅再去细化放行规则就行。还有一个经常被忽略的地方workers文件。在 Hadoop 3.x 中这个文件名是workers在 Hadoop 2.x 中是slaves。它位于$HADOOP_HOME/etc/hadoop/目录下每行写一个节点名。执行start-dfs.sh时脚本会按照这个文件去远程启动 DataNode 进程。# workers 文件示例 datanode1 datanode2 datanode3如果你在 workers 文件里没写某个节点那start-dfs.sh就不会去那台机器启动 DataNode。但要注意即使你在某台机器上手动执行hdfs datanode启动 DataNode它依然可以连接到 NameNode 注册。所以如果 workers 文件漏了节点只是没启动但一旦手动加上节点依然能出现在界面里。另外如果节点的磁盘空间不足DataNode 也可能启动成功但因为无法分配存储目录而反复退出。我记得有次排查了很久最后发现是分区满了导致缓存数据写不进去DataNode 在启动后十几秒就自动退出了界面上也是一只把节点列成 dead。检查命令还是最基础的那个df -h5. 我把排查思路做成了速查表省得你每次都重头查起5.1 从现象到原因的一页速查现象可能原因第一步验证方法其他节点 jps 看不到 DataNodeDataNode 未启动手动执行hdfs datanode看报错启动后几秒就退出clusterID 不一致 / 磁盘满了 / 权限不足看 DataNode 日志关键词进程在但界面 Dead心跳超时网络不通从节点 telnet NameNode 9000 端口界面 Live 只有一台hostname 错误 / fs.defaultFS 指向 localhost检查 core-site.xml 和 /etc/hosts启动时 Connection refused防火墙挡了端口临时关闭防火墙测试启动时 Cannot assign requested address主机名解析不到本机 IP检查 /etc/hosts 和 hostname这张表其实是我自己实战中的真实顺序。先说好它不代表严谨的官方方法论但能帮你缩小排查范围尤其是新集群搭建按这个顺序查绝大多数问题十分钟内能定位。5.2 我的排查顺序和几个实用习惯我踩过无数次坑之后形成了一套固定流程。执行顺序是这样的先看进程再翻配置。用 jps 扫一遍所有节点排除进程完全没起来的情况。这一步能砍掉一半的问题。再看日志不看日志瞎猜是浪费时间。日志文件路径也就那两三个优先看.out的启动尾部再看.log的 WARN / ERROR。确认 NameNode 与 DataNode 的 clusterID。直接在 NameNode 上执行cat /data/hadoop/hdfs/namenode/current/VERSION在 DataNode 上执行cat /data/hadoop/hdfs/datanode/current/VERSION对比两边的 clusterID不一致就是它了。检查网络通路。telnet 一下 9000 和 9870 端口不行就直接关防火墙测试。最后再回头核配置。确认core-site.xml里的 fs.defaultFS 不是 localhost确认workers文件里包含所有节点。这几个步骤我建议按顺序来不要跳。很多同学一上来就看配置结果配置文件没问题绕了半天才发现是 DataNode 进程压根没起来。另外还有一个习惯很重要改完配置或清理完目录后一定要重启集群而且启动顺序要正确。先启动 NameNode确认 NameNode 进程稳定了再启动 DataNode。可以用start-dfs.sh一把梭但严格来说手工分布启动更利于观察哪一步出问题。# 在 NameNode 上先起 NameNode 进程 hdfs --daemon start namenode # 然后在每台 DataNode 上起 DataNode hdfs --daemon start datanode # 也可以依赖 workers 文件批量启动 start-dfs.sh等你确认所有节点都能正常显示了再把启动方式切回start-dfs.sh也不迟。5.3 踩过的坑伪分布式与一学期集群的那种痛说到界面上只有一个 DataNode还有一种非常隐蔽的场景是你以为自己在搭分布式集群其实还在跑伪分布式。我在教程里见过太多这种案例了在 Ubuntu 上用三台虚拟机搭 Hadoop但每台虚拟机都装了一遍 Hadoop 单机版core-site.xml全部写成hdfs://localhost:9000。结果就是每一台的 DataNode 都在尝试连自己的 NameNode整个集群实际上是一堆互不相干的伪分布式节点。这种场景下NameNode Web UI 上永远只显示本机一个 DataNode也永远不会显示其他机器。原因非常简单DataNode 配置的 nameService 地址是 localhost 或 127.0.0.1压根不知道集群中心在哪。解决方式就是回到 4.1 节说的统一 hostname 和fs.defaultFS。这里我再补充一个确认手段在 NameNode 上执行hdfs dfsadmin -report这个命令会直接汇总所有存活的 DataNode 信息如果这里的节点数量和 Web UI 对不上说明是 UI 显示问题如果 report 里也只有一台那问题就是真实存在的继续按上面的排查表走。我每次带新人搭集群都会要求他们把集群里所有节点的/etc/hosts打印出来贴到一起核对一遍再开始动 Hadoop 配置。因为这个环节一旦错位后面所有排查都是在做无用功。6. 这类问题背后的思维方式其实排查只有一个 DataNode这个问题本质上是在训练一种分布式系统的故障定位思维不要从界面显示反推原因要从数据流向去理解问题。DataNode 启动 - 注册 - 心跳 - 界面显示这个过程里每一步都有对应的检查点。进程在不在、日志写什么、网络通不通、ID 对不对、配置文件指向哪里一层一层查下去问题一定会在某一层暴露出来。没有玄学只有还没查到的环节。我第一次碰到这个问题时也花了一整个下午。后来发现只是一台机器的防火墙没放行 9000 端口当时真想抽自己。后来养成了习惯每动一个新的测试环境先把端口放行列表跑一遍写成脚本固化下来再也不用手动敲了。这类问题虽然解决起来简单但浪费的时间是真金白银。希望这篇排查记录能帮你把调试时间从几小时压缩到十分钟。如果你现在正卡在某个具体的报错上建议把 DataNode 日志的最后五十行发给你身边的人看日志能告诉你答案。我这个习惯也送给你。
返回列表