☰
Ubuntu下Hadoop集群搭建实战:从规划到故障排查
2026/10/22 21:16:29 网站建设 项目流程

前阵子有个朋友问我,手里有几台Linux机器想搞个Hadoop集群,但网上教程大多是用CentOS写的,他自己装了Ubuntu,照着改了半天愣是起不来。这话题我太熟悉了——Ubuntu和CentOS在用户、命令、目录结构上都有差异,直接照搬确实容易翻车。今天我就以“基于Ubuntu下hadoop集群搭建”为主线,把从规划、环境准备、配置、启动到验证的完整过程捋一遍。

这篇内容适合两类人看:一类是刚接触大数据,想在自己电脑上用虚拟机搭一个最小集群练手;另一类是在公司内网申请了几台物理机或云主机,需要搭一个能跑业务任务的生产级实验集群。不管你是哪种,读完你都能得到一份可以直接落地执行的方案,而且我会重点解释每个关键配置背后的理由——有些坑不是配置写错,而是你没搞懂它为什么这么配。

1. 集群规划与设计思路

1.1 为什么要用Hadoop集群而不是单机

很多人在入门阶段会问:我在笔记本上装个单机版Hadoop也能跑WordCount,为什么非得搭集群?

这个问题值得先想清楚。单机版Hadoop本质上是把所有守护进程跑在同一台机器上,数据存储和计算都受限于单机磁盘和内存。一旦数据量达到TB级别,单机磁盘装不下、单进程计算太慢,这时候就需要把数据分散到多台机器的磁盘上、把计算任务分散到多台机器的CPU上——这就是Hadoop集群解决的问题。

我这次搭建的是一个经典的3节点集群,由1个主节点和2个工作节点组成。主节点运行NameNode和ResourceManager,负责管理文件系统的元数据和资源调度;工作节点运行DataNode和NodeManager,负责实际存储数据块和执行计算任务。3个节点是最小规模的“真实”集群,既能体现出分布式特性,配置和维护成本又不至于太高。

1.2 操作系统和软件版本选型

操作系统我选了当前较新的Ubuntu LTS版本(22.04或24.04均可),LTS意味着长期维护支持,对服务器场景比较稳妥。相比CentOS,Ubuntu的包管理用apt,安装依赖时会自动处理大部分软件包之间的依赖关系,省去很多编译和依赖的烦恼。

软件版本上,我采用的是Hadoop 3.3.x版本搭配JDK 8或JDK 11。Hadoop 3.x较2.x有诸多改进,包括支持HDFS纠删码、YARN资源类型的精细化、以及默认的副本数变为3等。JDK版本一定不能选太高,JDK 17虽然新,但和Hadoop 3.3.x的组合容易踩到模块化相关的坑,不是不能用,是没必要给自己添堵。

版本选型这件事我的原则很简单:要么选生态里最新稳定的组合,要么选经过时间验证的经典组合。Hadoop 3.3.x + JDK 8就是后者,社区资料最全,遇到问题基本都能搜到答案。

1.3 网络、主机名和用户规划

集群里每台机器都要能通过主机名互相访问,这一步很多人会漏。我在搭建时规划了三个主机名,主节点叫master,两个工作节点叫worker1和worker2。在每台机器的/etc/hosts里写上三台机器的IP和主机名映射,这样后续配置和命令执行都简洁很多。

另外建议全程用同一个系统用户操作,生产中常见做法是创建一个专用的hadoop用户。我这次直接用了一个普通用户(非root),因为Hadoop的部分脚本对root用户有限制,比如某些启动脚本检测到root会拒绝执行。如果你不想额外创建用户,至少在root下需要额外配置才能正常跑,不如规规矩矩建个普通用户省心。用户规划和网络规划是后续所有步骤的地基,这一步做扎实了会省掉后面大量排查时间。

2. 基础环境准备

2.1 系统更新与必要工具安装

拿到一台全新的Ubuntu服务器,我会先执行系统更新:

sudo apt update sudo apt upgrade -y

然后安装一些排查和操作必备的工具:

sudo apt install -y vim net-tools openssh-server ssh pdsh

这里pdsh是个容易被忽略但很实用的工具,它可以同时在多台机器上执行相同的命令,比如同时在三台机器上执行jps查看进程状态,不用一台一台登录,明显提高后续运维效率。

