☰
Hadoop单机版部署测试全流程:从环境准备到WordCount踩坑记录
2026/10/14 21:51:50 网站建设 项目流程

折腾了整整一下午,终于把 Hadoop 单机版部署测试完整跑通了。这事情说起来不复杂,但坑确实不少:环境变量、SSH 免密、格式化时机、进程死活、作业卡住……每一项都能让你怀疑人生。如果你现在也在准备从零部署一套 Hadoop,我的建议很直接:别一上来就搭集群,老老实实把单机版部署测试做扎实,后面理解分布式才有底气。

这篇文章我会按自己实际的部署过程来写,覆盖“单机版/伪分布式”的完整链路:环境准备、JDK 和 SSH、下载解压、核心配置、NameNode 格式化、启动验证、HDFS 命令、WordCount 作业、Web UI,以及我当时踩过的各种坑。目标读者是刚接触 Hadoop 的开发者,也适合准备做课程实验、客户端工具联调、本地功能验证的朋友。你可以直接照着我给的操作步骤抄作业,遇到问题时跳到第 6 节看排查思路。

1. 先弄清楚:这次部署测试要“测”什么

很多人拿到 Hadoop 安装包第一反应是解压、改配置、敲启动命令,结果进程起一半就开始迷茫。我建议先花五分钟想清楚:单机版部署测试到底要验证什么?只有把这个想明白了,后边的每一步才不容易跑偏。

1.1 单机版是哪个“单机版”

Hadoop 有三种运行模式,网上教程里经常混着叫“单机版”,如果你不搞清楚,很容易拿错配置方案。

  • 本地模式(Local Mode):什么都不用配置,解压完直接能跑 MapReduce,所有组件都跑在同一个 JVM 里,用本地文件系统,不启动 HDFS 和 YARN 守护进程。它适合开发调试 MR 程序逻辑,严格来说谈不上“部署”。
  • 伪分布式模式(Pseudo-Distributed Mode):所有 Hadoop 进程(NameNode、DataNode、ResourceManager 等)都跑在同一台机器上,但各自是独立 JVM,文件系统是真的 HDFS,调度是真的 YARN。这是学习 Hadoop 最划算的模式,也是本题“单机版部署测试”最常见的指向。
  • 完全分布式模式(Fully-Distributed Mode):至少三台机器以上,分别跑不同角色。生产环境用这种,但它是建立在伪分布式之上的进阶操作。
模式是否启动守护进程是否使用 HDFS是否使用 YARN主要用途
本地模式否否否调试 MapReduce 程序
伪分布式是是是学习部署、测试组件联动
完全分布式是,且分散多机是是生产或仿真集群

我下面的配置按照“伪分布式”来写。如果你只是想快速跑起来看效果,本地模式其实你解压完就可以hadoop jar跑示例,但那并不能验证部署这件事。标题既然带着“部署”二字,最终要看到 HDFS、YARN、作业调度都动起来才算数。

1.2 部署测试的验收标准

我说一下我给自己定的验收清单,你部署完了对着打钩就行:

  1. java -version和hadoop version都能正常输出,说明 JDK 和 Hadoop 的环境变量生效。
  2. ssh localhost不用输密码就能登录,这是启动脚本能拉起远程进程的前提。
  3. 执行jps能看到 NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager 五个进程都在。
  4. HDFS 命令能创建目录、上传文件、读取文件,说明文件系统 API 链路通。
  5. 跑一个 WordCount MapReduce 作业,能看到 Map 100% 和 Reduce 100%,并且输出结果正确。
  6. 浏览器能打开 NameNode 的 9870 端口和 YARN 的 8088 端口。

这六条全过,你的单机版部署测试就算真正通过。后面学完全分布式时,很多概念直接复用这套心智模型。

2. 环境准备:资源规划、JDK 与 SSH

Hadoop 部署最怕三件事:内存不够、Java 没装对、SSH 登录不过。这三样全坐在“环境准备”这一关,所以这一部分我写得啰嗦一点。

