news 2026/10/21 3:39:49

Ubuntu上从零搭建Hadoop集群:配置详解与踩坑实录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu上从零搭建Hadoop集群:配置详解与踩坑实录

直接上手在 Ubuntu 上搭 Hadoop 集群,光看官方文档真的容易劝退。版本对不上、Java 路径写错、SSH 免密没配好,随便哪个坑都能卡你一整天。这篇我用自己实际部署的经验,从环境准备、配置文件逐项拆解,到格式化、启动、验证,把每一步为什么这么做讲清楚,最后附上高频踩坑记录,照着抄基本不会出大问题。


1. 搭建前的整体设计与环境准备

1.1 集群角色划分与硬件规划思路

Hadoop 集群最常见的部署方式是主从架构,一主多从或者多主多从。对于学习环境或者中小规模数据实验,一台主节点加两台从节点是最经济也最踩坑最全的组合。主节点跑 NameNode、SecondaryNameNode 和 ResourceManager,从节点跑 DataNode 和 NodeManager。也可以把主节点的 ResourceManager 单独拆到第三台机器上,但那样对机器数量和网络配置要求更高,不推荐新手一上来就搞复杂拓扑。

部署之前先把机器 IP、主机名、角色规划好。以三台为例:

节点主机名IP(示例)角色
主节点hadoop-master192.168.1.101NameNode、ResourceManager、SecondaryNameNode
从节点1hadoop-slave1192.168.1.102DataNode、NodeManager
从节点2hadoop-slave2192.168.1.103DataNode、NodeManager

主机名规范很重要,不要随便起名,后面 hosts 映射、HDFS 目录路径、日志输出里到处都会出现主机名,不一致就排查到哭。我自己习惯统一用hadoop-master、hadoop-slave1这种语义化命名,一眼能看出角色。

内存规划也要心里有数。NameNode 和 ResourceManager 分别在 JVM 堆内存上跑,DataNode 节点上同时跑 DataNode 和 NodeManager,内存紧张时很容易互相挤占。建议主节点至少 4GB,从节点至少 2GB,如果是虚拟机,每台 2GB 起步勉强能跑,但别指望跑大数据量任务。

1.2 系统环境、JDK 版本与 SSH 免密配置

Ubuntu 版本选择上,18.04、20.04、22.04 我都试过,Hadoop 3.3.x 在这几个版本上都能正常跑,前提是 Java 版本匹配。JDK 一定不要用最新版,Hadoop 对 Java 版本支持是滞后的。Hadoop 3.3.x 官方要求 Java 8 或 Java 11,实测 OpenJDK 8 最稳。

安装 Java 之前先更新系统源,用官方源可能比较慢,可以换成国内镜像源。这里我踩过一个坑,换源之后 Java 包版本不完整,导致编译环境缺失,后面配置hadoop-env.sh时 JVM 参数一直报错,所以建议先确认源可用再继续。

sudo apt update sudo apt install -y openjdk-8-jdk

装完以后确认版本和路径:

java -version readlink -f $(which java)

readlink -f拿到的路径后面配置JAVA_HOME要用。很多文章写/usr/lib/jvm/java-8-openjdk-amd64,这个在 18.04 和 20.04 上是对的,但 22.04 默认源里可能没有 openjdk-8,需要额外配置源。所以最好自己确认一下。

SSH 免密这块是整个安装过程中最容易被忽略又最容易出错的环节。Hadoop 启动时需要主节点通过 SSH 无密码登录到所有从节点,去拉起 DataNode 和 NodeManager 进程。如果免密配置失败,启动脚本不会直接报错,但你会发现从节点上 DataNode 进程根本不存在。

配置免密在三台机器上都要执行:

ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa

然后把主节点的公钥加到所有节点(包括主节点自己)的authorized_keys里:

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

如果希望更省事,直接用ssh-copy-id:

ssh-copy-id hadoop-master ssh-copy-id hadoop-slave1 ssh-copy-id hadoop-slave2

验证方式很简单,从主节点 SSH 到每个主机名,如果不要求输入密码,说明连通了。很多人在这一步被坑,原因往往是.ssh目录权限不对。authorized_keys文件权限必须是 600,.ssh目录权限必须是 700,否则 SSH 会忽略公钥文件。这个特性是 OpenSSH 的安全机制,权限太宽松反而拒绝认证。

注意:SSH 配置完成后,一定要用主机名而不是 IP 去测试连通性。因为 Hadoop 内部的进程间通信使用主机名解析,如果 IP 能连通而主机名不通,启动后依然会有一堆 connection refused。


