ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Hadoop平台搭建全指南:从伪分布式到集群高可用实战

Hadoop平台搭建全指南:从伪分布式到集群高可用实战 你有没有遇到过这种情况网上搜“Hadoop平台搭建”教程铺天盖地照着某一篇一步一步做眼看jps输出里NameNode、DataNode都在了浏览器却死活打不开管理界面换一篇重试又卡在YARN起不来的地方。更让人崩溃的是不同教程给的配置写法还不一样有的让你改core-site.xml有的让你动hdfs-site.xml最后你也不知道自己到底错在哪。我最早搭Hadoop也是这样过来的。后来带着团队做过好几套环境从伪分布式学习环境到多节点集群再到配合Zookeeper做高可用踩过的坑攒了一堆。这篇就把Hadoop平台搭建这件事从头到尾捋一遍重点不在“照着敲命令”而在搞清楚每一步为什么这么做、哪些地方容易埋雷、出了问题该怎么查。文章会按照“部署形态选型 → 环境准备 → 伪分布式搭建 → 横向扩展为集群 → Zookeeper整合 → 线上故障排查”这条主线展开。无论你是在自己笔记本上搭一个学习环境还是准备给团队搭一套多节点集群这篇都能给你一套可以落地的思路。1. 先搞明白三种部署形态再动手不迟很多人一上来就搜“Hadoop集群搭建”结果跟着教程跑了半天发现自己搭的根本不是集群而是伪分布式。这其实不怪你市面上的教程标题乱得很内容经常混着发。所以在动手前先用几分钟搞清楚Hadoop的三种部署形态这会决定你后面每一步的配置方式。1.1 单机版、伪分布式、全分布式的本质区别Hadoop的部署形态可以简单分成三种形态进程分布使用场景配置复杂度单机版本地模式不使用HDFS直接在本地文件系统跑MapReduce验证API、调试Mapper/Reducer逻辑最低几乎不用配置伪分布式所有守护进程NameNode、DataNode、ResourceManager等都跑在同一台机器上学习HDFS原理、开发调试、跑通完整流程中等全分布式集群不同进程分布在不同机器上生产环境、接近真实的测试环境较高单机版严格来说不算“平台搭建”它只是把Hadoop解压好能让你用hadoop jar去跑一个本地模式的MapReduce作业。数据不经过HDFS分布式文件系统的特性一个都体验不到。所以如果你是想学习Hadoop体系至少要从伪分布式开始。伪分布式的“伪”字很传神——它在一台机器上同时启动所有角色进程模拟出一个最小的分布式环境。你在这套环境里能体验到完整的HDFS读写流程、YARN的资源调度、MapReduce作业提交全过程但性能和真实集群没法比。全分布式才是真正意义上的“平台”一般建议至少3台机器起步1台Master 2台Worker。Master上跑NameNode和ResourceManagerWorker上跑DataNode和NodeManager。1.2 为什么伪分布式是绝大多数人的最佳起点从热搜词就能看出来“hadoop伪分布式搭建”“hadoop开发环境搭建”是搜索量最大的方向这说明大多数人的真实需求是“先有一套能用的开发学习环境”。我个人的建议路径是伪分布式单机→ 多节点集群 → 高可用配合Zookeeper。别一上来就搭HA那玩意儿涉及JournalNode、ZKFC、Zookeeper集群任何一个环节出错都很难排查基础不牢的话会被打击到怀疑人生。伪分布式的另一个好处是它和全分布式在配置层面几乎完全一致。你把伪分布式搭好了后面扩展为集群只是改几个配置项、加几个worker节点的事。这也是为什么我建议把伪分布式的每一步都吃透——它其实是一套浓缩版的集群。1.3 根据你的硬件条件选择路线伪分布式虽然只是单机但不是随便什么配置都能跑。Hadoop启动后NameNode、DataNode、ResourceManager、NodeManager四个Java进程加起来内存轻松吃掉4~6G。我用2G内存的虚拟机试过启动后频繁触发OOM进程直接消失jps啥都查不到。给你一个参考标准内存4G以下的机器建议先装单机版或者把HDFS的副本数设为1关掉SecondaryNameNode尽量减少常驻进程。内存8G的机器跑伪分布式没问题但别同时开太多其他应用。内存16G以上的机器或服务器可以放心跑多节点集群方案也可以开HA。另外强烈建议用Linux系统来搭CentOS 7、Ubuntu 20.04/22.04都可以。Windows上虽然也有Hadoop的二进制包但坑多得离谱很多底层脚本在Windows上跑不起来非要用Windows的话还得装Cygwin或者WSL纯粹给自己找不痛快。2. 环境准备里的细节每一条都可能让你白忙一场正式下配置文件之前环境准备阶段有四个高频踩坑点JDK版本不匹配、SSH免密没配好、主机名解析不对、防火墙没关。这四件事看似基础但实际上90%的“启动失败”“连接不上”都和它们有关。2.1 JDK与Hadoop版本兼容性不是越新越好Hadoop 3.x系列官方要求JDK 8或者JDK 11。但这个“支持”是有讲究的——Hadoop 3.3以前用JDK 11还是有不少兼容性问题Hadoop 3.3之后JDK 11才能算“体验良好”。我自己常用的搭配是Hadoop 3.3.x JDK 1.8Oracle JDK或OpenJDK都行Hadoop 3.4.x JDK 11不管装哪个版本装好之后第一件事是验证java -version确认PATH里面指向的是你装的那个JDK。很多人机子上自带OpenJDK 17Hadoop跑起来会报一堆奇怪的类加载错误最后排查到JDK版本不兼容白白浪费几个小时。2.2 SSH免密登录伪分布式也要配有人觉得“我就一台机器配什么SSH免密”这个想法会坑了你。Hadoop的start-dfs.sh和start-yarn.sh脚本是通过SSH去各台机器上启动守护进程的即使是本机脚本也会走一遍SSH。如果没配免密启动过程中会反复提示输入密码而且输入了也不一定能顺利启动因为脚本在批量执行时会卡在密码提示符上。配置步骤很简单三步# 1. 生成密钥对一路回车就行 ssh-keygen -t rsa -P -f ~/.ssh/id_rsa # 2. 将公钥加入authorized_keys本机免密 cat ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys # 3. 验证 ssh localhost hostname第三步执行后如果直接输出主机名而不要求输密码就说明配好了。注意chmod 600那一步别省SSH对authorized_keys的权限非常敏感权限太开放会直接拒绝使用这个文件。2.3 主机名与IP映射最容易忽略的定时炸弹Hadoop集群内部是通过主机名互相访问的不是IP。所以如果你没配置好/etc/hosts或者主机名和IP对不上启动时经常报“UnknownHostException”或者连接超时。在/etc/hosts里加上所有相关节点包括本机192.168.1.100 hadoop-master 192.168.1.101 hadoop-worker1 192.168.1.102 hadoop-worker2同时用hostnamectl set-hostname改好每台机器的主机名。注意改完主机名之后要重新登录一次否则当前会话里的hostname还是旧的启动脚本照样懵。2.4 防火墙与SELinux先关掉再讲别的防火墙拦截的是端口Hadoop涉及一堆端口最简单粗暴的方式是搭建阶段直接关掉防火墙。内网搭建环境不涉及安全风险先把功能跑通再说安全加固的事。# CentOS 7/8 systemctl stop firewalld systemctl disable firewalld # Ubuntu ufw disableSELinux也建议先临时禁用setenforce 0永久禁用需要改/etc/selinux/config把SELINUXenforcing改成SELINUXdisabled。注意SELinux的坑很隐蔽——它不会让进程直接消失而是“看起来一切正常但就是访问不了某些文件”排查起来极其痛苦。3. 伪分布式搭建的完整过程与参数选择逻辑前面那些环境问题解决之后正式开始搭伪分布式。整个流程大约半小时但每一步都值得搞清楚为什么。3.1 下载、解压、目录规划Hadoop官网下载二进制包是第一步。国内从官网下载速度不稳定用清华镜像或阿里云镜像会快得多。这个在热搜词里也有人遇到了直接说结论镜像站的文件和官网是同步的校验一下SHA256没问题就可以用。wget https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz tar -zxvf hadoop-3.3.6.tar.gz -C /opt/ mv /opt/hadoop-3.3.6 /opt/hadoop目录规划上我习惯把Hadoop安装在/opt/hadoop数据目录单独放在/data/hadoop下面不要和安装目录混在一起。原因很简单后面做升级或者重装的时候直接替换安装目录就行数据不用动。创建目录并赋权mkdir -p /data/hadoop/{namenode,datanode,tmp} chown -R $USER:$USER /opt/hadoop /data/hadoop3.2 环境变量配置编辑/etc/profile.d/hadoop.sh统一管理Hadoop相关环境变量比直接改/etc/profile更干净export HADOOP_HOME/opt/hadoop export PATH$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin export HADOOP_CONF_DIR$HADOOP_HOME/etc/hadoop export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64JAVA_HOME一定要写实际路径不要写export JAVA_HOME$(dirname $(dirname $(readlink -f $(which java)))这种花活等你在某个极端场景下发现Hadoop脚本读不到JAVA_HOME时就知道直接写死路径有多省心了。3.3 核心配置文件逐个拆解Hadoop的配置分散在etc/hadoop下的几个XML文件里。伪分布式要改的就四个core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml。core-site.xml设置默认文件系统为HDFS同时指定临时目录。configuration property namefs.defaultFS/name valuehdfs://localhost:9000/value /property property namehadoop.tmp.dir/name value/data/hadoop/tmp/value /property /configurationfs.defaultFS指定了HDFS的NameNode地址和RPC端口。Hadoop 3.x默认RPC端口是9000NameNode的web UI端口是9870。注意Hadoop 2.x的UI端口是500703.x改成了9870网上大量老教程还在写50070照着做的话浏览器打开端口就不对。hdfs-site.xml设置副本数和NameNode/DataNode的数据目录。configuration property namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name valuefile:///data/hadoop/namenode/value /property property namedfs.datanode.data.dir/name valuefile:///data/hadoop/datanode/value /property /configuration伪分布式下副本数只能设为1。如果你硬要设3不是报错而是DataNode会不停尝试复制副本到其他节点然后发现根本没有其他节点日志里的警告能刷屏。这个我在第一次搭的时候也犯过以为副本数越大越安全结果给自己埋了个性能坑。mapred-site.xmlMapReduce运行在YARN之上。configuration property namemapreduce.framework.name/name valueyarn/value /property /configuration这个配置的意义是告诉MapReduce作业用YARN来做资源调度而不是本地跑。不少人在这一步漏配结果作业是能跑但提交到YARN界面里看不到任何任务资源管理形同虚设。yarn-site.xml配置YARN的辅助服务。configuration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property /configurationaux-services这个参数是YARN中比较容易忽略但极其关键的一项。NodeManager通过这个配置知道要为MapReduce作业提供shuffle服务如果漏配或者值不对MapReduce作业会卡在RUNNING状态日志里报的是“Shuffle handler not running”之类的错实际根子在这。3.4 格式化NameNode务必注意时机配置改完后启动HDFS之前必须格式化NameNode。格式化操作会初始化文件系统元数据生成clusterId和存储目录。hdfs namenode -format这里有个关键教训格式化操作只能在首次启动HDFS之前执行之后不要随便再跑。因为每次格式化都会生成一个新的clusterId而DataNode在启动时会把自己数据目录里的clusterId发给NameNode做校验两边对不上就会被拒绝注册。结果就是你重新格式化之后NameNode起来了但所有DataNode都连不上报错日志里全是“Incompatible clusterIDs”之类的字样。如果确实需要重新格式化比如数据都不要了必须把dfs.datanode.data.dir和dfs.namenode.name.dir下面的目录清空再格式化。3.5 启动HDFS和YARN用jps验证进程环境变量文件生效后执行启动命令# 使环境变量生效 source /etc/profile.d/hadoop.sh # 启动HDFS start-dfs.sh # 启动YARN start-yarn.sh启动完成后运行jpsJDK自带的小工具列出当前用户的Java进程正常情况下你应该看到NameNode DataNode SecondaryNameNode ResourceManager NodeManager每个进程一行一个都不能少。少一个就说明对应的组件启动失败了需要去看对应日志。日志位置在$HADOOP_HOME/logs/目录下后续排查问题基本全靠这里。验证Web UI浏览器打开http://localhost:9870HDFS管理界面和http://localhost:8088YARN资源管理界面。看到界面能打开说明伪分布式基本搭建成功。3.6 跑一个WordCount验证全链路搭建完成后跑一个官方的WordCount示例验证整个数据链路# 在HDFS中创建目录 hdfs dfs -mkdir -p /input # 上传本地文件到HDFS echo hello hadoop hello world | hdfs dfs -put - /input/test.txt # 运行官方WordCount示例 hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar wordcount /input /output # 查看结果 hdfs dfs -cat /output/part-r-00000如果你的结果正确输出了每个单词的统计次数那说明HDFS的读写、YARN的资源调度、MapReduce的执行链路全部通了。这一步跑通平台搭建就算成功了一半。4. 从伪分布式迈向真集群需要改动的核心配置伪分布式跑通之后很多人会问“接下来怎么办”。答案是把它扩展成一个真正的多节点集群。好消息是大部分配置都不用动只需要调整少数几个参数。4.1 节点规划Master和Worker的分工以一个经典的一主两从集群为例三台机器分工如下节点角色部署进程hadoop-masterNameNode ResourceManager管理节点负责元数据和资源调度hadoop-worker1DataNode NodeManager存储和计算节点hadoop-worker2DataNode NodeManager存储和计算节点有条件的可以加一台专门的SecondaryNameNode节点Hadoop 3.x里叫Checkpoint Node但小规模集群其实没必要默认放Master上就行。4.2 配置文件要改动的地方把伪分布式那套配置文件同步到所有节点改动如下core-site.xmlfs.defaultFS从hdfs://localhost:9000改成hdfs://hadoop-master:9000指向真正的NameNode主机名。hdfs-site.xml改动dfs.replication的值为2。三节点集群副本数设为2是合理的——既能保证数据可靠性又不会像3副本那样浪费存储空间。workers文件Hadoop 3.x如果用的Hadoop 2.x则叫slaveshadoop-worker1 hadoop-worker2把Master主机名从workers文件里去掉因为你不需要在Master上启动DataNode如果机器资源富余其实也可以加但标准做法是不加。4.3 数据目录的拷贝问题最容易翻车的地方来了DataNode的数据目录不能直接拷贝NameNode格式化后的数据目录。我之前在部署集群时图省事把Master上的/data/hadoop整个打包分发到worker节点结果worker上的DataNode启动后不停尝试连接NameNode但NameNode收到的注册请求全被拒绝。查了很久才发现是worker上残留了NameNode格式化时生成的元数据文件。正确做法是worker节点上只保留datanode目录可以预创建也可以是空的不要包含namenode目录的内容。DataNode第一次启动时会自己格式化并生成clusterId然后向NameNode注册这个流程是自动的。4.4 集群的启动顺序验证集群启动有个基本原则先启动管理节点再启动工作节点。因为DataNode启动后要主动向NameNode注册如果NameNode还没起来DataNode会反复重试虽然最终也会成功但日志里会有一堆连接拒绝的报错容易干扰判断。# 在master上执行 start-dfs.sh start-yarn.shstart-dfs.sh脚本会自动通过SSH登录到workers文件里的节点去启动DataNode所以你只需要在Master上执行一次。启动后分别在每台机器上跑jps确认进程状态Master上应有NameNode、SecondaryNameNode、ResourceManager每个Worker上应有DataNode、NodeManager要顺带练一下启停命令的话stop-dfs.sh和stop-yarn.sh也是对称的在Master上执行即可。4.5 动态添加节点不用重启集群的做法集群跑着跑着机器不够用了想加一台新的worker节点。不需要全集群重启只需要在新机器上完成以下几件事安装JDK和Hadoop同步配置文件和workers文件。确保新机器到Master的SSH免密配好。在Master的workers文件里加上新节点主机名。在新节点手动启动DataNode和NodeManagerhdfs --daemon start datanode yarn --daemon start nodemanager整台新节点加入后可以在NameNode UI9870端口的Datanodes列表里看到它状态变为In Service。这种滚动扩容的方式对线上集群非常友好不会影响正在跑的作业。5. Zookeeper整合HA机制的入场券热搜词里专门有一条“hadoop和zookeeper整合实战”说明很多人在这一环卡过。确实Zookeeper不是Hadoop的必装组件但一旦你追求高可用Zookeeper就绕不过去了。5.1 Zookeeper在Hadoop HA中扮演的角色先想清楚一个问题Hadoop的NameNode是单点如果它挂了整个HDFS就瘫痪了。解决办法是用两台机器组成Active/Standby一台作为活跃节点提供服务另一台作为热备随时接管。这就带来两个问题怎么选主怎么防止脑裂Zookeeper就是来解决这两个问题的。NameNode通过ZKFCZookeeper Failover Controller这个守护进程和Zookeeper交互选主两个ZKFC在ZK中竞争创建一个临时节点谁创建成功谁就是Active另一个自动成为Standby。这个机制类似抢锁极端情况下如果Standby看到锁被持有就不会去抢了。防脑裂Active节点会定期向ZK发送心跳如果ZK长时间收不到心跳会自动删除临时节点并通知Standby接管。同时ZKFC还通过fencing机制确保老Active真正退出比如用sshfence远程杀掉它的进程避免两个节点同时写数据导致脑裂。理解了这两点你就知道为什么HA一定要依赖ZK——没有这个外部协调者两台机器无法协商出“谁是老大”这个基本问题。5.2 Zookeeper集群的安装与配置生产环境下Zookeeper最好是奇数节点3个或5个。在搭建学习环境时你可以在三台Hadoop节点上分别装ZK也可以在一台机器上跑3个ZK实例。我建议直接装3台节点的ZK集群因为这才符合真实场景。下载解压后每台机器上编辑zookeeper/conf/zoo.cfgtickTime2000 initLimit10 syncLimit5 dataDir/data/zookeeper clientPort2181 server.1hadoop-master:2888:3888 server.2hadoop-worker1:2888:3888 server.3hadoop-worker2:2888:3888关键参数含义tickTimeZK的基本时间单位单位毫秒2000即2秒。initLimitFollower启动后能与Leader完成数据同步的最大tick数10个tick即20秒。syncLimitFollower与Leader之间心跳的最大延迟5个tick即10秒。clientPort客户端连接端口默认2181。server.N集群节点列表每个节点用“IP:port1:port2”标识。port1用于Leader间通信port2用于选举通信。然后每台机器在dataDir目录下创建一个myid文件内容是数字编号对应server.N里的Necho 1 /data/zookeeper/myid # hadoop-master上执行 echo 2 /data/zookeeper/myid # hadoop-worker1上执行 echo 3 /data/zookeeper/myid # hadoop-worker2上执行启动顺序没有严格的先后要求依次执行zkServer.sh start即可。用zkServer.sh status查看状态会看到其中一台是leader另外两台是follower。到这里ZK集群就已经准备好了。顺带说一句如果你只是学习HA机制不想搞三台机器官方文档里有一种伪集群模式——在一台机器上起3个ZK进程每个进程用不同端口和不同dataDir。但这个配置比较绕新手容易搞混不推荐。5.3 Hadoop侧为HA增加的重要配置项ZK就绪后回到Hadoop配置层面。相比单NameNode的集群HA方案下hdfs-site.xml和core-site.xml要多出一大截配置。这里挑最重要的几项解释core-site.xmlconfiguration !-- 使用逻辑名称不用具体主机名 -- property namefs.defaultFS/name valuehdfs://mycluster/value /property !-- 配置ZK地址列表 -- property nameha.zookeeper.quorum/name valuehadoop-master:2181,hadoop-worker1:2181,hadoop-worker2:2181/value /property /configurationhdfs-site.xmlconfiguration !-- 启用HA -- property namedfs.nameservices/name valuemycluster/value /property !-- 定义两个NameNode的逻辑名称 -- property namedfs.ha.namenodes.mycluster/name valuenn1,nn2/value /property !-- nn1和nn2的RPC地址分别指向两个NameNode -- property namedfs.namenode.rpc-address.mycluster.nn1/name valuehadoop-master:8020/value /property property namedfs.namenode.rpc-address.mycluster.nn2/name valuehadoop-worker1:8020/value /property !-- 两个NameNode共享的edits日志目录用JournalNode实现 -- property namedfs.namenode.shared.edits.dir/name valueqjournal://hadoop-master:8485;hadoop-worker1:8485;hadoop-worker2:8485/mycluster/value /property !-- 启用自动故障转移 -- property namedfs.ha.automatic-failover.enabled/name valuetrue/value /property /configuration这些配置的精髓在于两个NameNode之间要通过JournalNode共享edits日志任何一条元数据变更Active NameNode都会同时写入JournalNodeStandby NameNode从JournalNode读取并实时应用到自己的内存中这样它才能随时顶上。5.4 整合过程中最容易踩的坑启动顺序HA整合有一个严格的首次启动顺序打乱了就会出各种怪问题。正确顺序是先启动三台机器上的ZookeeperzkServer.sh start每台都执行。在每台机器上启动JournalNodehdfs --daemon start journalnode三台都要。在其中一个NameNode上执行hdfs namenode -format只执行一次。在这台格式化过的NameNode上执行hdfs zkfc -formatZK初始化ZK中的HA状态。启动第一台NameNodehdfs --daemon start namenode。在第二台NameNode上执行hdfs namenode -bootstrapStandby从第一台同步元数据。启动第二台NameNode。最后通过start-dfs.sh把DataNode等其余进程拉起。这个顺序里第6步“bootstrapStandby”特别关键。很多人不知道直接启动第二个NameNode结果它会一直报“No edits file found”之类的错因为它的本地元数据目录是空的根本不知道怎么去同步JournalNode。执行一次bootstrapStandby它会从已格式化的NameNode拉取完整元数据之后才能正常工作。5.5 验证HA是否真的生效配置都做完后怎么验证HA确实生效了推荐两个方法先用hdfs haadmin -getAllServiceState查看两个NameNode的状态正常情况下应该是一个active一个standby。如果两个都是standby说明ZKFC竞争锁失败了多半是ZK状态被污染可以执行hdfs zkfc -formatZK重新初始化。然后做一次故障切换演练直接kill掉Active NameNode的进程生产环境别这么干测试环境可以。等十几秒后再看状态Standby应该自动变为Active整个过程中如果有客户端在读写HDFS会发现短暂中断后自动恢复。这个行为验证了ZK的自动故障转移逻辑是通的。6. 运行期高发问题排查链路平台搭好了运行阶段的问题才是最折磨人的。把遇到的几个高频问题整理一下每一条都是实际排查经历照着这个思路能省很多时间。6.1 案例一java.lang.NoClassDefFoundError: org/apache/hadoop/crypto这个报错在热搜词里出现了大概率是在跑Hive或者Spark作业时遇到的。完整的报错信息类似Exception in thread main java.lang.NoClassDefFoundError: org/apache/hadoop/crypto/CryptoCodec排查链路如下第一步确认是不是Hadoop的native库没加载。Hadoop的$HADOOP_HOME/lib/native目录下有各平台的本地库文件.so文件如果这个目录缺失或平台不匹配CryptoCodec就加载不了。第二步用hadoop checknative命令看一下native库的加载状态。如果输出显示openssl为false或者有Unable to load字样那就是本地库的问题。常见原因是你用的Hadoop包是从Windows或Mac上直接拷到Linux的或者是解压后没有给.so文件可执行权限。第三步检查classpath。执行hadoop classpath确认hadoop-common的jar包路径在输出里。如果classpath不完整手动把$HADOOP_HOME/share/hadoop/common/*加入环境变量export HADOOP_CLASSPATH$HADOOP_HOME/share/hadoop/common/*:$HADOOP_HOME/share/hadoop/common/lib/*:$HADOOP_CLASSPATH还有一种特殊情况机器上装了多个Hadoop版本跑作业时用的是老版本的jar包老版本里没有CryptoCodec这个类。这种就要全局搜一下老的hadoop-common jar把它从应用lib目录里请出去。6.2 案例二DataNode启动不了日志报Incompatible clusterIDs这个在前面格式化部分提过这里展开说说排查链路。典型场景是集群跑了一阵子有人为了“重置环境”又跑了一遍hdfs namenode -format然后DataNode就全挂了。从DataNode的日志文件$HADOOP_HOME/logs/hadoop-hadoop-datanode-xxx.log里能看到类似这样的错误Incompatible clusterIDs in /data/hadoop/datanode: NameNode clusterID CID-xxxx, datanode clusterID CID-yyyy原因是NameNode格式化时生成了新的clusterId但DataNode的数据目录里还保存着旧的clusterId两者不一致DataNode拒绝注册。解决办法有两个开发环境直接清空DataNode的datanode目录然后重启DataNode。它会以新的clusterId重新初始化数据目录但原有数据块全部丢失。线上环境不要清空而是修改DataNode数据目录里的VERSION文件在/data/hadoop/datanode/current/VERSION把clusterId改成和NameNode的一致再重启DataNode。这个操作在紧急恢复场景下很管用能保住大部分数据。这个案例也解释了为什么格式化NameNode要慎重——做好元数据备份再操作否则线上环境可能直接丢数据。6.3 案例三进程都在但Web UI打不开jps显示NameNode、DataNode都在但浏览器打开9870端口就是转圈打不开。排查顺序先看端口有没有真正监听ss -tlnp | grep 9870如果端口没监听说明NameNode进程虽然存在但已僵死去日志里找原因。如果端口在监听那问题出在防火墙或网络层面检查是不是在别的机器上访问的hosts解析是否正确。还有一种特殊情况界面能打开但一直显示“NameNode is in SafeMode”安全模式。HDFS在启动初期会自动进入安全模式此时只读不可写。正常情况下几十秒后自动退出但如果长时间不退出说明数据块丢失严重可以用以下命令观察和强制退出hdfs dfsadmin -safemode get # 查看安全模式状态 hdfs dfsadmin -safemode leave # 强制退出强制退出之前要确认数据块缺失比例别让坏盘上的数据在被读取时报错。hdfs dfsadmin -report可以查看各节点数据块状态和缺失情况。6.4 排查问题的通用方法论先看日志再看状态最后分享一套我自己总结的Hadoop排查方法适用于上面所有案例。遇到问题不要瞎猜按固定链路走第一看进程在不在jps。进程少了一个这个组件就没起来去看对应组件的日志。第二看日志日志目录是$HADOOP_HOME/logs/每个角色对应单独的日志文件。tail -100最新的报错信息重点看栈顶的Caused by。Hadoop的报错很啰嗦但Caused by后面那几行通常才是真正的根因。第三看状态hdfs dfsadmin -report看集群整体状态yarn node -list看YARN节点hdfs haadmin -getAllServiceState看HA状态。第四看系统资源free -g看内存df -h看磁盘df -i看inode。这两个经常被忽略——HDFS小文件一多inode会先被耗尽表现就是DataNode看着正常但写文件时各种超时。inode满的情况我当时排查了一下午最后df -i一看全是100%那种感觉真是刻骨铭心。7. 实操中的几个个性化建议平台能跑起来只是第一步真正用起来还有几个建议是我在实际操作中反复体会过的。把启停命令封装成脚本。集群节点越多启停操作越繁琐而且启动顺序有讲究ZK → JournalNode → HDFS/YARN。我在每台机器上写了一个~/hadoop-ctl.sh包含start/stop/status三个参数先把ZK和JournalNode拉起来再执行start-dfs.sh最后确认所有进程都在。这样每次开机恢复集群只需要执行一条命令。定期做NameNode元数据备份。NameNode格式化一次就把clusterId全换了如果不小心误操作恢复极麻烦。我习惯每天用hdfs dfsadmin -fetchImage /backup/把当前NameNode的fsimage拉一份到本地备份出问题的时候能快速恢复。在配置里打开日志聚合。默认情况下MapReduce作业跑完后日志分散在各NodeManager上排查问题要挨个机器翻。在yarn-site.xml里加上property nameyarn.log-aggregation-enable/name valuetrue/value /property跑到ResourceManager的8088界面点进任何一个历史作业就能看全部日志效率翻倍。给新手一个明确的“成功标准”。平台搭建完别急着撒手。列一份验收清单HDFS能正常读写文件、能上传真实数据、跑通一个MapReduce作业、YARN界面能看到集群资源、故意停掉一个worker节点集群不瘫痪HA模式下。这五项全过再往外发“环境已就绪”的消息否则后面开发同学用起来三天两头找你救火。回头再看Hadoop平台搭建这件事技术上真不难难点全在细节和环境差异上。把前面那些坑一个个排掉之后再搭第二套、第三套环境基本就是流水线作业了。如果你在搭建过程中遇到什么没见过的报错记住那条排查方法论先看日志再找根因别盲目重装。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进