资讯动态

云主机搭建Hadoop集群全指南:从配置到验证

发布时间:2026/10/18 11:22:04 来源:尧图企业网站定制
最近被问得最多的一个问题能不能在云主机上把 Hadoop 集群搭起来用来做课程设计或者跑点实验数据。我给的回答通常是“能而且值得折腾一次”但前提是你别照着两三年前的旧教程闷头装因为云环境的网络模型、系统版本还有 Hadoop 的版本演进都会让旧教程翻车。这篇文章我就把从零搭建到测试完成的全过程写出来包括版本怎么选、配置文件每个字段为什么那么写、第一次格式化 NameNode 需要付出什么代价以及测试完之后怎么把云资源收拾干净。不管你是准备做毕业设计的学生还是刚入行想熟悉大数据生态的开发者照着这套思路走下来至少能少踩我当初踩过的那一堆坑。1. 先回答一个关键问题为什么要在云主机上搞集群1.1 本地虚拟机和云主机的体验差异很多人第一反应是在自己电脑上开几个虚拟机用 VMware 或者 VirtualBox 把三台 CentOS 跑起来觉得这样不花钱。我自己大一的时候也是这么干的但实际体验并不好。笔记本内存 16G开三台虚拟机每台分 2G再加上本机系统占用几乎什么都干不了磁盘 IO 还特别慢格式化 NameNode 或者启动 DataNode 的时候那进度条慢得让人怀疑人生。更麻烦的是本地虚拟机的网络是 NAT 或桥接三台机器之间的通信有时候会莫名其妙地不通排查起来特别耗时间。换到云主机之后最直观的感受就是三台机器是独立的公网实例内网互通是云厂商帮你搞好的网络层面的坑少了一大半。而且云主机按量付费搭完测试完直接释放成本可能就是一杯奶茶钱。对学习场景来说云主机还更接近真实的生产环境你能体验到安全组、公网 IP、内网 IP、弹性 IP 这些概念这些是本地虚拟机给不了你的。1.2 云上环境特有的三个前提条件在正式动手之前有几个云环境特有的前提必须心里有数不然搭到一半会发现推倒重来都来不及。第一个是计费方式。如果你只是为了搭集群跑个测试强烈建议选“按量付费”而不是包年包月。按量付费可以随时释放实例按小时计费测试两三天完全没问题。包年包月看着单价低但你如果只用一星期剩下的时间全在浪费钱。第二个是 IP 的区分。云主机一般有两个 IP公网 IP 和内网 IP。你 SSH 登录用的是公网 IP但集群节点之间通信应该用内网 IP。很多人不注意这一点配置文件里写了公网 IP结果节点间通信走公网流量跑一次任务流量费就能让你肉疼。而且内网 IP 一般不会变但公网 IP 如果你释放再开机很可能就换掉了这也是一个隐患。第三个是安全组。安全组相当于云主机的防火墙规则控制哪些端口可以被哪些 IP 访问。默认情况下很多云厂商只放行了 22 端口其他端口全给你堵住。Hadoop 的 Web UI、节点通信端口都得在安全组里手动放行否则你配置全对浏览器也打不开 9870。2. 动手前的环境准备镜像、规格和网络决定后续是否省心2.1 实例规格和镜像选择思路集群我建议至少三台一台作为 NameNode 和 ResourceManager两台作为 DataNode 和 NodeManager。这是 Hadoop 中最小的“真分布式”形态。如果你只有一台机器那只能做伪分布式学不到真正的多节点协作体验。规格方面NameNode 那台建议 2 核 4G 起步DataNode 每台 2 核 4G 也就够了。如果你要跑稍微大一点的数据2 核 4G 能撑住但别指望它跑多块。磁盘每台给 40G 到 60G 就行云盘性能和容量足够练习用。镜像选择上我用的是 CentOS 7.9。虽然这个系统已经进入维护末期但 Hadoop 生态对它支持最好资料最多遇到问题随便搜索都是一堆解决方案。你也可以选 Ubuntu 20.04系统命令上略有差异比如用户组、防火墙的默认状态但核心步骤是一样的。如果你是第一次搭我建议直接用 CentOS 7.9别在系统选择上给自己增加额外难度。2.2 JDK 版本与 Hadoop 版本搭配别在这里翻车这个环节真的是一堆人翻车的高发区。Hadoop 本身是用 Java 写的所以必须先装 JDK。版本搭配上Hadoop 3.3.x 对 JDK8 的支持最稳定你用 OpenJDK 8 就行不需要去折腾 Oracle JDK。JDK11 虽然也能跑 Hadoop但不少第三方组件和示例代码对 JDK8 的依赖历史最悠久你没必要拿自己宝贵的排错时间去赌版本兼容性。Hadoop 版本我选的是 3.3.6这是 3.x 系列里比较稳定的一个版本。不要一上来就追最新版也不要为了“稳定”去用 Hadoop 2.x——2.x 的 Web UI 端口、配置文件名称和 3.x 完全不同你在网上搜到的教程大概率是 3.x 的版本错位会让你很痛苦。安装 JDK 的步骤其实很简单三台机器都执行yum install -y java-1.8.0-openjdk-devel java -version注意这里一定要装-devel版本不要只装java-1.8.0-openjdk。因为 Hadoop 编译源码和寻找JAVA_HOME时需要完整的 JDK 工具链只装 JRE 的话后续会出现一些匪夷所思的错误。装完之后配置环境变量在/etc/profile里加上export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk export PATH$PATH:$JAVA_HOME/bin然后source /etc/profile使其生效。不同系统里 JDK 的安装路径可能不太一样建议先执行ls /usr/lib/jvm/看一下实际目录名再填进去。2.3 hosts 映射和内网通信这一步省掉后面会悔青肠子三台机器创建好之后第一件事是修改主机名。我在三台机器上分别设置主机名为master、worker1、worker2hostnamectl set-hostname master然后修改每台机器的/etc/hosts把三台机器的内网 IP 和主机名映射写进去。这里务必写内网 IP不要写公网 IP172.16.0.4 master 172.16.0.5 worker1 172.16.0.6 worker2顺序上建议把 master 放在最前面。配置完之后三台机器互 ping 一下如果通了再进行下一步。这一步看似基础但一旦写错后续 SSH 免密、Hadoop 启动都会出现莫名其妙的连接问题。我当初就是漏了一台机器的 hosts 配置结果 master 去连 worker2 时找不到主机名排查了半小时才发现是单词拼错了。2.4 安全组端口放行一张表讲清楚该开哪些安全组规则在云厂商控制台里配置。这里我直接给出一张端口清单照着填就行。放行对象如果是学习环境建议只对你自己的 IP 开放减小暴露面如果你是要让同学或者老师也能访问 Web UI再放行对方 IP 或者临时全放行。用途端口说明SSH 登录22默认已放行NameNode 通信9000HDFS 客户端和 DataNode 通信端口NameNode Web UI9870Hadoop 3.x 的 HDFS 管理界面DataNode 通信9866DataNode 数据传输端口SecondaryNameNode9868辅助元数据备份进程端口ResourceManager Web UI8088YARN 任务调度管理界面NodeManager 通信8042节点管理器状态页端口注意这是 Hadoop 3.x 的默认端口。如果你用了 2.xNameNode Web UI 是 50070通信端口是 8020完全不一样别对照错了。放行安全组时建议把 9000、9866 这种节点间通信用端口放行到安全组内网互访也就是源地址写内网网段。公网访问只开 22、9870、8088 这几个就够了。3. SSH 互信不是玄学把免密登录一次配明白3.1 为什么 Hadoop 必须要 SSH 免密很多人第一次搭 Hadoop 时会有个疑问我明明已经把启动脚本运行起来了为什么还是要输密码原因是这样的start-dfs.sh脚本执行时master 节点需要通过 SSH 远程登录到每台 worker 节点然后在远程执行命令去启动 DataNode、NodeManager 等进程。如果你没有配置免密脚本在等待密码输入时会卡住或者干脆报错退出。这个过程和你在终端里手动 SSH 到另一台机器是一样的只是 Hadoop 替你做完了。你可以把它理解成master 要拿着钥匙串去开启 worker 上的一扇扇门钥匙串就是 SSH 私钥门锁就是每台机器上的authorized_keys文件。3.2 密钥生成和分发步骤操作步骤不复杂但有几个细节必须注意。在 master 机器上执行ssh-keygen -t rsa -b 4096 -P -f ~/.ssh/id_rsa这里用-P 表示私钥不设置密码短语否则每次连接还是要输一遍密码等于没配。-f指定生成路径默认就是~/.ssh/id_rsa不要乱改。然后复制公钥到三台机器包括自己 masterssh-copy-id master ssh-copy-id worker1 ssh-copy-id worker2ssh-copy-id会自动把你的公钥追加到目标机器的~/.ssh/authorized_keys中。如果ssh-copy-id命令不存在可以手动执行cat ~/.ssh/id_rsa.pub | ssh rootworker1 cat ~/.ssh/authorized_keys验证免密是否配置成功ssh master ssh worker1 ssh worker2每一步都应该不需要输入密码直接返回并且退出来没问题。注意第一连接时它会提示是否确认主机指纹这不算密码输入yes回车即可。3.3 免密配置失败的最常见原因免密配置出问题十有八九是权限或者配置项的原因这里集中说一下。第一种是.ssh目录权限太宽松。SSH 对密钥文件的权限非常敏感如果~/.ssh目录别人也能写SSH 会认为不安全而拒绝使用密钥。正确权限是这样chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys第二种是云主机默认禁用了 root 的密码登录或者禁用了公钥认证。如果你在/etc/ssh/sshd_config里看到PubkeyAuthentication no改成yes并重启 sshd 服务。不过大多数情况下created 主机默认是允许 root 公钥登录的。第三种是 SELinux 的干扰。CentOS 默认开启 SELinux有时候它会阻止 SSH 读取新写入的authorized_keys文件。如果权限检查都没问题但就是连不上执行restorecon -R -v /root/.ssh恢复一下上下文或者临时把 SELinux 置为 permissive 再测试。我踩过一次这个坑密钥配置全部正确就是 SELinux 在捣乱当时真的头大。4. 五个配置文件里的每一个字段都值得理解后再填4.1 先理解 Hadoop 的角色划分在填配置之前先花一分钟理解你要配的是什么东西。Hadoop 的核心是两块HDFS 负责存储YARN 负责计算调度。HDFS 里有一台 NameNode 管理元数据可以理解成班级花名册记着每个文件放在哪个柜子里多台 DataNode 真正存数据可以理解成学生的储物柜。YARN 里有一台 ResourceManager 负责资源调度多台 NodeManager 负责干活。你要在这些配置文件里告诉 HadoopNameNode 在哪台机器、DataNode 都在哪、ResourceManager 在哪、数据放到什么目录。把这个角色图在脑子里过一遍后面每个字段都不会再感觉像是天书。4.2 hadoop-env.shJAVA_HOME 必须显式声明这个文件看起来最不起眼但坑最多。很多教程会让你在~/.bashrc里配置JAVA_HOME但在启动 Hadoop 时脚本本身不一定能读到你的~/.bashrc环境变量所以最稳妥的做法是直接编辑hadoop-env.shexport JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk这个文件在 Hadoop 安装目录的etc/hadoop/下。你可以用grep -n JAVA_HOME hadoop-env.sh找到对应的行取消注释然后填上路径。如果不配置这一步后面start-dfs.sh可能会报JAVA_HOME is not set。4.3 core-site.xml默认文件系统和临时目录的选择core-site.xml里最核心的是fs.defaultFS它决定了你的“默认文件系统”在哪里。这里写hdfs://master:9000意思是所有默认路径都用 HDFS 访问NameNode 的 RPC 端口是 9000。configuration property namefs.defaultFS/name valuehdfs://master:9000/value /property property namehadoop.tmp.dir/name value/data/hadoop/tmp/value /property /configuration第二个属性hadoop.tmp.dir是必须改的。默认情况下 Hadoop 的临时数据目录在/tmp/hadoop-*Linux 系统重启后/tmp下的文件会被清空你的 NameNode 元数据就没了。到时候你会看到一个让你怀疑人生的现象集群明明上次还在运行这次启动的时候 DataNode 怎么都连不上了。把临时目录改到一个独立的数据盘路径比如/data/hadoop/tmp并且提前创建好这个目录。4.4 hdfs-site.xml副本数和数据目录hdfs-site.xml决定了 HDFS 的行为。这里最重要的几个字段configuration property namedfs.replication/name value2/value /property property namedfs.namenode.name.dir/name value/data/hadoop/namenode/value /property property namedfs.datanode.data.dir/name value/data/hadoop/datanode/value /property property namedfs.namenode.secondary.http-address/name valuemaster:9868/value /property /configurationdfs.replication指的是每个数据块应该被复制几份。默认值是 3意味着每个块要存三份。如果你只有两台 DataNode默认 3 会导致持续出现Under replicated blocks的告警因为根本凑不齐三份副本。这里根据 DataNode 数量设置成 2或者直接用 1。学习环境用 2 比较合适既能体验副本容错也不至于产生太多冗余数据。dfs.namenode.name.dir和dfs.datanode.data.dir分别是 NameNode 和 DataNode 的数据存储目录。写在这里的好处是后续如果要格式化或者清理数据只需要删掉这两个目录就行不会误删其他文件。4.5 yarn-site.xml调度器、辅助服务和内存设定YARN 负责给 MapReduce 任务分配计算资源。yarn-site.xml里的关键配置是configuration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property property nameyarn.resourcemanager.hostname/name valuemaster/value /property property nameyarn.nodemanager.resource.memory-mb/name value2048/value /property /configurationyarn.nodemanager.aux-services这一项必须写mapreduce_shuffle因为 MapReduce 的 Shuffle 阶段需要 NodeManager 提供辅助服务。漏掉这个配置任务会卡在 SUBMITTED 或 ACCEPTED 状态日志里会报关于 shuffle 的错误。yarn.nodemanager.resource.memory-mb是 NodeManager 最多能用多少内存给容器。如果机器内存只有 4G设置太高容易导致操作系统内存不足NodeManager 直接被系统杀掉。我试过的经验值是 2048也就是每个节点分配给 YARN 的内存为 2G留一部分给系统和 HDFS 进程。4.6 mapred-site.xml 和 workers 文件mapred-site.xml需要指定 MapReduce 运行在 YARN 上configuration property namemapreduce.framework.name/name valueyarn/value /property /configuration然后是workers文件Hadoop 3.x 叫这个名2.x 叫slaves。它告诉 Hadoop 哪些节点是 DataNode / NodeManager。内容就是每行一个主机名worker1 worker2注意不要写localhost。如果你把 localhost 写进去master 会把自己也当 DataNode 用而集群结构就乱掉了。5. 首次启动流程与 NameNode 格式化这里的坑最密集5.1 为什么必须格式化 NameNode以及格式化时发生了什么Hadoop 集群启动前必须执行一次hdfs namenode -format。你可以把它理解成初始化一盘新的磁带NameNode 需要在本地磁盘上建立一套元数据的目录结构之后才能接受客户端的写入请求。这个操作只需要做一次。如果提前配好了所有配置文件直接执行hdfs namenode -format格式化成功的标志是最后几行输出里出现successfully formatted字样。如果中间有 ERROR 或者 WARN就得回头检查数据目录的权限和磁盘空间。这里有一个特别坑的点很多人在第一次启动失败之后为了“修复问题”再次执行格式化。这样做的问题很大格式化会重新生成一个 clusterID。同时你的 DataNode 节点上原有的数据目录里还保留着第一次格式化时写入的 clusterID。启动的时候 DataNode 发现自己的 clusterID 和 NameNode 的不一致会直接拒绝加入集群现象就是 DataNode 进程起来了但 Web UI 上还是看不到活跃节点。如果你真的需要重新格式化正确的操作步骤是先把所有节点上dfs.datanode.data.dir和dfs.namenode.name.dir指到的目录都清空然后再重新执行格式化。只清空一台是不行的。5.2 启动顺序先 HDFS 再 YARN每一步留意输出启动顺序是有讲究的。一般先启动 HDFS再启动 YARNstart-dfs.sh start-yarn.shstart-dfs.sh在 master 上执行后会根据workers文件的内容通过 SSH 到各台 worker 上启动 DataNode。观察脚本的执行输出很重要它会打印每一台机器上进程的启动结果比如Starting namenodes on [master]、Starting datanodes on [worker1 worker2]。如果哪台机器没出现基本就是 SSH 免密没配好回第三章排查。启动完 YARN 之后全集群的进程应该长这样节点应该出现的进程masterNameNode、SecondaryNameNode、ResourceManagerworker1DataNode、NodeManagerworker2DataNode、NodeManager用jps命令查看这是一个 JDK 自带的工具能列出当前用户启动的 Java 进程。比如在 master 上执行jps输出里应该包含NameNode、SecondaryNameNode、ResourceManager三个进程。缺哪个就排查哪个日志写在 Hadoop 安装目录的logs/文件夹下。5.3 Web UI 验证集群确实活了命令行看到进程还不够我习惯去浏览器里看一眼。在本地访问http://master的公网IP:9870如果能看到 HDFS 的统计页面并且显示两个存活的 DataNodeHDFS 就稳了。再访问http://master的公网IP:8088能看到 YARN 的调度页面ResourceManager 的状态是 ACTIVE说明计算框架也起来了。如果打不开页面优先检查安全组是否放行对应端口其次检查防火墙。CentOS 7 默认用的是 firewalld临时测试可以直接停掉systemctl stop firewalld systemctl disable firewalld虽然生产环境不建议这么干但学习阶段这是最快定位问题的方式。等 Web UI 能打开之后再考虑回头把防火墙规则收敛起来。5.4 进程起了但节点不活跃的典型排查链路我在这里列举一个真实的踩坑过程。某次我启动集群后master 上的 jps 输出正常但 9870 页面显示 DataNode 数量是 0。当时的排查链路是这样的先到 worker1 上看 DataNode 日志发现里面有Incompatible clusterIDs字样。这立刻让我想到了之前的手动格式化。我查了/data/hadoop/namenode/current/VERSION文件里的 clusterID再对比 worker 上/data/hadoop/datanode/current/VERSION里的 clusterID确实不一样。于是我在两个 worker 上删除了 datanode 目录下的内容重新启动 DataNode问题解决。后来我想通了一点这种 clusterID 不匹配的问题只会出现在你对 NameNode 做了二次格式化之后。如果从头到尾只格式化一次根本不会遇到。所以遇到 DataNode 一直连不上时不要急着去改配置文件先看日志看 clusterID 是否一致再看网络是否能互相连通最后再动配置。6. 用自带的 WordCount 验证整条链路真的打通了6.1 准备测试数据并上传到 HDFS集群启动只是第一步能跑任务才算真的搭好了。Hadoop 安装包里自带一个hadoop-mapreduce-examples-*.jar里面包含 WordCount、Pi 等经典示例。我们可以拿来直接验证。先在任意节点上生成几个测试文本文件mkdir /tmp/input echo hello hadoop hello world /tmp/input/file1.txt echo hadoop is powerful /tmp/input/file2.txt然后在 HDFS 上创建输入目录把文件传进去hdfs dfs -mkdir -p /test/input hdfs dfs -put /tmp/input/*.txt /test/input hdfs dfs -ls /test/input注意hdfs dfs命令操作的是 HDFS 上的路径不是本地路径。本地路径用file:///前缀或者不加前缀这个细节有时候会让新手困惑。6.2 执行 WordCount 示例任务上传完毕后执行 MR 任务hadoop jar /usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar wordcount /test/input /test/output命令最后一个是输出目录这个目录不能提前存在否则任务会报Output directory hdfs://master:9000/test/output already exists。跑完之后用hdfs dfs -cat /test/output/part-r-00000查看结果能看到每个单词出现的次数。看到hello 2、hadoop 2这样的输出时说明 HDFS 存储、YARN 调度、MapReduce 计算这三条链路全部打通了。6.3 任务卡住或失败时的判断思路如果任务提交后一直卡在 ACCEPTED 或 RUNNING 状态最常见的两个原因一个是内存资源不够。YARN 给每个任务分配内存如果你的 NodeManager 只有 2G 可用同时跑多个 Map 任务时内存不够用任务就会一直排队。解决办法是在yarn-site.xml里降低yarn.scheduler.maximum-allocation-mb或者把示例数据调小一点。另一个原因是/test/output目录已经存在。MR 任务不允许输出目录预先存在这是一个很容易忽视的规则。删除已存在的输出目录用hdfs dfs -rm -r /test/output。还有一个很经典的现象任务到了map 100% reduce 0%就不动了这是因为你的输入文件太小只有一两个 Map 任务Reduce 任务又默认只有一个等它拉取 Shuffle 数据就好不一定真的是卡死。耐心等一会儿或者把输入文件弄大一点现象自然消失。7. 测试收尾别忘了算清云上资源的账单7.1 停止集群的正确操作测试完成之后大多数人会直接关云主机控制台关机但这个习惯在云环境里是要花钱交学费的。首先要先在集群里优雅停止服务stop-yarn.sh stop-dfs.sh这两条命令会通知所有节点保存状态并退出进程比直接关机安全得多。也可以执行stop-all.sh一条命令完成以上两步。如果你还想把 HDFS 上的测试结果下载到本地在停止服务之前执行hdfs dfs -get /test/output /tmp/local-output这是把 HDFS 文件拿到本地文件系统的常用方式忘了这一步关了集群之后就只能重新启动再取了。7.2 释放实例和防止账单飞起来的经验云主机测试完之后最正确的方式是先停止集群服务然后到云厂商控制台把三台实例“释放”掉。注意释放和关机是两个完全不同的概念。关机之后云盘还占着存储费用照收释放才是把机器彻底删掉只留下快照如果你想保留。我自己的经验是给按量付费的实例设置一个“定时释放”时间是很好的习惯。很多云厂商控制台都支持按量付费实例设置自动释放时间比如设为测试结束当晚的某个时间点。这样做的好处是不会因为临时有事忘了释放下个月一看账单多了几十上百块。如果以后还想继续实验释放之前可以给/data/hadoop目录打一个快照下次创建机器之后直接挂载回去集群就能恢复。这比每次从零搭建快得多。7.3 一个可以把搭建过程自动化的扩展思路说到恢复顺便提一个进阶玩法这套手动搭建流程熟练之后完全可以写成一个 Shell 脚本或者 Ansible 剧本。把 JDK 安装、Hadoop 解压、配置文件填写、SSH 密钥分发都固化成脚本后续再需要集群的时候只需要在控制台创建三台机器、填一下 IP 和主机名就能一键拉起整个集群。我第一次这样自动化时大概花了半天时间写脚本之后每次做实验省下来的时间远超这半天。如果你未来可能会多次使用 Hadoop 集群比如课程设计的多个项目阶段非常建议花点时间走上自动化的路。说到底在云主机上搭 Hadoop 集群的核心并不在于记住几条命令而在于理解清楚每个环节为什么这样做。安全组为什么放行这些端口、配置文件为什么填这些 IP、格式化为什么只能做一次、为什么节点间要用内网地址——把这些搞明白了以后不管是换版本还是换发行版你都能快速迁移这套思路。踩过一次 clusterID 不一致的坑、看过一次 ResourceManager 起不来的日志之后你对这套系统的理解就上了台阶。动手去搭吧有问题就回来看对应的章节剩下的交给时间。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