2. Hadoop 版本选型与核心配置文件逐项拆解

2.1 版本选择与安装目录规划

Hadoop 版本选型直接影响后面配置文件的字段差异。Hadoop 2.x 和 3.x 在端口号、配置文件字段上区别很大,比如 NameNode Web UI 端口,2.x 是 50070,3.x 变成了 9870。如果照着 2.x 教程配 3.x,Web UI 永远打不开。建议直接用 Hadoop 3.3.x 系列,它已经非常稳定,社区里踩坑资料也齐全。

下载 Hadoop 时不要用 GitHub 上的 release 包,从 Apache 官方镜像站下载 tar.gz 包最稳妥。下载完解压到/opt目录,并做软链方便后续升级:

sudo tar -xzf hadoop-3.3.6.tar.gz -C /opt cd /opt && sudo ln -s hadoop-3.3.6 hadoop sudo chown -R hdfs:hdfs /opt/hadoop

这里创建专门用户hdfs(也可以叫hadoop)而不是直接用 root,是安全考虑。Hadoop 的 DataNode 会以该用户身份写 HDFS 数据,权限管控上更清晰。如果你不想单独建用户,直接用自己的普通用户也行,但三台机器的用户名必须一致,否则跨节点通信时权限和路径会有各种诡异问题。

2.2 五个核心配置文件的配置逻辑

Hadoop 的配置集中在$HADOOP_HOME/etc/hadoop/目录下,核心就四个文件:core-site.xml、hdfs-site.xml、yarn-site.xml、mapred-site.xml,加上workers(旧版本叫slaves)。

第一个core-site.xml,这个文件决定了集群的默认文件系统地址和临时目录。关键是fs.defaultFS这个属性,它指定了 NameNode 的 RPC 地址,也就是 HDFS 的入口。很多新手在这里写错端口,一旦端口不一致,客户端根本找不到 NameNode。

<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://hadoop-master:9820</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/opt/hadoop/data/tmp</value> </property> </configuration>

端口 9820 是 Hadoop 3.x 的 NameNode RPC 默认端口,2.x 是 8020 或者 9000,这个细节很容易忽略。hadoop.tmp.dir是 NameNode 和 DataNode 存储元数据和数据块的根目录,不配置的话默认在/tmp下,系统一重启数据全没了,这是生产环境绝对要避免的。

第二个hdfs-site.xml,它控制 HDFS 自身的属性。dfs.replication决定每个块有几个副本,三台节点的集群设置成 2 比较合理。如果你保留默认的 3,而集群只有两个 DataNode,多余的副本会一直处于复制等待状态,空间浪费还容易误判为故障。

<configuration> <property> <name>dfs.replication</name> <value>2</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:///opt/hadoop/data/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:///opt/hadoop/data/datanode</value> </property> <property> <name>dfs.namenode.http-address</name> <value>hadoop-master:9870</value> </property> </configuration>

dfs.namenode.name.dir是 NameNode 元数据存储路径,dfs.datanode.data.dir是 DataNode 数据块存储路径。这两个目录在格式化之前要手动创建好,并且确保属主是 Hadoop 用户,否则启动时会因为目录权限问题直接失败。

第三个yarn-site.xml,它管理计算资源调度。核心配置是 ResourceManager 所在的主机名,以及是否启用 NodeManager 的辅助服务。很多人以为 YARN 和 HDFS 必须同机,其实可以分开部署,不过小集群放一起最省事。

<configuration> <property> <name>yarn.resourcemanager.hostname</name> <value>hadoop-master</value> </property> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> </configuration>

aux-services是 YARN 的 NodeManager 辅助服务配置,MapReduce 任务跑在 YARN 上时必须配置mapreduce_shuffle,否则提交作业时会报错“Shuffle handler is not enabled”。

第四个mapred-site.xml,这个文件原本在 Hadoop 2.x 中是不存在的,需要从模板复制出来,3.x 版本安装包里自带模板。配置文件内容很简单,就是告诉 MapReduce 使用 YARN 作为底层资源调度框架:

<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>

这四个文件的配置逻辑其实可以概括为:core-site.xml是全局入口,hdfs-site.xml管存储,yarn-site.xml管资源,mapred-site.xml管计算框架对接。底层关系上,MapReduce 任务提交到 YARN,YARN 从 HDFS 上读取输入数据,计算完再写回 HDFS。

2.3 环境变量与 workers 节点列表配置

配置完核心 XML 后,还要改两个文件。第一个是hadoop-env.sh,里面设置JAVA_HOME。这里必须写 JDK 的绝对路径,写JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64,不要在配置文件里写java命令,因为 Hadoop 启动脚本在某些环境下不会加载用户的~/.bashrc里的环境变量。