虚拟机环境有一个必须检查的点:确保每台机器的网络模式一致,且IP地址固定。DHCP分配的IP可能在重启后变化,导致hosts映射失效。我习惯在Ubuntu上用netplan配置静态IP,文件在/etc/netplan/目录下,具体文件名每台机器可能不一样。配置静态IP看起来是基础操作,但整个集群的稳定性就依赖IP稳定。

2.2 JDK安装与JAVA_HOME配置

Hadoop是用Java写的,所以JDK是硬依赖。在Ubuntu上安装OpenJDK很简单:

sudo apt install -y openjdk-8-jdk

安装完成后,需要确认JDK的实际安装路径:

readlink -f $(which java)

我在机器上得到的路径是/usr/lib/jvm/java-8-openjdk-amd64,这个路径后面配置JAVA_HOME时要用。可以用sudo vim /etc/environment,在文件中追加一行:

JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64

然后执行source /etc/environment使其生效。注意这里的路径以你机器实际输出为准,不同的Ubuntu版本和架构可能路径不同(比如32位系统是java-8-openjdk-i386)。

这一步看起来简单,但很多新手会把JAVA_HOME配到用户家目录的.bashrc里,而Hadoop的守护进程启动时是通过/etc/environment或hadoop-env.sh读取的,如果两者不统一,会出现“Java路径找不到”的报错。建议直接在hadoop-env.sh里再显式指定一次,双保险。

2.3 配置SSH免密登录

Hadoop主节点需要远程启动工作节点上的守护进程,这是通过SSH实现的。如果每次启动都要输密码,那自动化就成了空话,所以必须配置SSH免密登录。

在三台机器上分别执行:

ssh-keygen -t rsa -b 4096 -N ""

这里-N ""表示空密码,这样生成的密钥才能用于免密登录。然后把我主节点的公钥分发给三台机器,包括主节点自己:

ssh-copy-id -i ~/.ssh/id_rsa.pub hadoop@master ssh-copy-id -i ~/.ssh/id_rsa.pub hadoop@worker1 ssh-copy-id -i ~/.ssh/id_rsa.pub hadoop@worker2

这里用户和主机名替换成你自己实际的。分发完成后,在主节点测试:

ssh master hostname ssh worker1 hostname ssh worker2 hostname

如果每条命令都能直接返回对应的主机名而不提示输密码,说明免密配置成功。

关于SSH配置,有一个权限细节必须强调。~/.ssh目录权限必须是700,authorized_keys文件的权限必须是600或644,权限太宽松会导致SSH直接忽略这个文件。我在一台机器上曾经遇到过反复配置免密都不生效,最后发现是~/.ssh目录的权限是777,chmod修正后立刻正常。这类小问题在文档里写得少,但在实践中非常常见,建议配置完成后顺手检查一下权限。

3. Hadoop配置文件的实战拆解

3.1 下载解压与环境变量配置

我这次使用的是Hadoop 3.x版本的稳定发行包。下载解压到/opt/hadoop目录下,并将Hadoop的bin和sbin目录加入PATH环境变量。在~/.bashrc中追加:

export HADOOP_HOME=/opt/hadoop export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

然后source ~/.bashrc使配置生效。

Hadoop的配置集中在$HADOOP_HOME/etc/hadoop/目录下。虽然新版Hadoop将部分配置抽取到了hadoop-env.sh等env脚本中,但核心的五个配置文件仍是:core-site.xml、hdfs-site.xml、yarn-site.xml、mapred-site.xml和workers(旧版本叫slaves)。下面我一个一个拆解。

3.2 core-site.xml与hdfs-site.xml配置

core-site.xml负责全局参数,核心是设置默认文件系统。

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

第一个参数把默认文件系统指定为HDFS,并指明了NameNode的通信地址和端口。第二个参数指定了Hadoop临时目录,这个目录会被NameNode和DataNode用来存放一些运行时数据。这个目录建议手动创建并确保属主正确:

mkdir -p /opt/hadoop/tmp chown -R hadoop:hadoop /opt/hadoop/tmp

hdfs-site.xml是HDFS的核心配置,设置副本数、NameNode元数据和DataNode数据块的存储路径:

<configuration> <property> <name>dfs.replication</name> <value>2</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>/opt/hadoop/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>/opt/hadoop/datanode</value> </property> </configuration>

