Ubuntu上Hadoop 3.1.3单机与伪分布式安装配置全攻略 前阵子在一台闲置笔记本上折腾 Hadoop 环境翻了不少教程要么版本对不上、要么关键步骤直接跳过。单机和伪分布式这两种模式看起来简单真正操作起来还是有不少值得注意的地方。这篇文章把我整个操作过程、配置文件怎么改、踩过的坑全部整理出来希望能帮到正打算在 Ubuntu 上安装 Hadoop 3.1.3 的朋友。1. 装之前必须想清楚的三件事单机、伪分布式到底选哪个1.1 两种模式的区别与适用场景很多人第一次接触 Hadoop 时会被单机和伪分布式这两个词搞晕。简单说单机模式Local Mode下所有组件都在同一个 Java 进程里运行不启动 HDFS直接使用本地文件系统主要用于快速验证代码逻辑伪分布式模式Pseudo-Distributed Mode则是在一台机器上分别启动 NameNode、DataNode、ResourceManager、NodeManager 等独立进程每个进程都有自己的 JVM模拟出一个完整的分布式环境。以我实际体会来看单机模式适合刚入门时跑通 WordCount或者写 MapReduce 程序用来本地调试。伪分布式更适合想深入理解 HDFS 和 YARN 工作机制的同学文件上传、副本策略、资源调度都能真实走一遍流程。如果你的目标是准备面试或者做课程设计伪分布式绝对值得多花点时间如果只是想快速看到程序跑出结果单机模式十分钟就能搞定。1.2 JDK版本选择和Hadoop的兼容性Hadoop 3.1.3 官方文档明确支持 Java 8这一点务必牢记。我见过不少人在这里踩坑装了 JDK 11 或更高版本有的功能可以用但运行日志里总会冒出一堆奇怪的警告甚至某些 YARN 服务启动失败。个人建议直接用 OpenJDK 8稳定、够用、社区资料最丰富。另外环境变量JAVA_HOME必须在 Hadoop 的启动脚本能读到的位置后面章节我会给出完整的配置方式。提示Hadoop 3.1.3 对 JDK 的依赖不只是运行命令那么简单格式化 NameNode、启动 DataNode 等操作全部依赖 Java 环境。建议先把 JAVA_HOME 配好再碰 Hadoop后面会少很多麻烦。1.3 用户、目录和主机名的规划这一步看起来不起眼却直接影响后面所有操作的顺利程度。我强烈建议创建专用用户hadoop不要用 root 用户跑集群也不要直接塞在某个普通用户下。原因有两个第一Hadoop 的守护进程会写入大量临时数据和日志独立用户便于管理和清理第二Hadoop 的进程之间需要通过 SSH 进行无密登录专用用户配置免密会简单很多。推荐目录规划如下用途推荐路径Hadoop 安装目录/opt/hadoop/hadoop-3.1.3Hadoop 数据临时目录/home/hadoop/hadoop_data/tmpNameNode 元数据目录/home/hadoop/hadoop_data/namenodeDataNode 数据块目录/home/hadoop/hadoop_data/datanode当初我第一次装的时候图省事直接把数据目录放到/tmp下结果重启系统后所有数据被清空NameNode 状态全丢只能重新格式化。希望大家不要重蹈我的覆辙。另一个容易忽略的点是主机名解析。伪分布式模式虽然只在一台机器上运行但 NameNode 和 DataNode 之间通信时仍然需要通过主机名访问对方。确保/etc/hostname和/etc/hosts里的配置正确比如主机名是hadoop-node那 hosts 文件里至少要有127.0.0.1 hadoop-node这一行。2. 环境准备Ubuntu系统、JDK和SSH免密一次配齐2.1 更新系统与安装基础组件先做一次系统更新避免软件源里的包版本过期导致后续安装失败sudo apt update sudo apt upgrade -y接着安装一些基础工具包括 vim、net-tools、wget、curl 等。这些工具后面排查问题时会经常用到sudo apt install -y vim net-tools wget curl如果想关闭防火墙一劳永逸仅限测试环境可以执行sudo ufw disable我在实际环境里也推荐先关掉因为 Hadoop 的进程间通信端口很多逐个放行太麻烦学习阶段没必要在这上面浪费精力。生产环境则另当别论。2.2 安装JDK并配置JAVA_HOMEUbuntu 仓库里如果直接有 OpenJDK 8执行下面的命令即可sudo apt install -y openjdk-8-jdk安装后确认版本java -version正常情况下会显示类似openjdk version 1.8.0_xxx的信息。接着编辑/etc/profile.d/java.sh这个文件在部分系统里不存在可自行建一个写入以下内容export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 export PATH$PATH:$JAVA_HOME/bin执行source /etc/profile.d/java.sh使其立即生效然后运行echo $JAVA_HOME验证。这里是整个 Hadoop 环境的地基务必确认无误。注意如果系统源里没有 openjdk-8-jdk可自行下载 Oracle JDK 8解压到/usr/local/java再按同样的方式设置 JAVA_HOME。只要版本是 8路径不同不影响后续步骤。2.3 配置SSH免密登录伪分布式模式下NameNode 需要通过 SSH 连接 DataNode 和 NodeManager因此免密登录是必需步骤。切换到 hadoop 用户后执行ssh-keygen -t rsa -P 一路回车生成密钥对然后把公钥追加到 authorized_keyscat ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys测试一下ssh localhost如果没提示输密码就能登录说明配置成功。这个步骤单独看没什么技术含量但漏掉它会导致后面启动start-dfs.sh时不停卡在密码输入环节进程起不来还不容易发现原因。3. 单机模式实战Hadoop 3.1.3下载、解压与第一个MapReduce任务3.1 下载Hadoop源码包与目录规划Hadoop 3.1.3 的二进制压缩包可以从 Apache 官方镜像站下载文件名是hadoop-3.1.3.tar.gz。下载完成后放到/opt/hadoop目录下并解压sudo mkdir -p /opt/hadoop sudo tar -zxvf hadoop-3.1.3.tar.gz -C /opt/hadoop sudo chown -R hadoop:hadoop /opt/hadoop这里把目录所有者改为 hadoop 用户避免后续操作出现权限错误。解压后目录结构大致为bin启动脚本和命令行工具、etc/hadoop所有配置文件所在、sbin守护进程启停脚本、share/hadoopjar 包和示例程序。3.2 配置环境变量和hadoop-env.sh在/etc/profile.d/hadoop.sh中加入export HADOOP_HOME/opt/hadoop/hadoop-3.1.3 export HADOOP_CONF_DIR$HADOOP_HOME/etc/hadoop export PATH$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin执行source /etc/profile.d/hadoop.sh后在终端里输入hadoop version如果能输出版本信息说明 Hadoop 已经进入 PATH。接着编辑etc/hadoop/hadoop-env.sh这里的关键是设置JAVA_HOME。虽然系统环境变量已经配置了但 Hadoop 的某些守护进程启动脚本并不会加载/etc/profile.d/下的变量因此最好直接在这个文件里写死export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64我在这上面栽过跟头系统环境变量明明没问题但start-dfs.sh启动后 NameNode 进程总是退出去。查日志发现 JVM 参数解析失败罪魁祸首就是JAVA_HOME没有在 hadoop-env.sh 里设置。3.3 用WordCount验证单机模式单机模式不需要启动任何守护进程直接执行 MapReduce 任务即可。先准备一个测试文本words.txt随便写几行英文单词然后在 hadoop 安装目录下执行hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount words.txt output_single注意这里的words.txt是本地文件路径output_single是本地输出目录。执行结束后用cat output_single/part-r-00000就能看到每个单词出现的次数。在单机模式下输入和输出都在本地文件系统你能直观理解 MapReduce 的计算流程却看不到 HDFS 和 YARN 的参与。这也验证了前面提到的单机模式跑通逻辑很快但离分布式还有距离。4. 伪分布式核心配置文件逐项拆解伪分布式和单机的本质区别在于要启动 HDFS 和 YARN因此必须把配置文件按规则改好。所有文件都位于$HADOOP_HOME/etc/hadoop下。4.1 core-site.xml文件系统地址和临时目录修改core-site.xml添加以下两个属性configuration property namefs.defaultFS/name valuehdfs://localhost:8020/value /property property namehadoop.tmp.dir/name value/home/hadoop/hadoop_data/tmp/value /property /configurationfs.defaultFS决定了默认的文件系统地址hdfs://localhost:8020表示所有 Hadoop 路径操作都走 HDFS。这里端口可以自定义但要保证和后续 hdfs-site.xml 中配置的 NameNode RPC 端口一致。hadoop.tmp.dir指定集群运行时临时数据的存放位置必须手动创建mkdir -p /home/hadoop/hadoop_data/tmp4.2 hdfs-site.xml副本、NameNode和DataNode数据目录修改hdfs-site.xml这是整个伪分布式配置里最核心的部分configuration property namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name valuefile:///home/hadoop/hadoop_data/namenode/value /property property namedfs.datanode.data.dir/name valuefile:///home/hadoop/hadoop_data/datanode/value /property property namedfs.namenode.http.address/name value0.0.0.0:9870/value /property /configurationdfs.replication设置为 1因为单节点的伪分布式环境里多个副本除了白白占用磁盘空间没有任何意义。很多教程这里会忽略解释新手照抄时往往不理解为什么要设成 1这里的逻辑其实非常简单副本数的意义是防止数据丢失而伪分布式只有一个 DataNode副本根本放不出去。NameNode 元数据目录和 DataNode 数据块目录分别指定避免混在一起导致格式化时互相干扰。提示9870 是 Hadoop 3.x 版本 NameNode 的 Web UI 端口Hadoop 2.x 用的是 50070。如果你之前看过 2.x 的老教程注意别把端口搞混。4.3 mapred-site.xml与yarn-site.xml让MapReduce跑在YARN上原始安装包里只有mapred-site.xml.template这个模板文件需要先复制一份:cp $HADOOP_CONF_DIR/mapred-site.xml.template $HADOOP_CONF_DIR/mapred-site.xml然后添加configuration property namemapreduce.framework.name/name valueyarn/value /property /configurationmapreduce.framework.name指定 MapReduce 的任务调度交给 YARN。如果不配置这一项任务会尝试在 local 模式下直接运行虽不至于报错但完全不会走 YARN 的资源调度流程也就失去训练意义了。接着修改yarn-site.xmlconfiguration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property property nameyarn.nodemanager.env-whitelist/name valueJAVA_HOME,HADOOP_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH/value /property /configurationaux-services是 YARN 的辅助服务配置MapReduce 在 YARN 上运行时NodeManager 和 ApplicationMaster 之间需要依赖 shuffle 机制完成数据混洗因此这里必须声明mapreduce_shuffle。env-whitelist这个属性是很多新手遗漏的关键。当 nodeManager 启动容器时需要把 Hadoop 和 Java 相关的环境变量传递给子进程。如果不加这个配置MapReduce 任务一启动Container 内部就直接报出各种ClassNotFoundException而且报错信息特别难定位。4.4 为什么workers文件在伪分布式里同样重要Hadoop 3.x 里使用workers文件在 Hadoop 2.x 时叫slaves来标识哪些节点是 DataNode 和 NodeManager。单节点伪分布式的workers文件内容只有一行写上主机名hadoop-node注意这里的主机名必须和/etc/hosts里解析到localhost或127.0.0.1的那条记录对应。启动脚本会 SSH 到这个主机名上执行远程启动命令如果主机名解析不对NameNode 能起来DataNode 却始终启动失败。5. 启动验证全流程格式化、起服务、跑任务、看趋势5.1 格式化NameNode的时机与注意事项伪分布式模式下首次启动 HDFS 前必须格式化 NameNode这一步会初始化元数据目录hdfs namenode -format执行后看到successfully formatted字样说明成功。但请注意格式化操作有一个大坑格式化以后NameNode 和 DataNode 之间会建立一致的 namespace ID如果中途在 data 目录已经存在的情况下再次格式化会导致 DataNode 和 NameNode 的集群 ID 不一致DataNode 无论如何都启动不了。所以当你需要重新格式化时正确姿势是先把/home/hadoop/hadoop_data/namenode和/home/hadoop/hadoop_data/datanode两个目录下的内容清空再执行格式化命令。说实话我第一次装伪分布式时就犯了这个错误DataNode 日志反复报Incompatible namespaceIDs查了半天才反应过来。5.2 启动HDFS和YARN并检查进程启动 HDFSstart-dfs.sh启动 YARNstart-yarn.sh也可以直接用start-all.sh一次性启动所有进程。启动完成后执行jps看看有哪些 Java 进程在运行jps正常情况下应该看到六个进程进程名作用NameNode管理文件系统命名空间SecondaryNameNode辅助 NameNode 合并编辑日志DataNode实际存储数据块ResourceManager全局资源调度器NodeManager节点级资源管理Jps查看 Java 进程的工具本身如果缺少 DataNode 或 NodeManager直接第一步打开日志文件排查。DataNode 的日志在$HADOOP_HOME/logs/hadoop-hadoop-datanode-主机名.log这里面会写明异常信息。5.3 用Web界面和命令行双重验证服务状态浏览器访问http://localhost:9870这是 NameNode 的 Web 管理界面可以看到 HDFS 存储容量、存活节点数量、文件目录结构等信息。再访问http://localhost:8088这是 ResourceManager 的界面可以查看 YARN 集群状态、正在运行的任务队列和执行历史。用命令行做进一步验证hdfs dfsadmin -report这条命令会输出 DataNode 的在线状态、容量、磁盘使用情况。如果看到Live datanodes (1):说明 DataNode 注册成功。然后在 HDFS 上创建一个目录并上传本地文件hdfs dfs -mkdir -p /input hdfs dfs -put /home/hadoop/words.txt /input/这里如果报参数错误或者文件找不到先检查是不是hdfs dfs命令里的路径书写有问题HDFS 路径不能带中文或特殊空格。接着运行真正的分布式 WordCounthadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input /output注意/output目录在 HDFS 中不能预先存在否则控制台会直接提示输出目录已存在并终止任务。这是非常经典的一个坑。任务运行时会打印每个阶段的进度。跑完后查看结果hdfs dfs -cat /output/part-r-00000这一步和单机模式的最大区别是输入输出路径都指向 HDFS整个计算过程会经过 YARN 的资源调度和容器分配在 8088 界面上能实时看到 Application 的执行状态。6. 我在这套环境上踩过的坑与解决套路6.1 DataNode起不来的常见原因与修复DataNode 起不来是伪分布式装机中最频繁的问题。我这里遇到过的几类典型原因如下首先是namespace ID 不匹配这个前面提过了。解决方式就是把 namenode 和 datanode 数据目录都清空然后重新格式化并启动一步到位。其次是目录权限不足。因为用了sudo tar -zxvf解压安装目录的属主可能是 root但启动脚本以 hadoop 用户运行写日志和数据块时就没有权限。解决办法是重新chown -R hadoop:hadoop /opt/hadoop和/home/hadoop/hadoop_data。第三类是workers 文件配置错误。如果这个文件里写的主机名在 hosts 里查不到DataNode 启动时就会卡在 SSH 连接上最终进程退出。建议先把 hosts 里的127.0.0.1 主机名加好再执行ssh 主机名测试一遍确认免密有效。6.2 端口冲突、防火墙和主机名解析问题Hadoop 3.1.3 的伪分布式模式会用到多个端口其中最常见的冲突有NameNode RPC 默认使用 8020如果被其他服务占用启动会失败NameNode HTTP 使用 9870ResourceManager 使用 8088可以用netstat -tlnp | grep 端口号查看占用情况。伪分布式环境里经常发现 8088 被其他 Web 服务占用最简单的办法是把 web 端口改掉比如在 yarn-site.xml 中修改property nameyarn.resourcemanager.webapp.address/name value0.0.0.0:8089/value /property如果防火墙没有关闭即使进程都启动成功外部浏览器也访问不了 Web UI。测试环境优先考虑ufw disable这一点在 2.1 已经提过。主机名解析问题同样值得注意不要以为安装了 Hadoop 后主机名就一定可用ping $(hostname)要是解析不了日志里会出现java.net.UnknownHostException看到这个异常第一反应就该去检查 hosts。6.3 重新格式化后数据丢失的预防建议伪分布式的本质决定了一切都在一台机器上格式化 NameNode 会清空元数据而 DataNode 里的数据块如果没有被同步清理就会出现存储状态不一致。这里我给三个经验性的建议。一是在动手格式化前先备份name.dir目录里的current/内容和 HDFS 日志里的关键启动信息一旦启动失败还能靠备份恢复元数据状态去定位问题二是宁可多花 30 秒清空两个数据目录也别赌格式化没关系数据目录存过的旧数据会残留大量in_use.lock等状态文件不清干净必然导致各种诡异异常三是想清楚格式化操作的真实目的它相当于重新初始化整个文件系统的元数据。如果在 HDFS 里已经存了重要数据格式化前务必通过hdfs dfs -get把所有文件拉到本地。此外还有一个我在使用中积累的小细节如果你只是修改了配置文件想重启服务不要一股脑跑start-all.sh和stop-all.sh可以分开操作。例如只修改了 yarn-site.xml就只执行stop-yarn.sh再start-yarn.sh只修改了 hdfs-site.xml就重启 DFS。这样减少整个环境的不必要波动排查问题时的日志跨度也更小。整套环境搭完以后日常使用时最常做的工作就是通过 Web UI 观察任务执行、用命令行管理 HDFS 文件。最后分享一个我遇到的奇怪问题明明所有配置都对用hdfs dfs -ls /也能正常列出目录但用hadoop fs -ls /却没有任何输出。这是因为hadoop fs命令在对 HDFS 操作时会按fs.defaultFS拼接路径老版本工具在某些配置下有兼容性问题。遇到这种情况直接用hdfs dfs而非hadoop fs就能绕开这也是踩过几次坑之后总结出来的经验。希望这篇记录能帮你少走一些弯路。