第二个是workers文件,这个文件列出了所有 DataNode 和 NodeManager 所在的主机名,一行一个,不含主节点。注意这个文件在 Hadoop 3.x 里叫workers,在 Hadoop 2.x 里叫slaves,版本变了很多人还在改那个旧文件,结果集群启动脚本扫描到文件名不对,DataNode 永远起不来。

# workers 文件内容 hadoop-slave1 hadoop-slave2

环境变量配置写入/etc/profile.d/hadoop.sh,内容如下:

export HADOOP_HOME=/opt/hadoop 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 并配置相同的 XML 文件和环境变量,不需要执行格式化操作,这个后面细说。


3. 从格式化到启动的完整实操过程

3.1 格式化 NameNode 的时机与坑位

所有配置完成后,第一件大事就是格式化 NameNode。hdfs namenode -format这个命令会在 NameNode 的元数据目录下生成一个current/VERSION文件,里面是有集群唯一标识的clusterID。

格式化的时机很讲究。必须是首次启动集群之前格式化,而且只需要在一台机器上执行。如果集群曾经启动过,因为配置变化需要重新格式化,必须先清空 NameNode 和所有 DataNode 的数据目录,否则会出现clusterID不一致的问题。这个坑我印象太深了:DataNode 启动时会在上报心跳,NameNode 发现两边clusterID不匹配就直接拒绝注册,日志里疯狂刷Incompatible clusterIDs。

格式化之前,确认三台机器的所有数据目录都准备完毕:

hdfs namenode -format

看到输出中Storage directory ... has been successfully formatted就说明成了。如果格式化了多次导致 ID 冲突,办法是同时删除namenode/current和所有 DataNode 的datanode/current目录,然后重新格式化。注意这种操作相当于清空整个集群的数据,生产环境不能随便做。

3.2 启动 HDFS 和 YARN 的具体步骤

启动顺序上,先启动 HDFS 再启动 YARN。HDFS 是存储层,YARN 的资源调度依赖 HDFS 提供输入数据和写入输出结果。

先在主节点执行:

start-dfs.sh

这个脚本会读取workers文件,通过 SSH 到每个从节点启动 DataNode,本地启动 NameNode 和 SecondaryNameNode。启动过程中如果 SSH 免密配置正确,整个过程不需要输入密码。

启动后务必使用jps检查进程状态。

主节点应该看到:

  • NameNode
  • SecondaryNameNode
  • ResourceManager

从节点应该看到:

  • DataNode
  • NodeManager

如果某个进程缺失,不要急着重启整个集群,先看日志。HDFS 日志在$HADOOP_HOME/logs/目录下,YARN 日志也一样。日志文件名一般是hadoop-hdfs-datanode-主机名.log、yarn-hadoop-resourcemanager-主机名.log这类格式。

HDFS 启动之后接着启动 YARN:

start-yarn.sh

启动完以后,再次用jps确认 ResourceManager 在主节点,NodeManager 在每个从节点。

3.3 通过 Web UI 与命令行验证集群状态

进程全部拉起后,还需要验证功能是否正常。第一条路径是 Web UI:

  • HDFS 管理界面:http://hadoop-master:9870
  • YARN 资源管理界面:http://hadoop-master:8088

浏览器打开 HDFS 页面,能看到 Live Nodes 数量和集群存储容量。如果Live Nodes数字小于从节点数,直接看 DataNode 日志。YARN 页面的Active Nodes也是同理。

命令行验证用 DFS 命令。上传一个测试文件到 HDFS,再把它拉回来,对比校验值:

echo "hello hadoop cluster" > /tmp/test.txt hdfs dfs -mkdir -p /user/hadoop hdfs dfs -put /tmp/test.txt /user/hadoop/test.txt hdfs dfs -cat /user/hadoop/test.txt

如果能看到内容输出,HDFS 的读写链路已经通了。再跑一个经典 WordCount 案例来验证计算链路,虽然在小集群上有点小题大做,但能同时打通 YARN、MapReduce 和 HDFS 全链路:

hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar wordcount /user/hadoop/test.txt /user/hadoop/output

跑完后确认输出目录下是否有_SUCCESS文件,有就是作业成功。如果没有,查看 YARN 日志。

提示:Hadoop 3.x 会在hdfs dfs命令时提示使用file://协议,如果你操作的是 HDFS 就不需要,只有操作本地文件系统时才需要。


4. 高频踩坑实录与排查思路