2.1 资源规划

伪分布式虽然只用一台机器,但进程数量不少。NameNode、DataNode、SecondaryNameNode 各自是独立 JVM,YARN 的 ResourceManager 和 NodeManager 又是两个 JVM,再加一个跑作业时临时拉起的 ApplicationMaster 和 Container,随便就是 6 到 8 个 JVM。

这里单独提个醒:我给一台 2 核 4G 的虚拟机部署过,能跑,但作业调度明显很紧张。如果你的机器只有 2G 内存,建议把桌面环境关掉,多留点空闲内存给 JVM。否则你可能会看到进程刚起来就被系统 OOM 杀掉,或者作业一直卡在 ACCEPTED 状态,进度条怎么都不动。

磁盘方面完全不用担心,单机测试副本数设置为 1,数据不会膨胀。预留 5GB 左右给 Hadoop 的临时目录、日志和测试文件就足够了。

操作系统以 Linux 为主。Windows 上跑 Hadoop 3.x 需要额外处理权限和本地库问题,新手不建议尝试。如果你手里只有 Windows,先用虚拟机方案装一个最小化 Linux,部署思路完全一致。

2.2 JDK 安装与环境变量

Hadoop 基于 Java 开发,运行环境必须有 JDK。我优先选择 JDK 8,原因很简单:Hadoop 3.x 官方对 JDK 8 支持最成熟,生态里面的 Hive、HBase、Spark 也基本都能兼容 JDK 8。你装 JDK 11 也没问题,但没必要在新手阶段给自己找兼容性麻烦。

安装 JDK 的方式根据发行版不同有差异,一般用系统自带包管理器装,比如apt或yum。装完先找一下 JDK 的绝对路径,后面要写进 Hadoop 脚本。位置通常类似/usr/local/jdk或/usr/lib/jvm/java-8-openjdk-amd64,具体以你机器为准。

然后配置系统级环境变量,建议在/etc/profile.d/下新建一个hadoop.sh文件,内容如下:

export JAVA_HOME=/usr/local/jdk export HADOOP_HOME=/usr/local/hadoop export PATH=$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH

为什么我不建议你把环境变量直接塞进~/.bashrc?因为 Hadoop 的启动脚本经常在非交互式 shell 里执行,~/.bashrc不一定被加载,而/etc/profile.d/下的脚本对所有登录 shell 都会生效。这个细节能帮你少踩一个隐蔽的坑。

改完执行source /etc/profile.d/hadoop.sh,然后验证:

java -version

如果输出里能看到 Java 版本号,JDK 就位了。注意 Hadoop 脚本本身不负责找 Java,它只认JAVA_HOME这个变量。很多人报“找不到主类”“无法运行 Hadoop”都是因为这个变量没配对。

2.3 SSH 免密登录:为什么它决定了启动成败

你可能觉得本地单机部署为什么要配 SSH?Hadoop 的start-dfs.sh脚本会通过 SSH 连接到 localhost 去逐一启动节点进程。如果没有免密,脚本会在每一个进程启动时停下来问你要密码,甚至直接报 Permission denied。

配置过程很简单:

ssh-keygen -t rsa -b 4096 -P '' -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys

然后立即验证:

ssh localhost

如果直接回到命令行,不需要密码,就说明免密配置成功。

这里有个容易忽略的关键点:如果当前主机名不是 localhost,Hadoop 内部解析主机名时会用/etc/hosts里的映射,建议确保 hosts 文件里有一条:

127.0.0.1 localhost 你的主机名

同时检查配置文件里是否有其他主机名映射导致解析错乱。否则启动时你可能会看到Local host name unknown: java.net.UnknownHostException一类的错误。

我把 SSH 配置放在 JDK 之后写是有原因的。启动失败的问题里,最常见的就是 SSH 没通,其次是 Java 路径不对。这两关过了,后面启动脚本基本能顺利执行。

