☰
Ubuntu上Hadoop 3.1.3单机与伪分布式安装配置全攻略
2026/10/21 23:16:39 网站建设 项目流程

前阵子在一台闲置笔记本上折腾 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.3
Hadoop 数据临时目录/home/hadoop/hadoop_data/tmp
NameNode 元数据目录/home/hadoop/hadoop_data/namenode
DataNode 数据块目录/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_HOME

Ubuntu 仓库里如果直接有 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_keys:

cat ~/.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/hadoop(jar 包和示例程序)。

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> <name>fs.defaultFS</name> <value>hdfs://localhost:8020</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/home/hadoop/hadoop_data/tmp</value> </property> </configuration>

fs.defaultFS决定了默认的文件系统地址,hdfs://localhost:8020表示所有 Hadoop 路径操作都走 HDFS。这里端口可以自定义,但要保证和后续 hdfs-site.xml 中配置的 NameNode RPC 端口一致。hadoop.tmp.dir指定集群运行时临时数据的存放位置,必须手动创建:

mkdir -p /home/hadoop/hadoop_data/tmp
4.2 hdfs-site.xml:副本、NameNode和DataNode数据目录

修改hdfs-site.xml,这是整个伪分布式配置里最核心的部分:

<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:///home/hadoop/hadoop_data/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:///home/hadoop/hadoop_data/datanode</value> </property> <property> <name>dfs.namenode.http.address</name> <value>0.0.0.0:9870</value> </property> </configuration>

dfs.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> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>

mapreduce.framework.name指定 MapReduce 的任务调度交给 YARN。如果不配置这一项,任务会尝试在 local 模式下直接运行,虽不至于报错,但完全不会走 YARN 的资源调度流程,也就失去训练意义了。

接着修改yarn-site.xml:

<configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.nodemanager.env-whitelist</name> <value>JAVA_HOME,HADOOP_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH</value> </property> </configuration>

aux-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并检查进程

启动 HDFS:

start-dfs.sh

启动 YARN:

start-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 路径不能带中文或特殊空格。

接着运行真正的分布式 WordCount:

hadoop 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 使用 9870,ResourceManager 使用 8088

可以用netstat -tlnp | grep 端口号查看占用情况。伪分布式环境里经常发现 8088 被其他 Web 服务占用,最简单的办法是把 web 端口改掉,比如在 yarn-site.xml 中修改:

<property> <name>yarn.resourcemanager.webapp.address</name> <value>0.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就能绕开,这也是踩过几次坑之后总结出来的经验。希望这篇记录能帮你少走一些弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询