
1. 为什么每个学大数据的人都绕不开这三种安装模式先说我自己的经历。第一次接触Hadoop时我照着网上的教程折腾了整整两天最后集群没起来倒是把虚拟机搞崩了三次。问题出在哪教程东一篇西一篇有的讲单机版有的直接上三节点集群我根本分不清它们之间的区别也不知道自己当前到底该用哪一种。后来把三种模式彻底理了一遍才明白Hadoop的安装配置其实就三条路本地模式Local Mode、伪分布式模式Pseudo-Distributed Mode、完全分布式模式Fully-Distributed Mode。三者的区别不只是“几台机器”这么简单而是映射了你的实际需求是想跑通一个示例验证环境还是想模拟完整的分布式流程或者是搭建一个真正能用于开发测试的集群。这篇内容就是我从零开始配置三种模式的完整记录包含每一步的配置文件和参数含义以及我在实验过程中遇到的报错和排查过程。适合刚接触Hadoop、准备做实验或者正在搭开发环境的人参考不管你是用虚拟机、云服务器还是自己的笔记本思路都是通用的。有一点先说清楚这篇文章里所有的路径、版本号和配置参数我都以Hadoop 3.x和JDK 1.8的组合为例这也是目前大多数大数据课程和实验环境采用的主流组合。你用2.x版本时部分配置项名称会有差异我会在对应位置标注出来。2. 开始之前必须想明白的三个问题配置Hadoop之前先别急着解压安装包。我把身边同学踩过的坑归拢了一下发现大部分问题都出在下面这三个环节提前搞定它们能省下大量排查时间。2.1 JDK版本和Hadoop版本怎么匹配很多人的第一个坑就是JDK版本不对。Hadoop对JDK的版本要求非常明确以Hadoop 3.x为例官方文档标注支持Java 8和Java 11但实际实验中最稳的是JDK 1.8。我试过用JDK 17跑Hadoop 3.3.x结果启动NameNode的时候直接报UnsupportedClassVersionError折腾了半小时查日志才发现是版本问题。安装完JDK后第一件事就是在终端里确认版本号java -version正常情况下应该输出类似这样的内容java version 1.8.0_202 Java(TM) SE Runtime Environment (build 1.8.0_202-b08) Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)同时需要配置JAVA_HOME环境变量。网上的教程让你改/etc/profile、~/.bashrc都行我的习惯是写在~/.bashrc里这样只对当前用户生效不会影响系统全局环境export JAVA_HOME/usr/local/jdk1.8.0_202 export PATH$JAVA_HOME/bin:$PATH改完之后执行source ~/.bashrc让它立即生效再用echo $JAVA_HOME验证一下能正常输出路径就说明配好了。2.2 主机名、IP和hosts映射最好提前规划这一点在做完全分布式模式的时候特别重要但哪怕只是搭伪分布式我也建议提前规划好。因为Hadoop内部组件之间通信时用的是主机名如果主机名解析不对轻则启动慢重则节点之间互相找不到对方。修改主机名用这个命令hostnamectl set-hostname hadoop01然后编辑/etc/hosts文件把IP和主机名的映射关系写进去192.168.10.10 hadoop01 192.168.10.11 hadoop02 192.168.10.12 hadoop03注意不要用127.0.0.1或者localhost来代替集群中其他节点的IP否则分布式模式下NameNode和DataNode之间的心跳通信会出问题。我见过有人直接在hosts里写127.0.0.1 hadoop01结果三台机器互相访问的时候全指向本机了DataNode一直注册不上。2.3 SSH免密登录要提前配好Hadoop的守护进程启动时需要远程到各个节点去拉起来这个过程就是靠SSH来做的。如果不配置免密每次启动集群都要输一堆密码而且脚本自动化执行的时候根本没法输入所以免密登录是必需项。最简单的验证方法是先对当前用户生成密钥ssh-keygen -t rsa -P 一路回车-P 的意思是不设置密码短语生成后直接测试ssh localhost如果不需要输密码就能登录说明本机免密已经生效。做成完全分布式的时候还需要把公钥分发到各台机器具体操作我在后面完全分布式的部分会详细讲。3. 本地模式十分钟验证Hadoop环境能跑起来本地模式是Hadoop最简单的一种部署方式它的特点是所有进程都在同一个Java虚拟机里运行不启动HDFS不启动YARN也不涉及任何分布式文件系统和资源调度。它存在的意义就是让你快速验证Hadoop环境是否安装正确、依赖是否完整。3.1 本地模式的原理和适用场景很多人不理解为什么要有本地模式觉得“不就是能跑个wordcount吗有什么用”。这种想法不太对。本地模式的价值在于它是一个最底层的环境自检如果连本地模式都跑不起来那伪分布式和完全分布式就更不用谈了。本地模式下Hadoop会使用本地文件系统作为输入输出没有NameNode和DataNode这些角色的概念。比如在本地模式运行一个WordCount示例大致流程是MapReduce框架在当前JVM里读本地文件经过Map阶段和Reduce阶段再把结果写到本地目录。整个过程可以理解为“用Hadoop的API在本地模拟了一次MapReduce计算”因为不涉及跨进程和跨节点调度所以速度非常快适合做功能验证。3.2 解压和配置的完整流程首先把下载好的Hadoop安装包解压到你想要的目录tar -zxvf hadoop-3.3.4.tar.gz -C /usr/local/解压后进入Hadoop目录你会看到一系列子目录。第一次接触的人可能有点懵我简单列一下最关键的几个目录作用binHadoop命令存放位置后续所有操作都要用到这里面的脚本etc/hadoop所有配置文件所在目录配置工作主要就是改这里sbin守护进程启动和停止脚本比如start-dfs.shshare自带的示例包和jar包WordCount示例就在这里接着需要修改etc/hadoop/hadoop-env.sh文件把JDK路径告诉Hadoop因为Hadoop启动脚本需要找到Javaexport JAVA_HOME/usr/local/jdk1.8.0_202修改完这个之后检查一下Hadoop的版本号看看安装是否正常cd /usr/local/hadoop-3.3.4 bin/hadoop version如果输出了类似下面的内容说明Hadoop本身已经能正常用Java运行了Hadoop 3.3.4 Java 1.8.0_202 ...3.3 跑通官方自带的WordCount示例验证环境官方自带的示例包在share/hadoop/mapreduce/目录下是一个名为hadoop-mapreduce-examples-3.3.4.jar的jar包。我们直接在本地模式跑一下WordCount作为环境验证的标准动作。先在Hadoop目录下创建一个临时输入文件随便写几行内容mkdir input echo hello hadoop hello world input/test.txt然后执行bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.4.jar wordcount input output执行过程中会打印一堆日志看到类似于Map-Reduce Framework的输出信息时说明任务正在走MapReduce流程。执行完成后查看输出文件cat output/part-r-00000如果正常输出hadoop 1 hello 2 world 1就说明本地模式完全没问题了。这里有一个我踩过的细节第二次运行wordcount之前必须先把output目录删掉否则会报Output directory output already exists错误。这是因为Hadoop的MapReduce框架出于安全考虑不允许不经确认就覆盖已有输出目录。实验的时候每次重跑都要rm -rf output这个动作要养成肌肉记忆。4. 伪分布式模式一台机器上模拟出完整集群本地模式跑通之后下一步就是伪分布式。伪分布式的核心价值在于它让HDFS、YARN、MapReduce这些分布式组件都以真实进程的形式在你本机上运行虽然都挤在一台机器里但角色之间的通信、调度逻辑和完全分布式是一致的。对于学习Hadoop的运行机制来说伪分布式是最划算的投入。4.1 伪分布式和本地模式的关键差异伪分布式模式下格局发生了变化HDFS启动了NameNode和DataNode两个进程一个负责元数据管理一个负责实际数据块存储YARN启动了ResourceManager和NodeManager进程开始有资源调度和任务分配的概念分布式文件系统输入输出的存储介质不再是本地文件系统而是HDFSgraph TD A[本地模式] -- B[进程全在一个JVM] A -- C[没有HDFS/YARN] D[伪分布式] -- E[每个守护进程独立JVM] D -- F[有HDFS/YARN] D -- G[部署在一台机器上]4.2 核心配置文件逐个拆解伪分布式模式需要修改两组核心配置文件core-site.xml和hdfs-site.xml。网上教程往往一句话“把如下内容粘贴进去”就完了但如果你不知道每个参数的含义后面出了问题的排查成本非常高。我把参数拆开讲。第一个是etc/hadoop/core-site.xml它的作用是指定HDFS的NameNode地址以及临时文件目录。configuration property namefs.defaultFS/name valuehdfs://localhost:9000/value /property property namehadoop.tmp.dir/name valuefile:///usr/local/hadoop-3.3.4/tmp/value /property /configurationfs.defaultFS的值是hdfs://localhost:9000意味着所有HDFS操作默认连接到本机9000端口上的NameNode。hadoop.tmp.dir参数指定元数据和数据块的存储根目录。注意这个参数默认值是/tmp/hadoop-${user.name}而系统/tmp目录重启后在大多数Linux发行版中会被清空这就可能导致NameNode格式化后的元数据丢失所以务必改到自己的Hadoop安装目录下。第二个是etc/hadoop/hdfs-site.xml主要配置数据块副本数量。伪分布式因为只有一个DataNode副本数只能设为1如果保持默认的3DataNode会一直尝试复制副本报出一堆健康警告。configuration property namedfs.replication/name value1/value /property /configuration4.3 格式化NameNode这一步不能省配置改完之后需要执行一次NameNode格式化。这个操作的作用是初始化文件系统元数据存储结构相当于给磁盘文件系统做一次格式化。以后的每次启动都是基于这次格式化产生的结果。bin/hdfs namenode -format执行成功的标志是日志中出现了类似successfully formatted的提示以及在/usr/local/hadoop-3.3.4/tmp/dfs/name/current目录下生成了VERSION、edits_0000000000000000000、fsimage_0000000000000000000等文件。这是我踩得最惨的坑Hadoop只能格式化一次或者更准确地说重复格式化会让NameNode生成的clusterID和DataNode已存储的clusterID不一致导致DataNode启动后无法向NameNode注册。实验中如果你必须重新格式化一定要先删掉tmp目录下的所有内容让NameNode和DataNode在相同的clusterID下重新初始化否则你就得在日志里看到我见过的那句Incompatible clusterIDs了。4.4 启动HDFS并验证进程状态格式化完成后就可以启动HDFS了sbin/start-dfs.sh在启动过程中会要求你输入SSH密码如果你提前配置了ssh localhost免密就会直接跳过。启动完成后用JPS命令检查Java进程jps正常情况下应该看到四个进程进程名作用NameNodeHDFS的命名节点管理文件系统的命名空间DataNode数据节点存储实际数据块SecondaryNameNode辅助NameNode合并编辑日志JpsJPS命令自身不用管它如果少了其中任何一个优先去Hadoop根目录下的logs/目录看对应日志文件。日志是最好的排错信息源我在后面的排错部分会再展开。4.5 验证HDFS读写和Web UI启动后在HDFS上创建一个目录再上传一个文件测试读写bin/hdfs dfs -mkdir -p /user/root/input bin/hdfs dfs -put input/test.txt /user/root/input/ bin/hdfs dfs -cat /user/root/input/test.txt能正常显示文件内容就说明HDFS的读写链路是通的。另外NameNode提供了一个Web UI界面浏览器访问http://localhost:9870这是Hadoop 3.x的默认端口2.x版本是50070。界面上能看到集群的健康状态、DataNode在线列表和HDFS存储使用情况。一个容易出现的坑是端口访问不了如果你是在云服务器或者虚拟机上配置的检查一下防火墙和安全组有没有放通9870端口。5. 完全分布式模式三节点集群从规划到启动的完整记录完全分布式才是Hadoop“分布式”的真正体现多台机器、各自独立的进程、通过网络通信协同工作。实验环境和生产环境大多采用这种模式所以这一部分值得仔细过一遍。5.1 节点规划主节点和从节点怎么分工我的实验环境是三台虚拟机操作系统都是CentOS 7.9。规划如下节点主机名角色主节点hadoop01NameNode、ResourceManager从节点1hadoop02DataNode、NodeManager从节点2hadoop03DataNode、NodeManager为什么这样规划完全分布式的核心角色中NameNode负责管理整个文件系统的命名空间ResourceManager负责YARN的资源管理和作业调度这两个角色对机器的资源要求较高放在主节点。DataNode负责数据块存储NodeManager负责具体计算任务的执行它们是真正干活的可以分布在多台从节点上。如果你还想加一个SecondaryNameNode角色我记得常见的做法是把它放到另一台机器上避免和NameNode同机这样可以分散单点压力。实验环境里如果不加也不影响核心功能验证。5.2 三台机器共用的环境准备三台机器都需要准备一份相同的JDK和Hadoop安装环境。快手做法是在一台机器上配置好然后通过SCP分发过去scp -r /usr/local/jdk1.8.0_202 roothadoop02:/usr/local/ scp -r /usr/local/hadoop-3.3.4 roothadoop02:/usr/local/别忘了修改每台机器的/etc/hostname和/etc/hosts。还有hadoop-env.sh里JAVA_HOME的路径三台机器要保持一致。5.3 完全分布式的五个核心配置文件相比伪分布式完全分布式需要配置的文件数量更多。我按表格列出每个文件的职责再逐个说明关键参数配置文件作用core-site.xmlHDFS地址、临时目录等核心配置hdfs-site.xml副本数、NameNode和SecondaryNameNode地址yarn-site.xmlYARN资源调度相关配置mapred-site.xmlMapReduce运行框架配置workers声明哪些主机是DataNode/NodeManagercore-site.xml配置在主节点上configuration property namefs.defaultFS/name valuehdfs://hadoop01:9000/value /property property namehadoop.tmp.dir/name valuefile:///usr/local/hadoop-3.3.4/tmp/value /property /configuration注意这里fs.defaultFS的值由localhost换成了主节点的主机名hadoop01因为从节点需要通过主机名找到NameNode用localhost的话从节点就会尝试连自己导致整个集群完全无法通信。hdfs-site.xmlconfiguration property namedfs.replication/name value2/value /property property namedfs.namenode.secondary.http-address/name valuehadoop02:50090/value /property /configuration副本数设为2而不是3这是实验环境下的常见选择。因为只有三个节点如果设3三个DataNode各存一份也没有问题但从节省空间的角度没必要。设为2表示除了本节点之外再找一个节点存一份副本在节点故障时能恢复数据即可。yarn-site.xmlconfiguration property nameyarn.resourcemanager.hostname/name valuehadoop01/value /property property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property /configuration第一个参数指定ResourceManager跑在哪台机器上第二个参数mapreduce_shuffle是MapReduce任务执行时的辅助服务属于YARN运行MapReduce作业的必要配置。很多教程会漏掉第二项漏掉之后作业提交到YARN时会在Shuffle阶段报错。mapred-site.xmlconfiguration property namemapreduce.framework.name/name valueyarn/value /property /configuration这个参数告诉MapReduce作业的运行框架是YARN而不是内置的本地框架。漏了它的话作业不会提交到集群上执行。workers文件Hadoop 3.x叫workers2.x叫slaveshadoop02 hadoop03这个文件的作用是声明哪些节点是Worker节点启动脚本会根据内容去远程拉起DataNode和NodeManager。注意文件里每行一个主机名不能有空格或者多余字符。5.4 把配置同步到所有节点所有配置都在主节点上改好之后用SCP把整个Hadoop配置目录同步到从节点scp -r /usr/local/hadoop-3.3.4/etc/hadoop/* roothadoop02:/usr/local/hadoop-3.3.4/etc/hadoop/ scp -r /usr/local/hadoop-3.3.4/etc/hadoop/* roothadoop03:/usr/local/hadoop-3.3.4/etc/hadoop/从节点上不需要单独改配置因为核心配置里写的是主节点的主机名从节点启动时会自动去连接主节点。5.5 SSH免密登录的完整配置动作完全分布式模式下主节点需要无密码登录到所有从节点才能远程启动守护进程。前置条件是把主节点的公钥写到从节点的authorized_keys文件里# 在主节点上执行 ssh-keygen -t rsa -P ssh-copy-id roothadoop01 ssh-copy-id roothadoop02 ssh-copy-id roothadoop03然后逐台验证ssh hadoop01 ssh hadoop02 ssh hadoop03能不打密码直接进去就说明免密配置成功。5.6 格式化NameNode并启动集群完全分布式模式下格式化操作只需要在主节点上执行一次bin/hdfs namenode -format格式化完成后启动HDFS和YARNsbin/start-dfs.sh sbin/start-yarn.sh启动完成后在主节点上执行jps应该看到NameNode ResourceManager在从节点上执行jps应该看到DataNode NodeManager再到Web UI上检查集群状态。HDFS的Web UI和伪分布式一样是http://hadoop01:9870YARN的Web UI是http://hadoop01:8088。YARN的界面上能看到NodeManager列表正常情况下应该有两台节点在线。5.7 提交一个真正的分布式作业在生成环境中验证集群是否工作正常最直接的方式是提交一个作业到集群上跑。先在HDFS上建目录、传文件bin/hdfs dfs -mkdir -p /user/root/input bin/hdfs dfs -put input/test.txt /user/root/input/然后提交WordCountbin/yarn jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.4.jar wordcount /user/root/input /user/root/output执行完之后用命令检查结果bin/hdfs dfs -cat /user/root/output/part-r-00000到这一步完全分布式集群就算真正搭建完成并且能跑作业了。6. 三台机器搭建过程中最容易翻车的五个问题配置过程很少是一帆风顺的我把自己实验中遇到过的问题列出来这些问题有一定的共性提前了解能省下不少排查时间。6.1 DataNode进程起不来clusterID不一致现象主节点NameNode正常启动但从节点的DataNode进程反复挂掉日志里报Incompatible clusterIDs或者java.io.IOException: NameNode is not formatted。原因重复格式化了NameNode导致NameNode生成了新的clusterID而DataNode数据目录里存的还是旧的clusterID。解决方式在所有节点上删除临时目录下的DFS数据然后回到主节点重新格式化rm -rf /usr/local/hadoop-3.3.4/tmp/dfs/ bin/hdfs namenode -format格式化后同步到所有从节点重启start-dfs.sh。这一步做完之后我特地对比了一下tmp/dfs/name/current/VERSION和tmp/dfs/data/current/VERSION里的clusterID确认一致后才启动此后DataNode就没有再掉线过。6.2 虚拟内存超出限制导致Container被杀死现象作业提交到YARN后Map或Reduce任务反复失败日志里频繁出现Container is running beyond virtual memory limits之类的报错。原因默认情况下每个NodeManager容器能被分配的内存有限虚拟内存超过阈值就会被杀死。这在虚拟机环境下非常常见因为虚拟机的内存本来就小。解决方式打开YARN的yarn-site.xml把虚拟内存比调大或者直接关掉这个检查property nameyarn.nodemanager.vmem-check-enabled/name valuefalse/value /property如果希望更精确地限制也可以同时调整yarn.nodemanager.vmem-pmem-ratio的值为4或更高。关掉检查实测最省心前提是集群只用于实验环境。6.3 SSH免密配置好依然要输密码现象主节点SSH到从节点仍然要求输密码。原因SSH对目录和文件的权限要求非常严格.ssh目录的权限必须为700authorized_keys文件的权限必须为600权限过宽会导致SSH拒绝读取公钥。解决方式chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys另一个容易被忽略的点是你当前登录的用户必须和生成密钥的用户一致。比如用root生成密钥就要确保远程连接时用的也是root用户。6.4 端口不通Web UI无法访问现象在宿主机浏览器上访问http://hadoop01:9870页面一直打不开但节点内部访问正常。原因最常见的是防火墙未放行端口或者是云服务器的安全组配置没加规则。解决方式systemctl stop firewalld systemctl disable firewalld如果是在云服务器上还需在控制台的安全组中添加9870和8088端口的入站规则。这一步容易被忽略但实验环境对安全性要求不高的情况下直接关闭防火墙是最快的方法。6.5 主节点执行start-dfs.sh后从节点没有任何反应现象主节点上执行start-dfs.sh只启动了本机的NameNode和DataNode从节点上什么进程都没起。原因workers文件配置有问题或者主节点没有配置到从节点的SSH免密。解决方式首先确认workers文件里的内容注意文件名在Hadoop 3.x是workers在2.x是slaves如果你改了Hadoop版本却沿用旧教程很可能就是在改一个不再起作用的文件。然后验证SSH免密ssh hadoop02如果无法免密进入重新执行ssh-copy-id。另外一个容易犯的错误是workers文件里包含hadoop01主节点自身如果你希望主节点不启动DataNode就不要把它写进去。7. 三种模式里我在实际配置中的选择建议站在实验角度把三种模式都过了一遍的人最后多半会回到一个问题上实际场景中我应该选哪种模式我的建议很简单。如果你只是验证Hadoop安装成功没有本地模式就够了五分钟跑完一个WordCount不需要处理任何配置文件的复杂度如果你想学习HDFS的读写流程、YARN的调度逻辑或者准备做后续的HBase、Hive集成实验伪分布式是最合适的因为单机就能模拟出完整链路排错成本也低如果你想模拟真实的集群环境或者需要跑多个节点的实验比如MapReduce的分布式计算效果验证、HDFS副本机制观察完全分布式才值得你花时间搭一遍。我见过不少同学一上来就搭三节点集群结果配置了三天毫无进展最后回头先把伪分布式摸透了再回来看完全分布式就觉得豁然开朗。这背后的原因是分布式系统涉及的角色多、网络通信链路长如果对单机版运行机制不理解多机环境的问题会让你根本不知道从哪个日志开始看起。就我自己而言三台虚拟机的配置目前依然保留着虽然实验已经结束但后续再做Spark、Flume或者HBase的集成实验时直接在这个集群上扩展就行不用一切从零开始。这也是我建议你把完全分布式搭好的原因——它不只是这周实验的交付物更是后面整个大数据学习周期的底层平台。