3. 下载、解压与目录规划

环境准备做完,接下来是把 Hadoop 本体放到合适的位置。这一步看起来简单,但版本选择和目录规范会影响后面排查问题的容易程度。

3.1 版本与下载源

版本选择上,我的建议是:选当前稳定发布的 3.x 正式版,不要选 2.x 老版本,也不要选 alpha/beta 之类的快照版本。Hadoop 3.x 相比 2.x 在性能、资源模型上都有明显改进,新学习的人没必要把精力浪费在旧版本的兼容性问题上。

下载时直接用wget拉官方镜像站里的hadoop-x.y.z.tar.gz。注意下载完成后最好校验一下文件的sha512哈希值,这一步虽然麻烦,但可以避免下载包损坏导致的异常启动问题。我之前有一次下载中断续传,解压没报错,结果hadoop version一直报错,就是这个原因。

wget https://mirrors.example.com/apache/hadoop/common/hadoop-x.y.z/hadoop-x.y.z.tar.gz sha512sum hadoop-x.y.z.tar.gz

3.2 目录规划与权限

解压后不要直接把目录扔在原地就完事,建议做两层规划:

先创建固定安装位置:

sudo mkdir -p /usr/local sudo tar -xzf hadoop-x.y.z.tar.gz -C /usr/local sudo mv /usr/local/hadoop-x.y.z /usr/local/hadoop

这样/usr/local/hadoop就是实际运行目录。以后如果升级,可以把新版本解压成hadoop-3.4.x再改软链,配置路径不用动。虽然直接改目录名最省事,但用软链或者别名维护版本更符合长期习惯。

然后是权限规划。我强烈建议不要用 root 跑 Hadoop。单机测试时 root 好像能省事,但 root 启动后生成的数据文件、日志全部属于 root,后续你想用普通用户操作 HDFS 或清理数据都会遇到权限问题。正确做法是给运行用户授权:

sudo chown -R $(whoami):$(whoami) /usr/local/hadoop

最后把 Hadoop 的配置目录单独声明到环境变量里,很多周边工具会默认去找这个变量:

export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop

别小看这个变量,后面你用 HBase、Spark 连接 Hadoop 时,它们都会读取HADOOP_CONF_DIR来定位集群地址。

再创建一个用于存放 HDFS 元数据和数据块的目录,后面配置会用到:

mkdir -p /usr/local/hadoop/tmp/dfs/name mkdir -p /usr/local/hadoop/tmp/dfs/data

这个目录可以按照你自己的习惯放到/data/hadoop之类的路径下,但必须保证运行用户有读写权限。我习惯放在 Hadoop 安装目录内部,方便整个安装目录一起迁移。

4. 核心配置与 NameNode 格式化

整个部署测试中,这一节最容易出问题,也最值得花时间理解。配置不多,但如果只是照抄粘贴,遇到报错时你会一头雾水。

4.1 四个 XML 和一个 env 文件

Hadoop 的配置都在$HADOOP_HOME/etc/hadoop下。伪分布式模式需要修改的文件是core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml和hadoop-env.sh。

第一个是core-site.xml,它负责全局参数,核心是 HDFS 的默认地址:

<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> </configuration>

这里9000是 NameNode 的 RPC 通信端口。HDFS 客户端、后续 HBase 等组件都是通过这个地址找到 NameNode 的。

第二个是hdfs-site.xml,它控制 NameNode 和 DataNode 的存储目录、副本数:

<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:///usr/local/hadoop/tmp/dfs/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:///usr/local/hadoop/tmp/dfs/data</value> </property> </configuration>

dfs.replication为什么必须设为 1?因为单机部署只有一个 DataNode,如果保持默认的 3 副本,文件永远处于 under replicated 状态,DataNode 只有一份数据却要拼命找另外两个副本所在节点,不仅日志里全是警告,还会不断触发不必要的块复制任务。设成 1 就是告诉 HDFS:我就一台机器,存一份够了。