副本数我设置为2,因为集群只有两台DataNode,副本数设为3会导致第三个副本写入失败。如果后续扩容到3台以上,可以改成3。

namenode和datanode的数据目录也需要在每台机器上手动创建,注意主节点需要创建namenode目录,所有节点(包括主节点和两个工作节点)都要创建datanode目录。这是因为主节点也可以作为DataNode参与存储,这里我让主节点也运行DataNode进程,以充分利用磁盘资源。

这里有一个关键的“为什么”:NameNode的数据目录绝对不能和DataNode的数据目录放在同一个物理磁盘上。因为NameNode管理的是整个文件系统的元数据,一旦损坏整个集群就废了;而DataNode存储的是数据块,丢失后还能通过副本恢复。生产环境通常用两块独立磁盘分开放,实验环境下至少也要放在不同目录。

3.3 yarn-site.xml与mapred-site.xml配置

YARN是Hadoop的资源调度器,负责给MapReduce或其他计算框架分配CPU和内存。yarn-site.xml里需要设置ResourceManager所在的主机,以及NodeManager的资源分配:

<configuration> <property> <name>yarn.resourcemanager.hostname</name> <value>master</value> </property> <property> <name>yarn.nodemanager.resource.memory-mb</name> <value>8192</value> </property> <property> <name>yarn.nodemanager.resource.cpu-vcores</name> <value>4</value> </property> <property> <name>yarn.scheduler.maximum-allocation-mb</name> <value>4096</value> </property> <property> <name>yarn.nodemanager.vmem-check-enabled</name> <value>false</value> </property> <property> <name>yarn.nodemanager.pmem-check-enabled</name> <value>false</value> </property> </configuration>

这里的内存和CPU数值以你的机器实际配置为准。假如每台工作节点有16GB内存、8核CPU,那么yarn.nodemanager.resource.memory-mb可以设为12GB(预留部分给操作系统和DataNode进程),cpu-vcores可以设为6。

我把虚拟内存检查和物理内存检查都设为了false,这个操作单机跑可能无所谓,但在多节点环境里,如果某个Container实际占用内存超过设定值,NodeManager可能会强制杀掉这个任务,导致作业莫名失败。关闭检查可以规避这类问题,代价是单个任务可能占用过多内存。如果你完全掌控了任务的资源需求,关闭更省心;如果集群是多租户共用,建议保持默认开启。

mapred-site.xml配置MapReduce的运行时框架为YARN:

<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> <property> <name>mapreduce.jobhistory.address</name> <value>master:10020</value> </property> </configuration>

3.4 配置workers文件并同步到所有节点

Hadoop 3.x版本的workers文件($HADOOP_HOME/etc/hadoop/workers)取代了旧版的slaves文件,内容是一行一个主机名,这里要写入所有DataNode和NodeManager的主机名:

master worker1 worker2

我让master也作为DataNode和NodeManager参与计算,所以也写在workers里。如果你的主节点资源比较紧张,可以不把它加入workers,只让它跑NameNode和ResourceManager。

配置全部完成后,用rsync命令把整个配置目录同步到所有节点:

rsync -avz /opt/hadoop/etc/hadoop/ worker1:/opt/hadoop/etc/hadoop/ rsync -avz /opt/hadoop/etc/hadoop/ worker2:/opt/hadoop/etc/hadoop/

这一步千万别省。集群配置不一致导致的诡异问题,比代码bug难排查得多。我早期犯过这个错,在主节点改了一个参数忘记同步,结果两台DataNode行为和主节点不一致,现象是部分数据块写入失败但进程都活着,排查了很久。

4. 集群启动与功能验证

4.1 格式化NameNode与首次启动

在首次启动之前,必须先格式化NameNode。这一步会初始化HDFS的元数据存储目录,生成唯一的clusterID:

hdfs namenode -format

这个命令只需要在主节点上执行一次就行。启动之后,DataNode启动时会把自身的clusterID和NameNode的clusterID做比对,如果不一致就会拒绝注册,表现就是DataNode反复启动然后自动退出。

这里必须强调一个很多新手都踩过的坑:格式化操作会重新生成clusterID,如果你在集群启动之后因为某个故障再次执行了格式化,那么DataNode上原有的clusterID就和NameNode新的clusterID对不上了,所有DataNode都会起不来。所以格式化nameNode要极其慎重,最好在格式化之前确认所有节点都是干净的,或者根本没有启动过集群。

