很多朋友一上来就想直接搭一个真正的多节点Hadoop集群觉得单机版的伪分布式跑起来不够带劲。这个想法没错但在动手之前我强烈建议你先理清楚自己到底要解决什么问题是单纯学习组件之间的协作关系还是要跑中等规模的数据处理任务又或者是给生产环境做预演这三者的规划思路完全不一样。今天这篇文章就围绕CentOS7搭建Hadoop集群这个主题给你一套从零到能跑通的完整操作记录包括硬件选型、系统初始化、配置文件逐行拆解、启动验证、常见坑位排查全程都是可以直接照做的内容。这篇内容适合三类人第一次搭集群、对配置文件理解得模棱两可的初学者准备从伪分布式迁移到多节点、想搞清楚规划要点的人以及从业一段时间但都是靠脚本一键部署、没手写过配置细节的工程师。我不会把每个概念都从二进制开始讲但会把关键的“为什么”讲清楚让你照着搭完之后遇到问题知道往哪个方向查。1. 搭建前的思考三台机器怎么规划最省心1.1 先想清楚你真的需要多节点集群吗很多人搭集群是奔着“分布式”这三个字去的但分布式不等于机器多。如果你只是学习HDFS的写入流程、MapReduce的执行机制伪分布式模式完全够用配置还少。真正推动你上多节点的场景一般是数据量超过单机磁盘承载能力、需要模拟多节点容错、或者要给后续的高可用升级做实验。CentOS7虽然官方已经停止维护了但存量环境基数很大网上教程和经验贴也最多很多公司的内部平台至今还在用它。选它做Hadoop集群的实验系统遇到问题基本都能搜到解决方案。Hadoop版本方面我建议直接用3.3.x2.x虽然资料丰富但已经在很多方面落后了比如ResourceManager的Rest API、NameNode的联邦机制、默认端口都不同学旧版本性价比不高。硬件上别用一台8G内存的笔记本硬开三台虚拟机跑起来会很痛苦。我之前的模拟项目X用的是三台物理服务器每台16G内存、4核CPU、1TB磁盘配置不算高但跑3节点集群加测试任务绰绰有余。如果你只有一台高配机器用虚拟机也行但每台建议至少给4G内存、2核CPU不然Yarn的NodeManager起个Container都费劲。1.2 节点角色划分与网络、端口规划经典的三节点布局是一台跑NameNode和ResourceManager另外两台跑DataNode和NodeManager。虽然你也可以把ResourceManager和NameNode拆到两台机器上但对三节点集群来说合在一起更符合资源利用率的平衡。规划表如下节点名角色建议配置磁盘要求node101NameNode、ResourceManager16G内存、4核系统盘 元数据盘node102DataNode、NodeManager16G内存、4核数据盘尽量大node103DataNode、NodeManager16G内存、4核数据盘尽量大节点名这个事别看它简单坑却不少。主机名不要用带下划线或特殊字符的名字尽量用node101这种纯字母加数字的形式。三个节点的/etc/hosts里都要写全所有节点的映射包括本机。很多奇怪的“DataNode起不来”问题查到最后都是hosts漏写了一行。端口规划也要心里有数。Hadoop 3.x的默认端口和2.x差别很大比如NameNode的Web UI从50070变成了9870SecondaryNameNode的50090变成了9868。以下是常用端口速查表端口用途9000NameNode RPCfs.defaultFS9870NameNode Web UI9864DataNode Web UI8020NameNode RPC的备选端口有的配置里会出现8088ResourceManager Web UI8030/8031/8032Yarn内部通信端口19888JobHistory Server Web UI端口冲突这个问题在CentOS7上最常见的是9000被其他进程占用。配置之前可以先执行netstat -tlnp看看免得后面启动时一脸懵。2. 基础环境CentOS7系统细节决定成败2.1 系统初始化与网络、时间同步操作系统安装就不展开说了记得选最小化安装省资源。装完第一件事是改主机名和hosts然后关闭两个捣乱的东西SELinux和firewalld。我知道有人会跳出来说生产环境不能关防火墙这话没错但集群实验环境里开着firewalld只会给你增加莫名其妙的问题——端口明明监听了从别的节点就是访问不了。如果是真实生产环境正确做法是放行指定端口而不是简单关闭我这里是为了让你少踩坑实验阶段先关掉。# 关闭SELinux sed -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config setenforce 0 # 关闭防火墙 systemctl stop firewalld systemctl disable firewalld时间同步这个事情容易被忽略但HDFS的租约机制和Kerberos认证都对时间敏感。三台机器时间差超过几十秒后续做高可用或者开启安全认证时会遇到诡异问题。用chrony做时间同步yum install -y chrony systemctl start chronyd systemctl enable chronyd chronyc sources -v # 验证同步状态如果你是在内网环境没有外网NTP服务器可以指定一台机器做时间源其他机器指向它。这个细节在生产环境里比什么都重要因为内网机器时间漂移会直接影响HDFS的写入操作。2.2 JDK安装与环境变量配置Hadoop 3.3.x要求JDK 8我推荐直接用OpenJDK的devel版本因为源码包编译时需要完整的JDK环境而不仅仅是JRE。yum安装最省事yum install -y java-1.8.0-openjdk-devel java -version安装完成后找到Java的实际安装路径。有人习惯用which java找但那个是软链接最后会指到jvm目录下的具体版本目录。我建议直接在/etc/profile里写环境变量export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk export PATH$PATH:$JAVA_HOME/bin然后source /etc/profile执行echo $JAVA_HOME验证。这里要提醒一个细节后面的hadoop-env.sh里也会需要设置JAVA_HOME。虽然Hadoop启动脚本默认会从系统环境变量里读但有时候因为登录用户不同环境变量没传到所以我会在hadoop-env.sh里再写死一次路径双保险。很多奇怪的环境问题都是这里差一步。同样的环境变量内容后续在node102和node103上也要配。别嫌烦这是集群环境的基本功。3. Hadoop安装与核心配置3.1 下载解压与目录规划统一规划目录我习惯把所有软件放在/opt/module下数据放在/opt/data下日志由Hadoop自己管理在安装目录的logs里。你也可以用/usr/local/hadoop只要三台机器保持一致就行。Hadoop官网下载hadoop-3.3.6.tar.gz传到node101后解压tar -zxvf hadoop-3.3.6.tar.gz -C /opt/module mv /opt/module/hadoop-3.3.6 /opt/module/hadoop mkdir -p /opt/data/hdfs/name /opt/data/hdfs/data chown -R 你的用户:你的用户 /opt/module/hadoop /opt/data创建专用用户这一步演示环境可以用当前用户直接跑但建议还是建一个hduser避免直接用root跑Hadoop。Hadoop官方文档其实不建议用root运行有些脚本在root下行为会不一样。我之前的模拟项目里就是用hduser跑的后面文件权限问题少了很多。Hadoop解压后先不改任何配置直接启动试试你会发现在本机能跑起来但跨节点就是连不上。这很正常因为默认配置绑定的是localhost。下面这些文件才是重头戏。3.2 配置文件逐个拆解每个参数为什么这么设Hadoop的配置集中在etc/hadoop/目录下核心就这几个hadoop-env.sh、core-site.xml、hdfs-site.xml、yarn-site.xml、mapred-site.xml再加一个workers文件。别死记硬背理解每个参数解决什么问题的同时你自己就会配了。先改hadoop-env.sh文件里有JAVA_HOME字段把它指向JDK真实路径export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk接着是core-site.xml这是全局核心配置。最关键是fs.defaultFS它决定了整个集群的“入口”地址configuration property namefs.defaultFS/name valuehdfs://node101:9000/value /property property namehadoop.tmp.dir/name value/opt/data/hdfs/tmp/value /property /configurationhadoop.tmp.dir如果不想显式设置Hadoop会用默认的/tmp目录。我劝你千万别默认因为Linux会定期清理/tmp到时候NameNode的元数据丢了哭都来不及。设置成自己的数据目录后面格式化时元数据就会写到这个路径下。然后是hdfs-site.xml重点配置NameNode的元数据存储目录、DataNode的数据块存储目录和副本数。生产环境里dfs.replication一般设2或3实验环境设2就行节省磁盘configuration property namedfs.namenode.name.dir/name value/opt/data/hdfs/name/value /property property namedfs.datanode.data.dir/name value/opt/data/hdfs/data/value /property property namedfs.replication/name value2/value /property property namedfs.permissions.enabled/name valuefalse/value /property /configuration最后一个权限参数我在实验环境会关掉不然你创建一个目录后别的用户读不了测试阶段还要折腾chown和chmod。生产环境不要学我这个权限控制是必须的这里只是让初学阶段少一个变量干扰。yarn-site.xml决定资源调度。ResourceManager跑在node101上NodeManager跑在各节点上。关键是把资源相关参数根据实际内存调整好否则默认值会按8G内存起Container小机器直接跑崩configuration property nameyarn.resourcemanager.hostname/name valuenode101/value /property property nameyarn.nodemanager.resource.memory-mb/name value8192/value /property property nameyarn.scheduler.maximum-allocation-mb/name value8192/name /property /configuration资源参数的值要按照机器实际内存调整。16G内存的机器NodeManager分配8G比较稳妥剩下的留给系统和其他进程。如果你开了很多别的服务这个值要再降。mapred-site.xml在Hadoop 3.x中默认不存在文件需要从模板复制cp etc/hadoop/mapred-site.xml.template etc/hadoop/mapred-site.xmlMapReduce程序跑在Yarn之上所以配置MR框架为yarn即可configuration property namemapreduce.framework.name/name valueyarn/value /property /configuration最后是workers文件。在Hadoop 3.x里还不叫slaves叫workers这个文件列出所有DataNode和NodeManager的主机名。一行一个node101 node102 node1033.3 配置同步到其他节点node101上所有配置都改完后要把整个Hadoop目录同步到node102、node103。不要只同步配置文件因为Hadoop二进制文件也要一致除非你每个节点都单独下载解压一遍。用rsync是最高效的rsync -av /opt/module/hadoop/ hdusernode102:/opt/module/hadoop/ rsync -av /opt/module/hadoop/ hdusernode103:/opt/module/hadoop/环境变量也要同步/etc/profile里加的那几行在node102和node103上同样加上。这一步完成后在三个节点分别执行hadoop version输出一致就说明同步没问题。4. 启动集群与验证4.1 格式化NameNode与正确的启动顺序启动前最关键的一步是格式化NameNode。这个概念很多教程一句带过但我要说清楚格式化会在dfs.namenode.name.dir指定的目录里初始化元数据结构和Block池标识相当于给文件系统“开荒”。只有首次启动时才需要格式化后续每次启动都不需要。格式化命令在node101执行hdfs namenode -format执行的时候注意输出里有没有“successfully formatted”字样。如果有“already formatted”的提示说明你之前格式化过了如果非要重新格式化就得先想清楚格式化会清空NameNode的元数据如果DataNode上已经有数据块格式化后clusterID不一致DataNode根本注册不上来。这是后续排障里最折磨人的问题后面第5节详细讲。启动顺序也有讲究先启HDFS再启Yarn。你可以分开执行start-dfs.sh start-yarn.sh也可以直接执行start-all.sh效果一样。启动完成后在三个节点分别执行jps观察Java进程是否齐全。以下是正常情况下的输出形状node101上应有NameNode、ResourceManagernode102/node103上应有DataNode、NodeManagerjps输出的进程名有时会带进程号格式类似“12345 NameNode”。少一个进程都要查原因。4.2 网页验证和HDFS冒烟测试进程起来了不等于集群可用。打开浏览器访问http://node101:9870能看到NameNode的Web界面里面会显示Live Nodes数量。正常是三台机器都在线如果只有一台问题基本都是hosts或者防火墙。再访问http://node101:8088这里是ResourceManager的界面能看到集群总内存、核数、Active Nodes数量。Yarn界面的Node Manager列表里三台都在才算完整。Web界面只能说明服务存活着真正的读写测试才是最关键的。在node101上执行下面的命令hdfs dfs -mkdir -p /test/input hdfs dfs -put /opt/module/hadoop/README.txt /test/input/ hdfs dfs -cat /test/input/README.txt | head写入成功后回到NameNode的Web界面找到“Utilities Browse the file system”进到/test/input目录你会看到README.txt确实已经存在还能看到DataNode上Block的分布情况。看到这里你的三节点集群才算真正能用了。一个容易被忽略的验证动作是检查数据块的副本分布。执行hdfs fsck /test/input -files -blocks -replicas你会看到每个Block被复制到了哪些节点。这个命令也是以后排查数据健康度的重要工具可以提前养成习惯。5. 常见问题与排查实录5.1 网络、主机名和防火墙问题集群搭建里最无厘头的错误多半出在网络层。我见过太多“DataNode起不来”“Web页面打不开”的案例最后查出来都是hosts里少写一行、主机名带下划线、或者防火墙没关干净。典型症状是NameNode的Web界面里Live Nodes显示数量不足或者DataNode进程启动了但几十秒后自己退出去。这个时候先别急着看日志按顺序检查三件事第一三个节点互相ping主机名通不通第二telnet node101 9000能不能通第三防火墙状态是不是真的关闭了。再补一个细节如果你改过/etc/hostsMaster节点用旧IP启动了重启后连不上集群。先检查/etc/hosts里有没有残留的旧IP映射坑得很。另外主机名里不要有下划线很多服务对主机名有特殊解析宁可多敲两个字也别用花哨名字。5.2 重复格式化导致的clusterID不一致这个坑我栽过一次后来发现群里的朋友也经常遇到。现象是你格式化NameNode后启动集群DataNode全部正常启动但过一会儿都变成dead或者日志里报“Incompatible clusterIDs”之类的错误。原因是格式化只清了NameNode的元数据目录DataNode的data目录里的VERSION文件还保留着旧clusterID。两边对不上DataNode自然无法注册。解决办法说穿了很简单把每个节点的/data目录全部清空然后重新格式化一遍。步骤是# 在三个节点都执行 rm -rf /opt/data/hdfs/name/* /opt/data/hdfs/data/* /opt/data/hdfs/tmp/* # 回到node101重新格式化 hdfs namenode -format格式化是小事但要知道为什么删。如果你格式化后不清DataNode数据这个报错会无数次重复所以我把“格式化前必清DataNode目录”写进了自己的操作清单里。5.3 容器超内存和虚拟内存检查跑MapReduce任务时经常遇到类似这样的报错Container [pidxxxx] is running beyond virtual memory limits. Killing container.这个报错的原因在于Yarn默认启用了虚拟内存检查它认为容器使用的虚拟内存超过限制就把容器杀了。实验环境里直接关闭这个检查是最快的解决办法property nameyarn.nodemanager.vmem-check-enabled/name valuefalse/value /property但真正的问题在于内存规划不合理。如果你给NodeManager只分配了4G给mapreduce.map.memory.mb设了1G给reduce设了2G排队的任务一多物理内存就不够用。更合理的做法是重新算一遍资源参数确保yarn.nodemanager.resource.memory-mb ≤ 物理内存的70%mapreduce.map.memory.mb和mapreduce.reduce.memory.mb之和远小于NodeManager总内存每个map/reduce任务的虚拟内存上限mapreduce.map.java.opts不要设得太大还有一种常见提示是“Unable to load native-hadoop library”这个虽然带着ERROR字样但真不是致命问题只是告诉你libhadoop.so用不了会对性能有影响但功能正常。想彻底解决就得装FUSE或者编译native库实验环境实在没时间可以跳过。5.4 日常运维的几个实用习惯集群跑起来容易稳定运行很难。我自己维护集群时养成了几个习惯现在分享出来能帮你省掉不少半夜被叫醒的时间。第一日志是最好的排障入口。Hadoop把日志放在HADOOP_HOME/logs/目录下每个进程一个日志文件。DataNode起不来就看hadoop-hduser-datanode-node102.logResourceManager有问题就看yarn-hduser-resourcemanager-node101.log。别去猜直接tail日志文件比任何教程都准。第二常驻一条巡检命令。进程有没有掉数据节点健康度怎么样一句话就能查hdfs dfsadmin -report这个命令能看到每个DataNode的容量、剩余空间和是否正常。配合jps一起用日常巡检一分钟搞定。第三启动关停脚本化。写一个简单的shell脚本把启动和关闭命令封装起来后续每天用都省心#!/bin/bash case $1 in start) start-dfs.sh start-yarn.sh ;; stop) stop-yarn.sh stop-dfs.sh ;; esac脚本里还可以加一步ssh到各节点检查进程状态的逻辑但初版这样已经够了。先把集群跑顺再慢慢完善运维工具。我个人实际操作下来最深的一点体会是从来没有“玄学故障”只有还没找到原因的故障。集群搭不起来的时候忘掉你的猜测按网络、环境变量、日志、数据目录这条线去查90%的问题都能解决。上面列的这些坑都是真实踩过、也帮别人排查过的如果你的环境和我的有些差异配置文件和日志信息是最不会骗你的那个老师傅。集群搭完只是起点后面加HA、调参数、做基准测试才是真正长经验的地方。