第三个是mapred-site.xml。这个文件默认情况下只有模板,需要从mapred-site.xml.template复制出来。它负责告诉 MapReduce 框架使用 YARN 调度,而不是本地执行:

cp $HADOOP_HOME/etc/hadoop/mapred-site.xml.template $HADOOP_HOME/etc/hadoop/mapred-site.xml
<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>

第四个是yarn-site.xml,核心是指定 ResourceManager 所在主机:

<configuration> <property> <name>yarn.resourcemanager.hostname</name> <value>localhost</value> </property> </configuration>

如果你的机器内存比较小,还可以在这个文件里加上资源调度参数,比如:

<property> <name>yarn.nodemanager.resource.memory-mb</name> <value>2048</value> </property> <property> <name>yarn.scheduler.minimum-allocation-mb</name> <value>256</value> </property> <property> <name>yarn.scheduler.maximum-allocation-mb</name> <value>2048</value> </property>

最后一个要改的是hadoop-env.sh。这个文件里写死了 Hadoop 默认的 JAVA_HOME 注释,必须把它设成你 JDK 的真实路径:

export JAVA_HOME=/usr/local/jdk

如果你前面已经在/etc/profile.d/hadoop.sh里配置了全局JAVA_HOME,这里有时也可以不写。但我是建议在hadoop-env.sh里也写一遍,因为 Hadoop 的某些子进程在特殊环境下不会读取你的 profile 文件。

4.2 格式化 NameNode:一次就够

配置完成后,第一次启动之前必须执行格式化:

hdfs namenode -format

这个命令的作用是初始化 HDFS 的元数据存储目录,生成一个空的文件系统映像和集群 ID。注意它和“格式化磁盘”不是一回事,它只是生成 NameNode 用来管理目录树和文件状态的元数据文件。

格式化是学习 Hadoop 时最容易被误用的操作。有的人遇到问题第一反应就是“重新格式化”,结果格式化多次后,NameNode 和 DataNode 的集群 ID 对不上,DataNode 启动时报错或者注册不进来。我的原则是:只在第一次部署或者明确想重置整个集群时格式化;如果是排查问题,先查日志,不要一上来就格式化。

格式化成功后,结尾会看到类似Storage directory ... has been successfully formatted的输出。此时dfs.namenode.name.dir目录下应该生成current文件夹,里面有VERSION文件,这个文件记录了集群 ID,后面 DataNode 就是拿它来匹配 NameNode 的。

4.3 启动与停止的顺序

建议分开启动,不要一把梭用start-all.sh,这样出问题的时候能快速定位是 HDFS 的问题还是 YARN 的问题:

start-dfs.sh start-yarn.sh

启动后执行jps,正常情况下你应该看到这 5 个进程:

NameNode DataNode SecondaryNameNode ResourceManager NodeManager

对应的停止命令是:

stop-dfs.sh stop-yarn.sh

启动过程中如果有报错,脚本会非常不友好地直接丢一堆 SSH 输出。如果你看到反复出现Permission denied (publickey),不要怀疑脚本,回头检查第 2.3 节的免密配置。

5. 部署测试:HDFS 命令与 WordCount

进程都起来了,部署只算成功了一半。接下来要真正把“测试”跑起来,用实际任务验证各个组件之间是否联动正常。

5.1 HDFS 基本命令

HDFS 的命令行风格和 Linux 很像,但必须以hdfs dfs或hadoop fs开头。先验证文件系统可用性:

hdfs dfs -mkdir -p /user/test hdfs dfs -ls / hdfs dfs -put /etc/hosts /user/test/ hdfs dfs -cat /user/test/hosts

为什么测试从这几条命令开始?因为这一步能同时验证 NameNode 的元数据服务、DataNode 的块存储服务、客户端与集群之间的 RPC 通信是否全部正常。mkdir走的是 NameNode 的目录树操作,put会真正把文件写入 DataNode 并建立块副本,cat又从 DataNode 读回数据。这三个动作全通了,说明 HDFS 的读写链路是健康的。