格式化完成后,在主节点依次启动HDFS和YARN:

start-dfs.sh start-yarn.sh

如果配置正确,脚本会通过SSH逐台启动守护进程。一台台地看,可以用jps命令检查进程是否都起来了。在主节点应该能看到NameNode、ResourceManager、DataNode、NodeManager四个进程,在两个工作节点上应该能看到DataNode和NodeManager。

4.2 HDFS命令行验证

进程起来了不代表集群真的可用,还要验证HDFS的读写功能。

首先创建用户目录并查看状态:

hdfs dfs -mkdir -p /user/hadoop hdfs dfs -ls /

然后上传一个本地文件到HDFS,我这里直接用了Hadoop自带的配置测试文件:

hdfs dfs -put /opt/hadoop/etc/hadoop/core-site.xml /user/hadoop/ hdfs dfs -ls /user/hadoop/

用hdfs dfsadmin -report查看各DataNode的存储状态:

hdfs dfsadmin -report

输出中会列出每个DataNode的IP、剩余空间、存储容量等信息。如果两个DataNode都在线,说明HDFS层已经正常工作。

4.3 运行WordCount验证计算能力

HDFS能读写文件只是第一步,集群的价值在于计算。我用Hadoop自带的WordCount示例做一次端到端测试:

hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.x.x.jar wordcount /user/hadoop/core-site.xml /user/hadoop/output

执行完成后,查看输出结果:

hdfs dfs -cat /user/hadoop/output/part-r-00000

如果输出了每个单词的出现次数,说明MapReduce任务从提交、分配到执行的整个闭环都打通了。这时候再去访问两个Web界面做进一步确认。

通过Web界面可以直观地验证集群状态,在浏览器里访问http://master:9870查看NameNode的Web UI,能看到HDFS的存储总容量、存活节点数和每个数据块的状态;访问http://master:8088查看YARN的集群资源状况,能看到Active Nodes数量以及每个节点的可用内存和核数。

5. 常见问题与排查实录

5.1 DataNode进程反复启动后退出

这是在多节点环境下最常见的故障。表现是群启动后,主节点和两个工作节点都狂刷日志,DataNode进程要么根本起不来,要么起来后几秒就自动退出。

排查路径:查看DataNode日志。

tail -100 /opt/hadoop/logs/hadoop-hadoop-datanode-worker1.log

如果日志里出现java.io.IOException: Incompatible clusterIDs,原因就是我前面说的——NameNode被重复格式化过,导致集群ID不一致。这种场景的解决办法有几个,我最常用的是保留原有的namenode数据目录,直接修改datanode数据目录下的current/VERSION文件里的clusterID,使它和NameNode的保持一致,然后重启。简单粗暴的办法是同时清理所有节点的namenode和datanode目录,然后重新格式化,但代价是所有已存储的数据都会丢失,生产环境禁用。

5.2 SSH免密配置不生效

另一种高发问题:免密配置完成后,执行ssh worker1仍然提示输入密码,或者出现Permission denied (publickey)。

排查时先确认密钥是否真的分发成功:

ssh -vvv worker1

如果输出显示Offering public key,但服务端拒绝了,优先检查目标机器上的/etc/ssh/sshd_config是否启用了PubkeyAuthentication yes。Ubuntu默认是开启的,如果被改过就要改回来并重启ssh服务。

最常见的还是权限问题。用以下命令修正:

chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys

曾经有个项目里所有机器都是某云厂商的镜像,它们的sshd配置里加了AuthorizedKeysFile .ssh/authorized_keys但路径没有展开到用户家目录,导致所有用户的公钥都无法识别,查看日志才发现是模板配置问题。这类问题很难预先预料,只能靠经验积累,多看一眼sshd_config总是对的。

5.3 防火墙与端口不通

集群启动后,主节点进程都正常,但从Windows本机浏览器访问http://master:9870一直超时。

排查步骤:

# 在主节点确认端口监听 sudo netstat -tlnp | grep 9870 # 在三台机器上检查防火墙状态 sudo ufw status

如果ufw是active状态,要么关闭,要么放行所需端口。我用的是放行:

