我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

鲲鹏云Hadoop集群搭建避坑:JAVA_HOME、SSH互信与OBS配置排查

鲲鹏云Hadoop集群搭建避坑:JAVA_HOME、SSH互信与OBS配置排查 简介面向高校学生与云计算初学者的一份鲲鹏云大数据实验文档聚焦在华为云环境中从零搭建并跑通Hadoop集群这一常见难题属于入门到进阶之间的实操型实验记录。压缩包内仅有1个docx文件约2.52MB以图文混排形式完整保留实验过程与配置细节便于边看边对照操作。目前已有893人学习说明该实验路径在同类课程中具有一定参考需求。内容覆盖购买与配置ECS、OBS并行文件系统及AK/SK密钥获取节点间hosts解析与SSH免密互信core-site.xml、hdfs-site.xml、yarn-site.xml、mapred-site.xml与slaves等核心配置以及Java家目录指向错误导致的重新分发、NameNode初始化与HDFS启动等排错过程读者可据此理解云上大数据基础设施的部署顺序与常见故障定位思路。1. 从一次“前七步都对第八步全崩”的搭建说起hadoop namenode -format跑下去终端直接回一行Error: JAVA_HOME is not set and could not be found。可你明明装过 JDKjava -version也能正常打出 1.8.0_242。这个坑在鲲鹏云上搭 Hadoop 集群的实操里出镜率极高翻这份鲲鹏云大数据实验报告时能看到同一个 Java 路径问题被反复标注了四五次——配置环境变量时错、分发安装包时错、NameNode 初始化时错、启动 HDFS 时错、执行 hdfs 命令时还错。表面看是五个故障根子上却只有一处java -version走的是PATHHadoop 启动脚本走的是JAVA_HOME指向的那个绝对路径两条路根本不是一回事前者通不代表后者通。再叠加节点互信没打通、OBS 的 AK/SK 填错位这两类高频翻车点一个看起来只有十几步的实验能把人卡上整整一个下午。这篇按我实际踩过的顺序走先拆 Java 路径这个总根因再讲节点互信和对象存储接入两处最容易配错的细节最后落一份能照着抄的避坑清单和定位路径。2. JAVA_HOME 指错格式化、启动、hdfs 命令全线报错这一章要先定位一个根本原因它是整套实验里牵连最广、最容易被误判的故障源头。原始记录里的细节很清楚节点上装了 openjdk/etc/profile里也加了环境变量可 Hadoop 的环境变量配置执行失败接着 NameNode 初始化报错、HDFS 起不来、hdfs命令也执行失败全部改对JAVA_HOME之后才逐一恢复正常。这种“一改全通”的现象说明它不是五个独立 bug而是一个问题在五个环节的投影。2.1 报错现场脚本说找不到 JAVA_HOME终端里 java 却能跑先把现象摆清楚。你执行下面三条命令会得到互相矛盾的结果# 终端里 java 明明在 java -version # 环境变量看着也设置了 echo $JAVA_HOME # 但 Hadoop 就是不认 hadoop versionjava -version有输出是因为 shell 通过PATH找到了某个java可执行文件hadoop version报JAVA_HOME is not set and could not be found是因为每个 Hadoop 脚本开头都有一句类似exec $JAVA_HOME/bin/java ...的调用脚本只认JAVA_HOME拼出来的绝对路径路径上没有可执行文件就直接退出。这两套查找机制互不相干所以完全可能出现“java 能跑Hadoop 说没有 Java”。更隐蔽的一种形态是JAVA_HOME路径确实存在脚本检查也能通过但指向的是另一套 JDK于是报UnsupportedClassVersionError或者Could not reserve enough space for object heap。这类报错更难往 Java 路径上想很多人会去翻yarn-site.xml的内存参数绕一大圈才回到原点。定位动作只有一步看java到底从哪来# which 看 PATH 命中的是谁 which java # readlink -f 追到软链接的最终真实路径 readlink -f $(which java)readlink -f的输出会是类似/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-1.h5.oe1.aarch64/jre/bin/java的绝对路径。这个字符串就是判断JAVA_HOME该写什么的唯一依据凭记忆写或者照抄别人的博客基本都会翻车。2.2 为什么在鲲鹏上路径必须写到 aarch64 那一层问题出在包名上。x86 平台上很多人习惯写/usr/lib/jvm/java-1.8.0-openjdk这个短路径能生效是因为发行版通常会给一份不带版本号后缀的目录或软链接。而在鲲鹏这种 aarch64 架构的机器上通过包管理器装出来的 JDK 目录名带完整版本号与架构后缀形如java-1.8.0-openjdk-1.8.0.242.b08-1.h5.oe1.aarch64/usr/lib/jvm/下压根没有那个“干净”的短路径。你把短路径写进配置脚本去.../java-1.8.0-openjdk/bin/java找文件找不到于是报错。正确的写法是带上完整目录名# 以 readlink -f 的真实输出为准这里按实际路径替换 export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-1.h5.oe1.aarch64 export PATH$JAVA_HOME/bin:$PATH # 立刻验证不要等到启动集群时才发现 $JAVA_HOME/bin/java -version三条命令的分工是第一行把JAVA_HOME钉死在真实目录上第二行把该目录下的bin前置到PATH保证java、javac、jps都来自同一套 JDK第三行用绝对路径调用一次绕开PATH缓存确认这个路径下确实有一个能跑的 java。养成用绝对路径验证的习惯能省掉一类“改完了还是不对”的自我怀疑。注意JAVA_HOME指到.../aarch64这一层即可不要指到.../aarch64/jre。部分组件会自己拼/jre/bin/java指到 jre 层会出现/jre/jre/bin/java这种双重拼接的路径。环境变量写进/etc/profile之后还必须source一次而且只能在当前会话生效新开的 SSH 连接会自动读到——这一点在下一节的“重新分发”中会变成一个关键差异。2.3 改完 JAVA_HOME 之后为什么必须重新分发一遍这是整章最容易被忽略的一步也是那份实验记录里反复出现“重新配置分发”“重新分发”“因为 javahome 错误重新分发”的原因。hadoop-env.sh这个文件是跟着 Hadoop 安装包一起分发的你在node-0001上先写错了JAVA_HOME然后scp -r把整个hadoop-2.8.3目录推到node-0002和node-0003那么三台机器上的hadoop-env.sh就都带着同一个错误值。这时候你只在node-0001上改了另外两台没动启动脚本推过去一样起不来报错还跟之前一模一样容易让人以为“改了没用”。所以改动要按“先改一台、验证、再统一分发”的顺序走# 1. 在 node-0001 上定位并修改 hadoop-env.sh 里的 JAVA_HOME cd /home/modules/hadoop-2.8.3/etc/hadoop # 把被注释掉的或写错的 JAVA_HOME 那一行替换成真实路径 sed -i s|^#*\s*export JAVA_HOME.*|export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-1.h5.oe1.aarch64| hadoop-env.sh # 2. 确认只有一处生效的 JAVA_HOME避免文件里留了多行互相覆盖 grep -n JAVA_HOME hadoop-env.sh # 3. 本机先验证通过再分发 hadoop versionsed那一行的含义是匹配行首可选的#和空白后面接export JAVA_HOME的整行替换成你要的那一行。用sed而不是手工vim是为了让三台机器的结果完全一致——手工改最容易出现多空格、少引号、行尾多一个字符这类肉眼难辨的差异。第三行的hadoop version是放行条件本机不过就不要再往下推。分发用scp -r或者rsync -av都可以关键是要覆盖到etc/hadoop整个目录而不是只推那一个文件# 把改好的配置目录推到另外两个节点覆盖旧的错误值 for ip in 120.46.156.37 121.36.3.111; do scp -r /home/modules/hadoop-2.8.3/etc/hadoop/ root$ip:/home/modules/hadoop-2.8.3/etc/hadoop/ done循环里两个 IP 是另外两个节点的地址scp -r覆盖同名文件时不提示所以不需要加-f。分发完成后每台机器都要执行一次source /etc/profile原因是JAVA_HOME还单独写在了/etc/profile里而hadoop-env.sh是 Hadoop 脚本自己读的两边都对才行。很多“明明改了还是报错”的情况就是改了hadoop-env.sh忘了改/etc/profile或者反过来。2.4 验证顺序三条命令按依赖关系排改完之后不要直接去跑start-dfs.sh按下面这个顺序走一遍能在最便宜的位置拦住问题# 第一层Java 本身是否可用 java -version # 第二层Hadoop 脚本是否认到了 Java hadoop version # 第三层进程是否真的起来了 jps第一条不通过说明/etc/profile或包安装有问题第一条过、第二条不过问题一定在hadoop-env.sh里的JAVA_HOME前两条都过但jps只看到Jps自己那才是 HDFS 配置或启动参数的问题Java 这一层可以排除了。这个三段式验证的价值在于它把“Java 路径”和“Hadoop 集群”两个层面切开不让你在集群日志里翻半天最后发现只是环境变量少了一级目录。3. 节点互信没配通ssh 还要密码scp 分发直接卡住集群搭建的第二类高频故障出在节点之间。原始记录里每台节点都做了同一组动作vim /etc/hosts、cat /root/.ssh/id_rsa.pub、把公钥追加到授权文件、然后验证“无密码跳转”。这几步看着简单但配置失败的形态很隐蔽——ssh有时候直接进不去有时候能进但要输密码还有时候ssh能进、scp却卡住不动。一旦互信没有配置好后面所有依赖“从主节点推送到子节点”的操作都会失败。3.1/etc/hosts里主机名和 IP 没对齐ssh 直接超时第一个动作是把主机名映射写进/etc/hosts。这一步失败的典型表现是ssh node-0002卡住十几秒然后Connection timed out但ssh 120.46.156.37是通的。这说明网络本身没问题是主机名解析走错了路——要么/etc/hosts里根本没写要么写的是别的主机名要么同一台机器在文件里出现了两行不同 IP解析取到了旧的那条。# 每台节点都要有一份完整且一致的主机名映射 cat /etc/hosts EOF 10.0.0.11 node-0001 10.0.0.12 node-0002 10.0.0.13 node-0003 EOF # 验证解析结果别只看文件内容 getent hosts node-0002追加进去的三行 IP 请换成你自己控制台里看到的私网地址主机名要和hostname命令的输出严格一致——大小写、连字符、下划线都算不同名字。第二行的getent hosts走的是系统实际使用的解析链路能暴露“文件里写了但被别的配置抢先”的情况比cat一眼更可靠。三台机器上的这份文件必须完全相同任何一台缺行都会在那台机器上表现为“别人连得进我我连不出去”。注意主机名映射优先写私网地址。写公网地址在带宽和时延上都不划算而且在部分网络环境下公网回环会导致scp传到一半断开。3.2 公钥追加与权限.ssh目录和文件的三个权限位第二个动作是把id_rsa.pub的内容追加到目标节点的authorized_keys。这一步最常见的两种失败一是用覆盖而不是追加把之前配好的公钥全冲掉了二是权限不对ssh 出于安全策略直接拒绝使用这个文件而且默认不告诉你原因。# 在每台节点上生成密钥对已有则跳过不要重复生成覆盖旧的 ssh-keygen -t rsa -N -f /root/.ssh/id_rsa # 把三台节点的公钥汇总追加到三台的 authorized_keys追加不是覆盖 for ip in 10.0.0.11 10.0.0.12 10.0.0.13; do cat /root/.ssh/id_rsa.pub | ssh root$ip cat /root/.ssh/authorized_keys done # 修权限这三条缺一条都可能被静默拒绝 chmod 700 /root/.ssh chmod 600 /root/.ssh/authorized_keys chmod 600 /root/.ssh/id_rsassh-keygen的-N 表示不设密码短语集群内部自动登录必须无口令设了密码短语每次都要交互输入脚本就断在那里。循环里的cat 是关键用才能保证多台机器的公钥共存如果第一台执行时文件不存在会自动创建不用提前touch。三条chmod分别对应目录、授权文件、私钥权限过宽时 sshd 会认为文件不可信而跳过表现出来就是“公钥明明在里面却还要密码”。改完权限后重登一次再测因为 ssh 客户端有连接复用不重开会沿用旧状态# 带 -v 看握手细节认证失败会明确打出尝试过哪些公钥 ssh -v node-0002 hostname-v的输出里找Offering public key和Authentication succeeded这两行。如果只看到Offering没看到succeeded说明公钥被拒绝了回头查权限如果连Offering都没有说明 ssh 压根没找到你的私钥去查id_rsa是否存在、~/.ssh/config有没有指定别的 IdentityFile。这个排查顺序比反复重生成密钥高效得多。3.3 用一条循环把全部节点验证一遍互信是 N 对 N 的关系手工一台台试容易漏。一条循环能一次性把矩阵跑完# 遍历所有节点逐台验证免密登录是否成立 for host in node-0001 node-0002 node-0003; do printf %-12s $host ssh -o BatchModeyes -o ConnectTimeout5 $host echo OK 2/dev/null || echo FAIL doneBatchModeyes让 ssh 在需要交互输入时直接失败而不是挂住等输入这样循环不会卡在某一台上ConnectTimeout5给每台机器 5 秒上限避免网络不通时脚本长时间空转2/dev/null把冗长的错误信息吞掉让输出保持成一列OK/FAIL。三个节点全部OK之后再往下走分发否则后面每一条scp都会以同样的方式失败把真正的根因淹没在一堆重复报错里。4. OBS 接不进去AK/SK 与 endpoint 填错位的三种报错Hadoop 集群本身跑起来之后第三个卡点往往出现在对象存储接入上。实验里用对象存储做数据存放需要在core-site.xml里填认证信息和访问地址而这几项参数恰好是最容易抄错、错一个字就完全不通的部分。原始记录里提到创建桶之后会得到一个credentials.csv里面有三列User Name、Access Key Id、Secret Access Key。这三个值对应到配置里的位置、以及 endpoint 该选哪个地址是这一节要拆清楚的事。4.1 credentials.csv 三列和配置项的对应关系很多人出错不是不会填而是把 AK 和 SK 填反了或者把 User Name 当成了 Access Key。先明确对应关系csv 中的列含义填到core-site.xml的哪个属性User Name账号名仅用于标识不参与认证填了也没用Access Key Id访问密钥 ID公开部分fs.obs.access.keySecret Access Key私钥保密部分fs.obs.secret.key对应到配置片段大致是这样configuration property !-- 访问密钥 ID取自 credentials.csv 的 Access Key Id 列 -- namefs.obs.access.key/name value你的AccessKeyId/value /property property !-- 私钥取自 Secret Access Key 列注意不要带引号 -- namefs.obs.secret.key/name value你的SecretAccessKey/value /property property !-- 对象存储的访问域名见下一小节的选择规则 -- namefs.obs.endpoint/name valueobs.cn-north-4.myhuaweicloud.com/value /property /configuration三个value里只有第一个键是公开的后两个属于敏感信息。把私钥贴进配置文件、配置文件再被分发到各节点、最后提交进版本库是这类实验里最常见的泄露路径所以我一般会在实验结束后把这套密钥直接删掉重建。填充时特别注意csv 里的值不带引号也不带空格复制粘贴时最容易带进一个不可见的行尾空格导致签名校验一直失败而报错信息只说权限不足。4.2 endpoint 选 IPv4 还是双栈两个域名不能混用对象存储给了两个访问地址一个是 IPv4 的obs.cn-north-4.myhuaweicloud.com另一个是双栈的obs.dualstack.cn-north-4.myhuaweicloud.com。这两个不是“主备”关系而是面向不同网络栈的两套入口选错的表现是域名解析失败或者连接超时。# 先确认当前机器能解析哪个域名再决定填哪个 getent hosts obs.cn-north-4.myhuaweicloud.com getent hosts obs.dualstack.cn-north-4.myhuaweicloud.com第一条有返回、第二条没有就老老实实用 IPv4 那个两条都有返回用 IPv4 更省事因为它对客户端的要求最低。不要因为“双栈听起来更先进”就选它——如果你的客户端所在网络对 IPv6 的支持不完整连接会先尝试 IPv6 然后超时回退表现为每次访问都慢几秒甚至直接失败日志里只有一句含糊的Connection timed out。这个现象很像集群性能问题实际上只是域名选错了。core-site.xml改完之后同样要分发到所有节点并且分发完不需要重启整个集群但需要让新的配置生效# 分发配置 for ip in 120.46.156.37 121.36.3.111; do scp /home/modules/hadoop-2.8.3/etc/hadoop/core-site.xml root$ip:/home/modules/hadoop-2.8.3/etc/hadoop/ done # 让 NameNode 重新加载配置 hdfs dfsadmin -refreshNodesscp只推单个文件因为这一步只改了core-site.xml没必要整目录覆盖。refreshNodes用于让 NameNode 重新读取节点相关配置配合重启相关服务使用如果改动涉及客户端访问路径最稳妥的做法还是重启一次 HDFS 服务避免部分进程还持有旧配置。判断是否需要重启的标准是改动影响的是服务端还是客户端。服务端的core-site.xml改了就重启纯客户端的配置分发后新起的命令自然生效。4.3 用一次列目录把链路走通配置对不对不要靠猜用一条命令验证到底# 列出对象存储桶根目录能列出来就说明认证和 endpoint 都通了 hadoop fs -ls obs://你的桶名/这条命令走的是完整的“读配置 → 签名请求 → 访问 endpoint → 返回列表”链路任何一环有问题都会在这里暴露。常见返回与对应根因如下AccessDeniedAK/SK 其中一项填错或者两列填反了回头对 csv 逐字符比。UnknownHostExceptionendpoint 域名拼错或者当前机器解析不了这个域名回到 4.2 用getent hosts确认。NoSuchBucket桶名写错或者桶不在这个 endpoint 对应的区域跨区域的桶必须换区域域名。长时间无响应后超时多半是 endpoint 选成了双栈但本机 IPv6 不通换回 IPv4 域名重试。把这条命令的返回结果和上面对照表比对比翻 Hadoop 的日志快得多因为日志里这类错误往往被包装成几层IOException真正的错误码埋在最里面。5. 避坑清单五个在鲲鹏云上搭 Hadoop 反复踩的坑下面五条都来自这套实验里真实出现过的失败按“现象 → 原因 → 解决”写遇到对得上的直接照做。坑一hadoop version报 JAVA_HOME 找不到。现象是终端里java -version正常Hadoop 相关命令全部失败。原因通常是JAVA_HOME写成了不带版本号的短路径在 aarch64 机器上根本不存在这个目录。解决方式是用readlink -f $(which java)拿到真实路径把它完整写进hadoop-env.sh和/etc/profile然后source并重新分发到所有节点。坑二只改了主节点子节点还在跑旧配置。现象是主节点上一切正常从子节点启动或者从主节点远程拉起时又报同样的错。原因是hadoop-env.sh随安装包一起被分发过错误值已经复制到了每台机器。解决方式是把etc/hadoop整目录重新推一遍推完每台机器执行source /etc/profile再用jps逐台确认进程。坑三ssh node-0002卡住或提示输密码。现象是 IP 能 ping 通、ssh却超时或者反复要密码。原因要么是/etc/hosts里主机名没写全或写重了要么是authorized_keys权限过宽被 sshd 拒绝。解决方式是用getent hosts验证解析结果用chmod 700/600修权限再用ssh -v看握手日志里有没有Authentication succeeded。坑四hadoop fs -ls obs://桶名/报 AccessDenied。现象是配置都填了、集群也起来了就是读不到对象存储。原因是fs.obs.access.key和fs.obs.secret.key两列填反或者粘贴时带了行尾空格。解决方式是对着credentials.csv逐字符比对重新分发core-site.xml并重启 HDFS 服务再用同一条ls命令验证。坑五同一个“Java 路径错误”在五个环节重复出现被当成五个 bug。现象是环境变量报错、格式化报错、启动报错、hdfs命令报错逐个去修改完一个另一个又冒出来。原因是这些环节共用同一个JAVA_HOME配置源头没修下游全部连着倒。解决方式是先停下来做一次三段式验证java -version→hadoop version→jps确认 Java 这一层是干净的再去看具体环节避免在症状上反复打补丁。6. 快速定位从报错关键词到根因的三分钟路径真到了现场最耗时间的不是修而是判断这串报错属于哪一层。我习惯按“报错关键词 → 可能层级 → 第一条验证命令”做一次快速分诊把范围从“整个集群”缩到“一个配置文件”。报错关键词大概率层级第一条验证命令JAVA_HOME is not setJava 环境变量readlink -f $(which java)UnsupportedClassVersionErrorJDK 版本不匹配$JAVA_HOME/bin/java -versionConnection timed outssh主机名解析getent hosts node-0002Permission denied (publickey)互信与权限ssh -v node-0002 hostnameAccessDeniedAK/SK 配置对照credentials.csv逐字符比UnknownHostExceptionendpoint 域名getent hosts obs.cn-north-4.myhuaweicloud.comNoSuchBucket桶名或区域回控制台核对桶名与区域进程缺失jps少进程启动脚本与配置看logs/下对应角色的.log拿到报错先在上表里找关键词不要一上来就tail -f全量日志。找到层级之后执行对应的那条验证命令一条命令就能确认或排除这一层。如果命令返回正常说明问题在更下游往下走一层如果返回异常直接就地修不要再往下查。这个思路能把排查成本从“翻几千行日志”降到“跑三条命令”。分诊之后还有两个细节值得刻意做。第一改任何配置前先备份原文件cp core-site.xml core-site.xml.bak一行的事但能让你在改崩之后三十秒回到上一个状态。第二每次只改一个变量然后立刻验证不要一次改五处再一起试——五处一起改、结果好了你也不知道是哪一处起的作用下次遇到同样的问题还是不会。还有一条更省事的习惯把“三台机器的同一个文件是不是完全一致”当成一个常规检查项。集群类实验里绝大多数诡异现象追到底都是某台机器上的某个文件跟别人不一样。一条md5sum就能比出来# 在三台机器上分别执行比对同一个配置文件的摘要 md5sum /home/modules/hadoop-2.8.3/etc/hadoop/core-site.xml三行输出一致说明分发到位有一行不同就单独把那个文件重推一次。这个动作花不了十秒但能挡掉一大类“看起来都配了就是不生效”的困惑。从那以后我每次动 Hadoop 配置都强制走一遍“改一台 →hadoop version验证 → 整目录分发 → 三台md5sum比对 → 再启动”这个流程宁可多花两分钟也不愿意在启动失败之后回头猜是哪台机器没同步。希望这套顺序能帮你少卡一个下午。这份鲲鹏云大数据实验文档把从云主机与对象存储的准备、节点互信、Hadoop 分发与配置到 NameNode 初始化和 HDFS 启动的每一步都记了下来连出错后怎么回改都留了痕迹需要对照原始步骤复现的可以直接取用。本文还有配套的精品资源点击获取
返回列表