ARM云主机Hadoop集群搭建:JAVA_HOME、SSH与对象存储排障

发布时间:2026/10/31 7:13:56
ARM云主机Hadoop集群搭建:JAVA_HOME、SSH与对象存储排障 简介《鲲鹏云大数据实验docx》是一份面向大数据初学者与云计算实验教学场景的实操型报告围绕华为云ECS、OBS与Hadoop集群的搭建配置展开重点解决云主机准备、对象存储接入、节点互信及Hadoop运行环境调试等问题。压缩包仅含1个docx文档大小约2.52MB以图文步骤和命令记录为主便于按实验流程查阅与复盘。资源已有893人学习适合作为课程实验、实训任务或自主练习的参考资料。内容完整记录了从购买云服务器、创建OBS并行文件系统并获取AK/SK到三节点Hadoop集群的目录规划、SSH免密、配置分发、NameNode初始化与HDFS启动等环节对Java家目录配置错误导致的重复分发与启动失败也保留了排错过程。读者可借此理解鲲鹏云环境下大数据基础设施的部署顺序、配置要点与常见问题定位方法。1. 集群环境里最容易卡住的一步集群搭到一半hdfs namenode -format突然报JAVA_HOME is not set可java -version明明能跑把 JAVA_HOME 补上格式化过了启动 HDFS 又报JAVA_HOME is incorrectly set等你改完路径再敲hdfs dfs -ls它第三次报错。Java 装好了却连续多次失败是 ARM 架构云主机上搭 Hadoop 最典型的开局。这份实验记录里最折腾人的几处根本原因几乎都在这一个环境变量上剩下的问题分布在节点互信、hosts 解析和对象存储接入这三段。下面按实际场景逐个拆解正卡在启动环节的人可以照着排查。2. 格式化就失败JAVA_HOME 指错目录引发的连续失败2.1 三个报错其实来自同一个问题第一次翻车通常出现在hdfs namenode -format。终端里不会给你任何“Java 路径不对”的提示抛出来的东西五花八门我按出现频率排一下# 形态一环境变量压根没设 JAVA_HOME is not set and could not be found. # 形态二设了但指向的目录不存在 /usr/local/hadoop/bin/hdfs: line 320: /usr/java/default/bin/java: No such file or directory # 形态三设了目录也存在但没有可执行权限或不是 JDK Error: JAVA_HOME is incorrectly set. Please update /home/modules/hadoop-2.8.3/etc/hadoop/hadoop-env.sh形态二最容易误导人。line 320: /usr/java/default/bin/java: No such file or directory看起来像个 shell 脚本错误实际上是 hadoop 启动脚本拿着$JAVA_HOME/bin/java去执行发现文件不存在。形态三更隐蔽目录明明在ls也能列出来但目录里只有jre/bin/java没有bin/javac脚本会判定这不是一个合法的 JDK 根目录。这三种形态的共同点是报错的模块和出问题的模块不是同一个。你在 NameNode 初始化的位置看到报错问题却出在几百行之外的hadoop-env.sh或者/etc/profile。很多人第一反应是重装 Hadoop、重新解压安装包、甚至重买一台机器做完一圈发现还是同样的报错这就是没定位到根本原因的表现。我一般会养成一个习惯先别管报什么错先在出问题的节点上手工把三件事验证一遍——echo $JAVA_HOME有没有值、这个值指向的目录存不存在、这个目录下有没有bin/javac。三个问题里只要有一个是“否”后面看到的所有报错都是它的衍生症状不用再往下查了。2.2 为什么 ARM 机器上这个路径特别容易写错x86 时代的教程里JAVA_HOME 基本是两三个固定值/usr/java/default、/usr/lib/jvm/java-1.8.0-openjdk.x86_64、/opt/jdk1.8.0_xxx。你照着抄八成的机器能跑起来。换成 ARM 架构的云主机之后这套照抄法就失效了原因有三个。第一个是目录名变长了。以常见的 openEuler 系镜像为例装完java-1.8.0-openjdk-devel之后真实目录是/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-1.h5.oe1.aarch64这种形态。中间那一串构建号加发行版标识加架构后缀随镜像版本变化不同批次买的机器可能都不一样。教程里写的java-1.8.0-openjdk.x86_64在这类机器上根本就不存在。第二个是只装了 JRE 没装 JDK。很多镜像为了省空间预装的是java-1.8.0-openjdk-headlessjava -version正常输出which java也有结果看起来一切正常。但 Hadoop 的脚本会去找javac找不到就判定 JAVA_HOME 非法。这也是“Java 明明装好了却报错”最常见的真相。第三个是软链接造成的假象。which java输出的是/usr/bin/java而/usr/bin/java只是个软链接指向/etc/alternatives/java后者又指向真实的 JVM 目录。如果直接把/usr/bin当成 JAVA_HOME 写进去Hadoop 会去/usr/bin/bin/java找可执行文件自然找不到。所以定位 JAVA_HOME 的正确做法不是猜而是让系统告诉你# 一层层剥掉软链接拿到 java 的真实绝对路径 readlink -f $(which java) # 典型输出/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-1.h5.oe1.aarch64/jre/bin/java # 确认同目录下有没有 javac没有就说明只装了 JRE ls -l $(dirname $(readlink -f $(which java)))/javacreadlink -f的作用是递归解析软链接并输出最终的真实路径比which可靠得多。拿到输出之后把末尾的/jre/bin/java三段砍掉剩下的部分就是 JAVA_HOME。上面那条典型输出的结果是/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-1.h5.oe1.aarch64。注意如果ls那一步报 no such file说明这台机器只装了运行时先补装开发包Debian 系是openjdk-8-jdkRPM 系是java-1.8.0-openjdk-devel再回来看 JAVA_HOME。这一步不补后面所有配置都是白费。2.3 改对 JAVA_HOME两处都得写一处都不能漏路径找到了接下来是写在哪。这里有个很典型的分歧有人只改/etc/profile有人只改hadoop-env.sh两种做法都会在某些场景下失败。/etc/profile是登录 shell 加载的你手工ssh上去敲命令它生效但start-dfs.sh启动子节点进程时是通过非交互式 SSH 远程执行的很多发行版的非登录 shell 根本不读/etc/profile。表现出来就是你在 node-0001 上手工java -version正常start-dfs.sh一跑node-0002 报JAVA_HOME is not set。hadoop-env.sh是 Hadoop 自己的脚本里 source 的任何启动方式都会读到优先级也最高。但它只对 Hadoop 生效你敲hdfs、yarn这些命令的时候用得上别的组件不受影响。稳妥的写法是两处都写、值保持一致# /etc/profile 末尾追加供交互式终端和依赖环境变量的脚本使用 export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-1.h5.oe1.aarch64 export HADOOP_HOME/home/modules/hadoop-2.8.3 export PATH$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH # 立即生效 source /etc/profile# $HADOOP_HOME/etc/hadoop/hadoop-env.sh 中把原来的 export JAVA_HOME... 换成真实路径 # 如果原文件里是注释掉的取消注释再改不要新增一行否则后面的赋值会覆盖前面的 export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-1.h5.oe1.aarch64第一段的关键是PATH的顺序。$JAVA_HOME/bin要排在前面否则系统里如果同时存在另一个 Java比如某个软件自带一份java命令解析到的可能不是你以为的那个。$HADOOP_HOME/sbin加进去之后start-dfs.sh、start-yarn.sh就能直接敲不用每次写全路径。第二段的关键是别重复赋值。hadoop-env.sh是顺序执行的 shell 脚本如果文件前面已经有一行export JAVA_HOME/usr/java/default你在末尾再追加一行正确的最终生效的确实是你新写的那行但如果你写在前面就会被后面的覆盖掉。改完记得用grep -n JAVA_HOME $HADOOP_HOME/etc/hadoop/hadoop-env.sh确认整个文件里只有一处有效赋值。验证不能只验一次要验两种 shell# 登录 shell 下验证 bash -lc echo $JAVA_HOME; java -version; javac -version # 模拟 Hadoop 远程启动时的非交互 shell ssh node-0002 echo \$JAVA_HOME; java -version; javac -version第二条命令里的\$JAVA_HOME用反斜杠转义是因为要让它在对端展开而不是本地展开。这条命令输出为空或者报 command not found就说明对端的 profile 没生效或者根本没配置那start-dfs.sh一定起不来。2.4 改完之后必须重做的三件事JAVA_HOME 改对不等于问题解决了。前面几轮失败的格式化、启动留下了不少残留不清干净的话你看到的下一个报错跟 Java 一点关系都没有。第一件事是把改过的配置同步到所有节点。Hadoop 的start-dfs.sh只在 node-0001 上执行但真正的 NameNode、DataNode 进程分布在各个节点上每个节点都有自己的hadoop-env.sh。只改一台另外两台起来照样报错。# 在 node-0001 上把整份 Hadoop 目录同步到其余节点包含改过的 hadoop-env.sh for h in node-0002 node-0003; do rsync -av /home/modules/hadoop-2.8.3/ $h:/home/modules/hadoop-2.8.3/ done # 各节点分别执行让 /etc/profile 的改动生效 ssh node-0002 source /etc/profile java -version ssh node-0003 source /etc/profile java -version这里用rsync -av而不是scp -r是因为前者只传改动过的文件后面你调core-site.xml的时候会反复用到这个动作。注意别加--delete一旦加了这个参数对端比源端多出来的日志、临时文件会被清掉排查到一半的现场就没了。第二件事是清掉上次失败的格式化残留。NameNode 格式化会在dfs.namenode.name.dir指定的目录里生成current/VERSION和一堆edits文件DataNode 在dfs.datanode.data.dir下也有自己的current/VERSION。上一次格式化如果中途因为 Java 报错中断这些目录可能只写了一半。# 清理 NameNode 与 DataNode 的数据目录路径以 hdfs-site.xml 里配的为准 rm -rf /home/modules/data/buf/* rm -rf /home/nm/localdir/* # 清理临时目录与日志避免旧日志干扰判断 rm -rf /home/modules/hadoop-2.8.3/logs/*第三件事是重新格式化并逐节点检查进程。这里必须强调顺序先清残留再格式化再启动最后jps核对。# 在 node-0001 上执行只格式化一次中间不要重复执行 hdfs namenode -format # 启动 HDFS start-dfs.sh # 每个节点都要看确认进程数对得上 jpsjps是 JDK 自带的工具能看到本机所有 JVM 进程。node-0001 上应该看到NameNode、SecondaryNameNode其余节点应该看到DataNode。少一个都不算成功别急着往下做实验。注意hdfs namenode -format在同一个集群上执行多次是有代价的。每格式化一次NameNode 会生成新的 clusterID而 DataNode 的VERSION文件里还记着旧的启动时就会报Incompatible clusterIDs。这个问题在下一章会详细说。3. 节点之间连不上SSH 互信与 hosts 的排查顺序3.1 三类报错对应三种根因配置节点互信这一段报错信息比 Java 那段直白得多但麻烦在于它会在不同阶段冒出来有时是ssh手工连不上有时是start-dfs.sh执行到一半停住。# 形态一公钥没有被对端接受 Permission denied (publickey,gssapi-keyex,gssapi-with-mic). # 形态二对端主机指纹没被记录或者变了 Host key verification failed. # 形态三主机名解析不了 ssh: Could not resolve hostname node-0002: Name or service not known形态一是最常见的。ssh-copy-id执行过一次自以为配好了实际上可能复制到了错误的用户目录下或者authorized_keys的权限不对。SSH 对权限非常敏感~/.ssh必须是 700~/.ssh/authorized_keys必须是 600多一个组写权限就会被拒绝而且日志里只说“publickey”不会告诉你权限有问题。形态二通常是重装机器或者重建实例之后出现的。云主机的 IP 复用很常见同一个 IP 上换了台新机器本地~/.ssh/known_hosts里记的还是旧指纹连接时直接拒绝。形态三是 hosts 没配或者配错。这个问题最直接但也最容易配漏——三台机器要各自维护一份/etc/hosts漏一台就有一个方向不通。我排查这一段固定按这个顺序走先ping node-0002看解析不通就先修 hosts通了再ssh -v node-0002看卡在哪一步-v的输出会把公钥尝试过程全部打出来比猜快得多。3.2 /etc/hosts 的几种典型错法很多人觉得/etc/hosts就是三行 IP 加主机名没什么可错的。实际排查下来出问题的方式至少有四类。第一类是只在 node-0001 上配了。start-dfs.sh在执行节点上是能解析对端名字的所以脚本能跑起来但它通过 ssh 到 node-0002 之后node-0002 上的sshd启动DataNode时又要解析一次node-0001这时候就对不上了。表现是 node-0001 上的NameNode起来了其他节点的DataNode一个都没有。第二类是把公网 IP 写进去了。云主机一般有内外两张网卡集群内部通信应该走内网地址。如果 hosts 里写的是公网 IP即使能通流量也会绕一圈还受安全组和带宽限制。更糟的情况是公网入方向没放行 22 端口ssh直接超时。第三类是主机名带下划线或者大小写不一致。Hadoop 的slaves文件、core-site.xml里的fs.defaultFS、/etc/hosts里的映射三处的名字必须完全一致。node_0001和node-0001在 DNS 规则里不是一回事Node0001和node0001也可能因为大小写敏感对不上。第四类是把主机名映射到127.0.0.1。这种写法在单机上没问题放到集群里就是麻烦node-0002 上ping node-0002解析到的是 127.0.0.1看似通了实际上 DataNode 注册到 NameNode 的地址是本机回环地址NameNode 永远找不到它。正确写法是这样的三台机器完全一致# /etc/hosts三台机器内容必须完全相同用内网地址不要用公网地址 10.0.0.11 node-0001 10.0.0.12 node-0002 10.0.0.13 node-0003 # 本地回环保持在最后且不要把主机名挂在 127.0.0.1 上 127.0.0.1 localhost localhost.localdomain改完 hosts 还要顺手确认主机名本身是对的# 三台机器各自执行确保 hostname 与 hosts 里写的名字一致 hostname hostnamectl set-hostname node-0002 # 校验解析结果是不是内网 IP getent hosts node-0002getent hosts比ping更干净它直接查名称服务输出解析结果就退出不会像ping那样还要等你按 CtrlC。三台机器上都跑一遍这三个名字全部返回内网 IP 才算过关。3.3 免密登录一次配通的完整序列节点互信的本质是三台机器互相之间都能免密ssh。常见的偷懒做法是只在 node-0001 上生成密钥、复制到其他两台这样 node-0001 能免密连出去反方向不行。平时跑start-dfs.sh勉强够用一旦涉及yarn的ResourceManager重启或者跨节点调度就会出现莫名其妙的权限错误。我的做法是每台机器都生成自己的密钥对然后把三份公钥汇总成一个authorized_keys再分发回去。# 三台机器各自执行生成密钥-N 表示不设密码-f 指定路径避免覆盖已有密钥 ssh-keygen -t rsa -b 2048 -N -f /root/.ssh/id_rsa # 三台机器各自执行把本机公钥追加到自己的 authorized_keys实现免密登录本机 cat /root/.ssh/id_rsa.pub /root/.ssh/authorized_keys chmod 700 /root/.ssh chmod 600 /root/.ssh/authorized_keys chmod 600 /root/.ssh/id_rsa # 在 node-0001 上把其他两台的公钥拉过来汇总成一份完整清单 ssh node-0002 cat /root/.ssh/id_rsa.pub /tmp/all_keys ssh node-0003 cat /root/.ssh/id_rsa.pub /tmp/all_keys cat /root/.ssh/id_rsa.pub /tmp/all_keys sort -u /tmp/all_keys -o /tmp/all_keys # 分发回每台机器 for h in node-0001 node-0002 node-0003; do scp /tmp/all_keys $h:/root/.ssh/authorized_keys ssh $h chmod 600 /root/.ssh/authorized_keys donessh-keygen -N 里的-N是 passphrase 参数空字符串表示不加密私钥。集群内部自动拉起进程时没有人能交互输入密码这一步必须做成空口令。-b 2048是密钥长度RSA 2048 位是当前兼容性和安全性都够用的值太短的老算法会被新版sshd拒绝。sort -u用来去重避免 node-0001 的公钥在文件里出现两次。虽然多一条不影响功能但后面出问题看文件的时候容易犯迷糊。分发完立刻验证而且要把六个方向都验一遍# 六条命令全部无密码返回 hostname才算互信成立 for src in node-0001 node-0002 node-0003; do for dst in node-0001 node-0002 node-0003; do echo -n $src - $dst : ssh $src ssh -o BatchModeyes -o ConnectTimeout5 $dst hostname done done-o BatchModeyes是关键参数它禁止任何交互式提问包括密码输入和首次连接的主机指纹确认。如果某一对没配好命令会直接失败而不是卡在那里等你敲yes。ConnectTimeout5防止网络不通时一直挂着。3.4 start-dfs.sh 只起了一半节点互信配完了start-dfs.sh还是可能出问题表现是输出里有一部分节点报了Starting datanodes之后就没了下文或者直接打印一串Permission denied。第一种情况是首次连接没有预先把对端指纹写进known_hosts。上面的验证脚本用BatchModeyes能发现这个问题但如果验证时偷懒用了手工ssh你可能已经点过yes指纹记录只是存在于你当前那个会话对应的用户目录下。start-dfs.sh以另一个身份跑或者用了不同的HOME指纹记录就读不到。第二种情况是slaves文件写错了。这个文件在$HADOOP_HOME/etc/hadoop/slaves每行一个主机名必须与/etc/hosts里完全一致不能有多余的空格和空行不能写 IP。# $HADOOP_HOME/etc/hadoop/slaves # 只写主机名不写 IP不要留空行和行尾空格 node-0002 node-0003提示slaves文件里不包含 node-0001 本身。NameNode 和 ResourceManager 跑在 node-0001 上DataNode 如果也想起在 node-0001 上需要在slaves里显式加上否则jps在 node-0001 上只会看到 NameNode。第三种情况是sshd对 root 登录做了限制。有些镜像默认PermitRootLogin是prohibit-password或者no公钥方式在部分配置下也会被拦。改/etc/ssh/sshd_config里的PermitRootLogin yes之后记得重启服务光改文件不重启是不生效的。4. 对象存储接不上core-site.xml 里的 AK/SK 与 endpoint 怎么填4.1 报错特征先分清是认证问题还是网络问题Hadoop 跑起来之后把对象存储挂成文件系统是下一个容易卡住的位置。这一段的报错信息看起来都很像“连不上”但根因差别很大先看异常类名能省掉一半排查时间。# 认证类AK/SK 不对、没权限、桶策略没开 org.apache.hadoop.fs.obs.OBSIOException: ... 403 Forbidden NoAuthException: Anonymous access is forbidden # 配置类协议实现类没配或者对应的 jar 包没加载 No FileSystem for scheme: obs java.lang.ClassNotFoundException: org.apache.hadoop.fs.obs.OBSFileSystem # 网络类endpoint 写错、区域不对、出口不通 java.net.UnknownHostException: obs.region.example-cloud.com java.net.SocketTimeoutException: connect timed out403 Forbidden说明网络是通的请求已经到达服务端被拒的是身份。No FileSystem for scheme说明 Hadoop 根本没找到处理obs://协议的实现类通常是 jar 包没放进 classpath 或者配置项名字写错。UnknownHostException是域名解析失败先nslookup或getent hosts验一下 endpoint 能不能解析别在配置里反复改。这三类里最坑的是UnknownHostException和SocketTimeoutException混着出。同一个 endpoint在你本地电脑上能解析在云主机上解析不了因为云主机的 DNS 配置可能指向了内网解析器。这种问题改配置文件是解决不了的。4.2 core-site.xml 关键参数逐项说明对象存储的接入配置集中在core-site.xml几个参数配错任何一个都会导致前面的报错。下面这份是我验证过的结构configuration !-- 默认文件系统仍然指向 HDFS对象存储作为额外的一种 scheme 使用 -- property namefs.defaultFS/name valuehdfs://node-0001:9000/value /property !-- 声明 obs:// 协议由哪个类实现名字写错就会报 No FileSystem for scheme -- property namefs.obs.impl/name valueorg.apache.hadoop.fs.obs.OBSFileSystem/value /property !-- Hadoop 的抽象文件系统层同样需要注册缺了它部分命令会退化 -- property namefs.AbstractFileSystem.obs.impl/name valueorg.apache.hadoop.fs.obs.OBS/value /property !-- 认证信息从控制台下载的凭证文件里取注意首尾不要带空格和换行 -- property namefs.obs.access.key/name value填写你自己的AK/value /property property namefs.obs.secret.key/name value填写你自己的SK/value /property !-- 终端节点必须与桶所在区域一致跨区会显著变慢甚至超时 -- property namefs.obs.endpoint/name valueobs.lt;regiongt;.example-cloud.com/value /property !-- 走 HTTPS端口 443公网环境下不要关掉 -- property namefs.obs.connection.ssl.enabled/name valuetrue/value /property /configurationfs.defaultFS保持指向 HDFS 是故意的。默认文件系统决定了hadoop fs -ls /这种不带 scheme 的命令落在哪里让它落在 HDFS 上更符合实验预期访问对象存储时显式写全obs://桶名/路径。fs.obs.impl和fs.AbstractFileSystem.obs.impl两个都要配。前者是文件系统实现后者是抽象层注册Hadoop 2.x 里这两层是分开的。只配一个的时候hadoop fs -ls obs://...可能能跑但hadoop distcp这类依赖抽象层的工具会报错。AK/SK 那两行最容易出问题。登录控制台创建一个访问密钥下载下来的凭证文件里是 CSV 格式字段顺序是用户名、Access Key Id、Secret Access Key。复制的时候别用鼠标划选容易多带空格用awk -F, {print $2}和{print $3}精确取值更稳。取出来的值写到配置里前后不能有空格value标签必须紧贴内容。endpoint 那行注意 XML 里的和要转义。有些区域名字里带特殊字符直接写会破坏 XML 结构导致整个配置文件解析失败Hadoop 启动时的报错会指向别的模块。4.3 endpoint 选错区域与双栈地址的区别对象存储的控制台一般会给两个终端节点一个是普通的 IPv4 地址一个是双栈地址。双栈那个能同时响应 IPv4 和 IPv6看起来更“高级”但用错了就是灾难。云主机如果只有 IPv4 出口大部分默认网络环境是这样双栈域名解析时可能优先返回 AAAA 记录。客户端拿到 IPv6 地址去连发现本机根本没有 IPv6 路由连接请求发不出去表现出来就是connect timed out而且超时时间很长看起来像服务端挂了。这种问题最难查因为ping那个 IPv4 地址是通的配置文件看起来也没问题。我的判断方法是直接看解析结果# 分别看 A 记录和 AAAA 记录确认客户端拿到的地址族 getent ahosts obs.region.example-cloud.com | head -5 # 如果第一行就是 IPv6 地址、而本机没有 IPv6 路由就换成纯 IPv4 的 endpoint ip -6 route show default第二条命令没有输出说明本机没有 IPv6 默认路由那就老老实实用 IPv4 那个 endpoint。别为了“看起来更先进”去配双栈除非你确认过整条链路都支持。区域一致性同样重要。桶建在哪个区域endpoint 就必须用那个区域的。跨区访问不一定报错但延迟会明显上升传大文件的时候表现成间歇性超时排查起来非常迷惑。控制台的桶详情页里能看到区域信息抄下来直接对应。4.4 用一条最小命令验证接入配置改完不是直接跑业务先做最小验证。这个顺序能帮你把“配置问题”和“数据问题”分开。# 第一步确认实现类加载成功能列出桶根目录 # 这条命令不涉及具体数据只验证认证和连通性 hadoop fs -ls obs://你的桶名/ # 第二步写一个小文件上去验证写权限 echo hello obs /tmp/probe.txt hadoop fs -put /tmp/probe.txt obs://你的桶名/probe/ # 第三步读回来比对内容验证读权限 hadoop fs -cat obs://你的桶名/probe/probe.txt第一步报403就回去查 AK/SK 和桶策略报No FileSystem for scheme就回去查fs.obs.impl和 jar 包报UnknownHostException就回去查 endpoint 和 DNS。三类错误对应三块配置不要混着改。第二步报权限错误但第一步能列目录说明这个 AK 只有读权限没有写权限。桶的访问策略里可以分别控制读写别想当然以为能读就能写。第三步读回来的内容不对那是传输或者编码问题跟接入配置无关了。到这一步接入就算通了可以开始跑后面的实验步骤。5. 踩坑清单五个卡了大半天的现场5.1 只改了一台机器的 hosts集群起了一半现象start-dfs.sh输出里 node-0002 显示Starting datanodes但等几秒后jps在 node-0002 上什么都没有node-0003 正常。NameNode 起来了hdfs dfsadmin -report显示只有一台 DataNode。原因node-0002 的/etc/hosts里只配了自己和 node-0001解析不到 node-0003也解析不到自己在集群里的角色名。DataNode 启动时要向 NameNode 注册注册信息里带上自己的主机名NameNode 反向解析失败就把这个节点丢弃了。解决把三台机器的 hosts 做成同一份文件用scp统一下发改完用getent hosts在每台机器上把三个名字都验一遍。以后任何涉及主机名的改动都按“改一份、发三份、验三遍”走。5.2 重新分发时漏了 hadoop-env.sh配置回滚现象node-0001 上java -version正常JAVA_HOME 也改对了start-dfs.sh一到 node-0003 就报JAVA_HOME is not set。去 node-0003 上看hadoop-env.sh里面还是老路径。原因改配置的时候只改了 node-0001分发的时候用了rsync但目标路径写成了$HADOOP_HOME/shareetc目录整个没同步过去。这种漏同步在目录层级多的时候特别容易发生。解决分发只做整目录同步不做局部。命令固定成rsync -av $HADOOP_HOME/ node-000X:$HADOOP_HOME/源和目标的结尾斜杠都带上保证是“目录内容到目录内容”的语义。同步完用md5sum对比一下关键配置文件确认三台一致。5.3 重复格式化DataNode 起不来现象HDFS 启动后jps在 node-0002 上能看到DataNode进程一闪而过日志里刷Incompatible clusterIDs in /home/nm/localdir/current: namenode clusterID CID-xxxx; datanode clusterID CID-yyyy。原因hdfs namenode -format执行过不止一次。每格式化一次NameNode 生成新的 clusterID而 DataNode 目录里的VERSION文件还记着旧值两边对不上DataNode 拒绝启动。解决最干净的办法是清掉所有节点的数据目录重新格式化一次之后别再执行 format。如果目录里有你不想丢的数据可以手工把 DataNodeVERSION文件里的clusterID改成与 NameNode 一致但这是补救手段实验环境直接清空更省事。注意format 命令只应该在集群首次搭建时执行一次。任何时候想“重新来一遍”都要先确认数据目录已经清空否则就是在给自己制造 clusterID 冲突。5.4 数据目录没提前建启动时报 Mkdirs failed现象start-dfs.sh过程中报java.io.IOException: Mkdirs failed to create /home/nm/localdir或者 YARN 那边报类似local-dirs are bad。原因hdfs-site.xml和yarn-site.xml里配的目录路径Hadoop 不会自动帮你逐级创建。父目录/home/nm不存在的时候mkdirs只能建最后一级前面的建不出来。解决在所有节点上提前把这些目录建好并且把属主设对。这一步要在启动集群之前做不是出了错再补。# 所有节点执行-p 保证父目录一起创建重复执行不报错 mkdir -p /home/modules/data/buf mkdir -p /home/nm/localdir mkdir -p /home/modules/hadoop-2.8.3/logs # 确认目录属主与运行 Hadoop 的用户一致 ls -ld /home/nm/localdir5.5 进程都在网页打不开现象三台机器jps输出齐全hdfs dfs -ls /也能正常执行但浏览器访问http://node-0001:9870一直转圈最后超时。原因云主机的安全组默认只放行 22 端口9870、8088、9000、8020 这些全都没开。命令行能通是因为走的是内网地址浏览器走的是公网入口两条路径的放行规则不一样。解决在控制台的安全组里按需放行端口并且限定来源 IP别图省事开成 0.0.0.0/0。先用ss -lntp确认进程确实在监听对应端口再去查安全组能省掉一半来回。# 在 node-0001 上确认监听状态有 LISTEN 才说明是网络层的问题 ss -lntp | grep -E 9870|9000|8088这个坑之所以记下来是因为它太像“玄学”了所有命令都正常日志里什么错都没有就是打不开。搞不清楚状况的时候人会开始怀疑镜像、怀疑版本其实只是云平台那一层没放行。6. 快速定位先看哪一行再敲哪条命令排查这套集群问题我最后收敛成一个三步走的习惯比翻文档快得多。第一步永远是确认“我以为的环境”和“实际的环境”是不是同一个。很多人报错之后的第一反应是改配置但配置改动生效需要重启进程重启又依赖互信互信又依赖 hosts。这条链上任何一环断了你改的所有东西都不会生效。所以先跑这三条# 三条命令分别确认Java 环境、主机名解析、免密登录 bash -lc echo $JAVA_HOME readlink -f $(which java) javac -version getent hosts node-0001 node-0002 node-0003 ssh -o BatchModeyes -o ConnectTimeout5 node-0002 hostname三条全过说明基础环境没问题问题在 Hadoop 配置或者服务进程上任何一条不过先修它别往下走。第二步是按“报错位置”反推“配置位置”。下面这张表是我贴在备忘里的对应关系遇到报错先查表别从零开始想报错或现象优先检查具体看什么JAVA_HOME is not sethadoop-env.sh是否只有一处有效export JAVA_HOME路径下有没有bin/javac只有部分节点起不来/etc/hosts、slaves三台 hosts 是否一致slaves是否只有主机名Permission denied (publickey)~/.ssh权限目录 700、authorized_keys600公钥是否在对端Incompatible clusterIDs各节点数据目录current/VERSION里的 clusterID 是否一致No FileSystem for scheme: obscore-site.xml、jar 包fs.obs.impl是否拼错jar 是否在 classpath命令能跑但网页打不开安全组、ss -lntp端口是否监听、来源是否放行第三步是看日志而且只看第一处异常。Hadoop 的日志会级联一个 Java 环境问题能刷出几百行ERROR你从后往前看会看到一堆衍生错误。正确姿势是grep -n Caused by 日志文件 | head -3找到最内层那个异常它通常才是根因。# 按时间取最近的 NameNode 日志只揪最内层异常 ls -t $HADOOP_HOME/logs/hadoop-root-namenode-*.log | head -1 grep -n -A3 Caused by $(ls -t $HADOOP_HOME/logs/hadoop-root-namenode-*.log | head -1) | head -20-A3会连带打出异常后面三行栈信息的第一层通常就写清楚了是哪个文件、哪一行出的问题。这比把整个日志文件从尾到头翻一遍高效得多。从那以后我每次重建集群都会强制走一遍这几个确认步骤先验 Java 真实路径再验三台 hosts 一致再验六向免密最后才动format和start-dfs.sh。前面这几步每步只要十几秒却能省掉后面几个小时反复重启和自我怀疑。前面这几个步骤通过了还有个固定习惯是改任何配置都先rsync全量同步一次再重启不做“只改一台试试看”的操作集群环境里从来没有“只改一台”这回事。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询