sudo ufw allow 9870/tcp sudo ufw allow 8088/tcp sudo ufw allow 9000/tcp sudo ufw allow 8020/tcp sudo ufw allow 50010/tcp sudo ufw allow 50020/tcp

如果是云主机,还要在云平台的安全组规则里放行这些端口。很多云厂商默认只允许22端口,其他端口外部无法访问。这一块属于环境差异,不同云平台设置位置不同,但排查思路是一样的:先本机确认监听正常,再检查防火墙,再检查安全组。

5.4 集群启动慢与磁盘空间不足

有时候集群不是起不来,而是启动过程异常慢,或者运行一段时间后任务开始大面积失败。

先排查磁盘空间。DataNode存储空间满了,会导致文件写入失败,上传文件报datanode.DiskOutOfSpaceException。用df -h检查每台机器的磁盘占用,如果有机器空间告警,及时清理或扩容。

内存也是一个隐患。Hadoop守护进程本身占用内存,YARN容器又需要额外内存。如果机器内存是8GB,YARN堆内存设了6GB,操作系统加上NameNode进程就可能把内存吃满,触发OOM Killer。这类问题不一定会直接报内存错误,而是表现为某个DataNode进程莫名消失。排查时看系统日志:

dmesg | grep -i oom

如果有Out of memory: Kill process的记录,说明确实是内存不足。解决思路是重新评估YARN允许分配的内存上限,留足系统余量。

5.5 常见问题速查表

我把上面这些故障和排查方法整理成了一张表,方便你在实际遇到问题时快速对照。

故障现象可能原因排查命令/方法
DataNode启动即退出clusterID不匹配cat /opt/hadoop/datanode/current/VERSION,和NameNode的VERSION比对
SSH免密不生效权限问题或sshd配置chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys,检查sshd_config
进程正常但Web UI打不开防火墙或云安全组未放行sudo netstat -tlnp检查监听,sudo ufw status检查防火墙
Worker节点始终不在线hosts配置错误或网络不通ping worker1,检查所有机器的/etc/hosts
任务提交后直接失败内存配置过大,节点无资源yarn node -list -all查看节点资源,确认nodemanager.resource.memory-mb
上传文件报磁盘满数据目录所在磁盘空间不足df -h /opt/hadoop/datanode,清理或扩展磁盘

6. 实操心得与后续扩展建议

集群搭建好之后,我习惯再花几分钟做几个优化动作,这些往往不是教程里必写的,但实际用下来很值得。

第一件事是确认集群的时间同步。分布式系统的元数据时间戳如果不一致,后来的维护和日志排查会非常痛苦。Ubuntu默认装了systemd-timesyncd,简单确认一下服务处于active状态即可。

第二件事是验证主节点的高可用能力。我搭的虽然是单NameNode集群,但至少要知道NameNode挂掉后怎么快速恢复。通常做法是把namenode目录定期备份到远程,或者配置SecondaryNameNode定期合并日志。对实验环境来说,做到“知道恢复流程”就够了,生产环境建议直接上高可用方案。

第三件事是提前规划数据目录的空间。Hadoop不像数据库,不会主动做容量规划,数据写满磁盘是迟早的事。给每个DataNode的/opt/hadoop/datanode单独挂一块大容量盘,比让它在系统盘上和其他数据挤在一起要稳得多。

如果后续需要扩容,可以把新机器装好JDK、配置好SSH免密,把主节点配置目录同步到新机器,然后启动DataNode和NodeManager进程,新节点会自动注册进集群。整个过程不需要重启现有节点,这也是Hadoop比较友好的设计之一。

最后分享一个小技巧。千万记得给Hadoop配置添加自定义的log4j日志级别调整,我在测试阶段习惯把日志级别调高,能看到更多任务内部执行细节。等集群稳定运行后再调回WARN级别,避免日志刷屏影响排查。

关于Ubuntu下Hadoop集群的搭建,最核心的一点不是某个配置项怎么写,而是把握住“配置一致性”和“权限正确性”这两条底线。前者依靠rsync和统一的配置文件管理,后者依靠规范的目录和文件权限。只要这两点做扎实了,集群基本不会出什么大乱子。剩下的就是遇到问题别慌,按第5节的排查路径一步步看日志、查网络、核配置,绝大多数故障都能在半小时内定位。

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

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

立即咨询