注意一点:不要直接往 HDFS 根目录写文件。根目录默认属于超级用户,普通用户对根目录没有写权限。所以先创建自己的 home 目录,一般规范是/user/你的用户名。

hdfs dfs -mkdir -p /user/$(whoami)

5.2 跑第一个 MapReduce 作业 WordCount

Hadoop 自带一个示例包:hadoop-mapreduce-examples-*.jar,里面包含 WordCount 等经典例子。WordCount 之所以成为“Hello World”,是因为它完整经历了分片、Map、Shuffle、排序、Reduce 这几个阶段,相当于把 HDFS 和 YARN 都压了一遍。

操作步骤:

cd $HADOOP_HOME hdfs dfs -mkdir -p /user/test/wordcount/input hdfs dfs -put etc/hadoop/*.xml /user/test/wordcount/input/ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar \ wordcount \ /user/test/wordcount/input \ /user/test/wordcount/output

注意输出目录/user/test/wordcount/output在作业启动前必须不存在。这是 Hadoop 为了防止覆盖结果而设置的保护机制,如果目录存在会直接报FileAlreadyExistsException。

运行过程中,终端会滚动打印 Map 和 Reduce 的百分比进度。看到这两行就说明作业完整跑完了:

Map 100% Reduce 100%

然后查看结果:

hdfs dfs -cat /user/test/wordcount/output/part-r-00000

这个文件就是 Reduce 阶段输出的最终结果,每一行是“单词\t次数”。如果能看到这样的输出,说明 HDFS 存储、YARN 资源调度、MapReduce 计算引擎整个链路全部通过。

如果 Map 100% 后 Reduce 一直停在 0%,优先考虑资源问题。Nodemanager 给每个作业分配的默认内存可能不够,回到 4.1 节的yarn-site.xml调大内存,并重启 YARN。

5.3 Web UI 验证

命令行验证完成后,别忘了打开两个 Web 界面看看集群状态。

NameNode 管理界面:

http://localhost:9870

在这个页面里可以看到 HDFS 的总体容量、存活 DataNode 列表、块健康状态。如果你配置的是 3.x 且没改端口,这个端口基本不变;2.x 版本是 50070,注意区分。

YARN ResourceManager 界面:

http://localhost:8088

这个页面能看到集群上运行和完成的 Application 列表,点击 Application 可以查看日志链接、任务数、资源占用情况。Web UI 是后续排查作业问题的重要入口,比命令行信息直观得多。

打不开页面时先检查进程是否还在,再检查防火墙。有些发行版默认开防火墙,需要放行 9870 和 8088,或者干脆在测试环境里关掉防火墙。生产环境当然不建议关,但单机测试完全可以。

6. 常见问题与排查思路

这一节我把实际部署测试中大概率会遇到的问题集中起来,按症状、原因、解决办法的顺序写。遇到问题先对号入座,别急着格式化。

6.1 进程缺失与集群 ID 不一致

症状:jps里只有 NameNode,没有 DataNode;或者 DataNode 起来几秒后自动退出,日志里出现Incompatible clusterIDs。

原因:最常见的是格式化时机不对。第一次部署后,NameNode 生成一个集群 ID;之后你再次删除数据目录并格式化,NameNode 的集群 ID 变了。但 DataNode 的数据目录里还保留着旧集群 ID,注册时发现两边不对不上,就拒绝启动。

解决:

stop-dfs.sh rm -rf /usr/local/hadoop/tmp/dfs/name/* rm -rf /usr/local/hadoop/tmp/dfs/data/* hdfs namenode -format start-dfs.sh

注意,这是在确认“没有重要数据”的前提下才能做的操作。如果你已经在 HDFS 里放了测试数据,想保留但又遇到集群 ID 不一致,理论上可以手动修改 DataNode 的VERSION文件里的clusterID为 NameNode 当前的 ID,但操作繁琐,新手不建议。重置重来是最省心的方式。

另一个症状:NameNode 起不来,日志提示Invalid URI或目录找不到。

原因:dfs.namenode.name.dir属性写错,常见错误是写成了dfs.name.dir,或者目录没有提前创建。XML 属性名差一个单词都不会被识别。

6.2 端口、内存与 HDFS 权限

端口占用这个问题在测试环境里很常见,尤其是 9000 端口,经常被其他 Java 服务抢了。查看方式:

ss -lntp | grep 9000

如果端口被占用,最省事的做法是清理占用进程。如果清理不了,只能改core-site.xml里的fs.defaultFS端口,但注意一旦改掉,后续客户端命令和yarn-site.xml里的地址都要跟着改,麻烦一些。

内存不足的典型表现是:作业一直显示ACCEPTED,或者 Map 进度停在某个百分比不动。前面已提到在yarn-site.xml里调整:

yarn.nodemanager.resource.memory-mb yarn.scheduler.minimum-allocation-mb yarn.scheduler.maximum-allocation-mb

调整后重启stop-yarn.sh && start-yarn.sh,再次提交作业。

HDFS 权限问题最常见的报错是:

Permission denied: user=test, access=WRITE, inode="/user":root

这是因为你用普通用户向超级用户拥有的目录写入文件了。解决办法是先创建自己的目录:

hdfs dfs -mkdir -p /user/test hdfs dfs -chown test /user/test

如果你是第一次部署,当前用户根本没有操作 HDFS 的权限,也可以用sudo -u hdfs来执行上述命令,前提是集群里有 hdfs 超级用户。另一种办法是设置dfs.permissions.enabled=false,但不建议,因为后面学习 HDFS 权限时会形成错误理解。

6.3 日志在哪里查

Hadoop 几乎所有排障都要靠日志,它在$HADOOP_HOME/logs/下。日志文件名通常形如:

hadoop-用户名-namenode-主机名.log hadoop-用户名-datanode-主机名.log hadoop-用户名-resourcemanager-主机名.log

查看最近日志:

tail -100 $HADOOP_HOME/logs/hadoop-*--namenode-*.log

注意如果日志文件太多,可以先ls -lt按时间排序,找最近修改的那个文件。.out后缀的文件是标准输出重定向,日志级别更粗糙;.log文件是 Log4j 输出的详细日志,排查问题优先看.log。

YARN 作业级别的日志,可以用命令行获取:

yarn logs -applicationId application_xxxx_0001

如果没有开启日志聚合,这条命令可能拉不到内容,那就直接到 8088 页面上点进对应 Application 看诊断信息。

还有一条经验:启动时看到这一行不用担心:

WARN util.NativeCodeLoader: Unable to load native-hadoop library

这只是在提示本地库没有编译,Hadoop 会用纯 Java 实现替代,功能不受影响,不是致命错误。很多人在这一步浪费了大量时间去装本地库,其实单机测试完全没必要。

最后说两句个人经验

部署测试这件事,我最大的体会是“别急着重装”。Hadoop 的每个组件都留了日志和端口状态,绝大多数问题都能从日志里回溯到根因。格式化是最后手段,不是第一手段。单机版跑通的那一刻,你会突然理解为什么 HDFS 要分 NameNode 和 DataNode,为什么 YARN 要单独做资源管理——这些概念在纸面上看很抽象,真正操作一遍之后,所有节点就都串起来了。

另外一个小技巧:部署测试过程中每次配置更改后,如果在启动时报错,不要反复重启,先把当前进程停干净,再验证配置文件里有没有非法字符。XML 标签多写一个空格或者属性名拼错,经常会导致组件启动失败,而这种问题靠单纯重启是解决不了的。做完这些,后面再接触完全分布式集群,你会发现所有流程都似曾相识。

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

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

立即咨询