4.1 SSH 免密、主机名解析类的疑难杂症

这类问题最典型的症状就是start-dfs.sh执行到从节点时卡住或报Permission denied (publickey)。排查思路先看权限:

ls -la ~/.ssh/

authorized_keys必须是-rw-------,.ssh目录是drwx------。另外检查一下三台机器的~/.ssh/known_hosts,有时候公钥信息过期会导致 SSH 连接时报 Host key verification failed。

如果权限没问题,手动 SSH 一次从节点,看是否有报错细节。顺便确认从节点的 SSH 服务已开启:

sudo systemctl status ssh

主机名解析问题一般在/etc/hosts文件,三台机器都要添加相同的主机名映射:

192.168.1.101 hadoop-master 192.168.1.102 hadoop-slave1 192.168.1.103 hadoop-slave2

这里有个常见的认知误区:只在主节点配置 hosts 是不够的。DataNode 启动时向 NameNode 注册,双方的通信需要各自解析主机名,如果从节点解析不了主节点的主机名,NameNode 地址就无法连接。我见过太多案例,主节点一切正常,从节点一直报 connection refused,一看 hosts 文件根本没改。

4.2 Java 版本不匹配与内存参数调优

Hadoop 的 Java 依赖非常严格。装了 Java 17 跑 Hadoop 3.3.x 在某些场景会报IllegalArgumentException,但错误信息又不够明显,很多人排查半天才发现是 Java 版本问题。强烈建议统一 OpenJDK 8,虽然不是所有场景都会出问题,但至少避开了大部分已知不兼容项。

内存参数的问题主要在hadoop-env.sh里的HADOOP_HEAPSIZE和HADOOP_OPTS。如果机器内存有限,默认的 1GB 堆内存可能让 JVM 直接 OOM。可以在hadoop-env.sh里设置:

export HADOOP_HEAPSIZE=512

NameNode 和 ResourceManager 各自都在 JVM 上跑,如果机器只有 2GB 内存,三四个 JVM 进程会直接吃满内存,表现就是系统卡顿、进程被内核杀掉。可以把YARN_RESOURCEMANAGER_HEAPSIZE和YARN_NODEMANAGER_HEAPSIZE调小,或者用 swap 文件撑一下。

NodeManager 内存不足的问题通常体现为容器启动失败,YARN 页面里Diagnostics信息会写明内存不足。这时候要去修改yarn-site.xml中的yarn.nodemanager.resource.memory-mb,默认是物理内存的 80%,看起来很大,实际上每个容器一分配就容易超。

4.3 格式化之后 NameNode 起不来、DataNode 反复掉线

格式化后 NameNode 起不来的典型案例是目录权限。dfs.namenode.name.dir指向的目录不存在或者属主不是当前用户,都会导致启动失败。解决办法:

sudo mkdir -p /opt/hadoop/data/namenode sudo mkdir -p /opt/hadoop/data/datanode sudo chown -R hdfs:hdfs /opt/hadoop/data

格式化完成后千万别急着 restart,先jps确认没有残留进程。如果有残留的 NameNode,先stop-dfs.sh杀掉再启动,不然新进程会因端口占用直接退出。

DataNode 反复掉线的场景,除了前面说的clusterID不一致,还有一个隐蔽的原因:DataNode 的dfs.datanode.data.dir磁盘空间不足。HDFS 默认有个dfs.datanode.du.reserved参数,预留空间不足会拒绝写入新块。小集群可能不明显,时间久了磁盘一满就容易误判成节点故障。

这块我个人的习惯是,先把日志打开,看 DataNode 上报失败的原始报错,是Incompatible clusterIDs这种明确的信息就按上面方法清理重启。如果日志信息很模糊,直接grep -i error过滤日志文件,往往能直接看到根本原因,比瞎猜效率高得多。


5. 个人实操心得与调优建议

5.1 几个值得花时间注意的细节

一个内容是,hostname和hostnamectl命令要配合使用。很多时候你改了/etc/hostname,但当前终端的主机名还是旧的,导致 Hadoop 各类日志里混淆。建议改完主机名后用hostnamectl set-hostname hadoop-master保存,然后重新登录。

还有一个容易被忽略的文件是/etc/hosts中不要写 IPv6 的::1映射和主机名关联,某些场景下 JVM 会优先解析到 IPv6 地址导致连接失败。可以在启动脚本前设置export HADOOP_OPTS="-Djava.net.preferIPv4Stack=true",或者直接在/etc/hosts中注释掉 IPv6 相关行。

配置文件分散在三台机器,维护时保持副本一致性很重要。我平时的做法是改完主节点配置后直接 scp 分发:

scp -r $HADOOP_HOME/etc/hadoop/* hadoop-slave1:$HADOOP_HOME/etc/hadoop/ scp -r $HADOOP_HOME/etc/hadoop/* hadoop-slave2:$HADOOP_HOME/etc/hadoop/

不要手工一台台改,两个文件的内容写错一个标点就是半天白干。

5.2 集群关闭与重启的经验

关闭集群时顺序和启动正好相反,先关 YARN 再关 HDFS:

stop-yarn.sh stop-dfs.sh

如果碰到进程明明停了但端口还占着,可以用lsof -i:9870找到残留进程手动 kill,但别一上来就 kill -9,先试试正常stop-*.sh脚本,避免元数据写入不完整。

重启集群时不需要重新格式化。反过来,如果有人误以为每次重启要hdfs namenode -format,集群数据就全丢了。只有第一次启动才需要格式化,重启只需要正常 start 脚本。

数据安全上,NameNode 的元数据目录最好做定时备份,最粗暴的办法是定期打包namenode/current目录到另一台机器。毕竟fsimage和edits文件承载了集群所有目录和文件的位置信息,一旦损坏,整个集群基本废了。小规模实验集群可能不会遇到这个问题,但养成备份习惯总没有坏处。

5.3 集群横向扩展的思路

三台集群跑通以后,如果想扩展到更多节点,流程很简单:新节点安装 JDK 和 Hadoop,配置相同 XML 和workers文件加一行新主机名,然后在新节点上手动启动 DataNode 和 NodeManager。不需要格式化,不需要动已有节点上的数据和元数据。

实际操作中我倾向于在新节点单独启动:

hdfs --daemon start datanode yarn --daemon start nodemanager

这样不用重启整个集群,HDFS 和 YARN 会自动感知新节点加入。几秒钟后,HDFS Web UI 的 Live Nodes 应该就多了一台。这种滚式扩展方式对线上环境来说非常友好,不过新增节点时最好观察一下数据均衡状态,块分配不均衡时可以用hdfs balancer触发均衡任务,让它自动调配。

搭建 Hadoop 集群本身不是目的,能跑通一个完整的离线计算链路才是价值所在。我在实际操作中最深刻的体会是:配置文件字段和端口号一定要以你下载的版本为准,别拿老版本教程硬套新版本。另外,日志永远是第一排查入口,学会看logs目录下各种.log文件,比到处搜答案快得多。这套环境跑顺之后,后面玩 Hive、Spark、Flink 都只是顺着现有框架加组件的问题,地基打牢了,上层才能稳。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 3:39:45

OpenAPI到MCP桥接器:将Spring Boot REST接口自动转为AI可调用工具

1. 先说说我为什么折腾这个桥接器大约两个月前&#xff0c;我在为一个内部平台做技术预研&#xff0c;团队计划把一个已有二十多个REST接口的业务后端&#xff0c;接进一个基于大模型的问答与操作助手。问题一开始就不在AI能力上&#xff0c;而是AI压根不知道这些接口长什么样&…

作者头像 李华
网站建设 2026/10/21 3:39:44

降AI率实操全解析:从检测原理到智能体改写流程

这两年凡是和文字打交道的人&#xff0c;基本都绕不开“降AI率”这三个字。不管你是写论文、做公众号&#xff0c;还是给公司写周报&#xff0c;只要用AI打过草稿&#xff0c;就大概率见过那个刺眼的“疑似AI生成”百分比。某次帮A同学看一篇投稿前的稿件&#xff0c;复制到检测…

作者头像 李华
网站建设 2026/10/21 3:39:03

深度学习异常流量检测系统毕业设计实战:数据、模型与答辩全攻略

毕业设计选"深度学习异常流量检测系统"这个题&#xff0c;我接触过不少同学&#xff0c;刚开始都觉得这是个又硬核又稳妥的方向&#xff1a;有公开数据集、有深度学习框架、有可视化能做&#xff0c;论文也有得写。可真动手之后才发现&#xff0c;坑比想象的多——数…

作者头像 李华
网站建设 2026/10/21 3:37:58

Java开发者转型大模型实战:从API接入到RAG应用落地全流程

做Java后端这几年&#xff0c;说实话&#xff0c;看着AI大模型这波浪潮一波接一波涌过来&#xff0c;说不焦虑是假的。大模型刚开始爆发那阵&#xff0c;我身边不少Java同事就在讨论要不要转Python、要不要去搞算法。两年多过去&#xff0c;回头看&#xff0c;焦虑的人很多&…

作者头像 李华