ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

Hadoop 3.3.6分布式集群从零部署实战指南

Hadoop 3.3.6分布式集群从零部署实战指南

1. 项目概述:这不是装个软件,而是搭一座数据工厂的地基

“大数据生态系统(Hadoop)的安装部署”——这九个字背后,不是一条命令敲完就能跑起来的玩具,而是一整套分布式计算基础设施的物理落成。我带过三届某高校实验室的实训项目,每次开课前第一件事,就是让学员亲手把 Hadoop 集群从零搭起来。为什么非得自己装?因为跳过这一步,后面所有 MapReduce、Spark 作业、Hive 查询、HBase 写入,全都会变成黑盒里的幻影。你调不通一个hdfs dfs -ls /,就永远不知道 NameNode 是在监听 9000 还是 8020,DataNode 是卡在 SSH 免密登录失败,还是磁盘挂载点权限没放开。Hadoop 不是“开箱即用”的应用,它是一套需要你亲手拧紧每一颗螺丝的重型机械。它的核心价值,在于把廉价 x86 服务器变成一台逻辑上统一、存储与计算可线性扩展的超级计算机。而安装部署,就是把这台机器的底盘、传动轴、油路和电路全部接通的过程。关键词里反复出现的“大数据生态系统”,指的正是以 HDFS 为存储底座、YARN 为资源调度中枢、MapReduce 为原生计算引擎,并向外延伸出 Hive、HBase、Spark、Flink 等组件的完整技术栈。今天我们要做的,就是把这个生态最底层、最硬核的那块基石——Hadoop 3.x 分布式集群——稳稳地夯进你的物理或虚拟机环境里。无论你是刚学完 Java 基础想进大数据领域的新人,还是运维老手要给测试环境配一套最小可行集群,这套部署方案都经过了上百次实操验证:它不依赖 Docker 或 Kubernetes 这类抽象层,直面 Linux 权限、网络配置、JVM 参数这些真实世界里的毛刺;它不追求一键脚本的虚假便捷,而是让你每一步都清楚“我在改什么、为什么这么改、不这么改会怎样”。接下来的内容,没有一句是教科书复述,全是我在机房里蹲着看日志、改配置、重装系统时记下的血泪笔记。

2. 整体设计与思路拆解:为什么选伪分布+完全分布双模式,而不是直接上云?

2.1 为什么拒绝“一键安装包”和“Docker Compose 快速启动”

市面上确实有各种 Hadoop 一键安装脚本,甚至还有封装好的 Docker 镜像,几条命令就能拉起一个“看起来能跑”的集群。但我在某公司做内部培训时发现,用这类方案的学员,三个月后连hdfs namenode -format执行失败的原因都查不出来。问题出在抽象层级太高:Docker 把/etc/hosts、SSH 密钥分发、Java 环境变量隔离、日志路径挂载这些底层细节全吞掉了;一键脚本则把core-site.xml和hdfs-site.xml的关键参数硬编码进 shell 变量里,你根本看不到它们长什么样。真正的生产环境不会给你一个预装好的容器,它只给你一台裸机、一个 root 密码、一段网络策略文档。所以我们的设计起点非常明确:必须暴露所有配置项,必须手动控制每一个服务进程的启停,必须能随时进入任意节点的 shell 查看实时状态。这不是复古,而是建立“系统直觉”的必经之路。就像学开车不能只坐自动驾驶汽车,你得亲手感受离合器的咬合点、方向盘的虚位、刹车的点头感——Hadoop 的jps输出、tail -f logs/hadoop-xxx-namenode-xxx.log的滚动日志、netstat -tuln | grep 9870的端口监听状态,就是这个系统的“驾驶反馈”。

2.2 伪分布模式:单机上的“微缩沙盒”,专治概念模糊症

很多初学者一上来就想搞三台虚拟机搭完全分布集群,结果卡在 SSH 免密登录三天。我们反其道而行之,先在一台机器上跑伪分布(Pseudo-Distributed)模式。这不是妥协,而是精准打击认知盲区。伪分布意味着:NameNode、DataNode、ResourceManager、NodeManager 全部跑在同一台机器的不同 JVM 进程里,但它们严格遵循分布式架构的通信协议和配置逻辑。HDFS 的客户端依然要通过hdfs://localhost:9000访问,YARN 的 ApplicationMaster 依然要向 ResourceManager 申请 Container,只是这些“远程”调用,实际走的是本地回环地址。这种模式的价值在于:它用最低硬件成本,100% 复现了分布式环境的核心约束——比如 DataNode 必须向 NameNode 定期发送心跳(默认3秒),如果 NameNode 持续收不到心跳,就会把该 DataNode 标记为 dead;再比如 YARN 的 NodeManager 启动后,必须能被 ResourceManager 识别并纳入资源池,否则yarn node -list就永远为空。你在单机上调试通了这些机制,再扩到多机,只是把localhost换成真实 IP,把免密登录从本机扩展到多机,思维模型完全平移。我见过太多人,在三节点集群里start-dfs.sh报错,却连hadoop fs -ls /在伪分布下是否成功都懒得验证——这就像没学会走路就想跑马拉松。

2.3 完全分布模式:三节点黄金组合,平衡学习深度与资源消耗

当伪分布稳定运行后,我们立刻升级到三节点完全分布(Fully-Distributed)集群。为什么是三台,而不是两台或五台?这是经过大量教学实践验证的“黄金比例”。两节点存在单点故障风险:如果 NameNode 和 ResourceManager 都挤在一台机器上,它一宕机,整个集群就瘫痪,你无法体会高可用(HA)的必要性;五节点则徒增管理复杂度,光是同步/etc/hosts、分发密钥、检查每台机器的磁盘空间,就可能耗掉半天时间,冲淡对核心原理的关注。三节点分工明确:Node1 专职 NameNode + ResourceManager(主控节点),Node2 和 Node3 均作为 DataNode + NodeManager(工作节点)。这个结构天然模拟了生产环境的主从架构,同时留出了冗余空间——比如你可以把 Node1 的 SecondaryNameNode 单独拎出来,或者后续把 ZooKeeper 集群部署在 Node2 上,为 NameNode HA 做准备。更重要的是,三节点能真实暴露网络问题:当hdfs dfsadmin -report显示某个 DataNode 的状态是InDead,你必须用ping、telnet、ss -tuln一层层排查,是防火墙挡了 9866 端口?还是/etc/hosts里 IP 和主机名映射错了?还是 SELinux 拦截了 socket 绑定?这些实战经验,是任何文档都写不出来的。

2.4 版本选择:Hadoop 3.3.6 是当前最稳的“教学锚点”

Hadoop 版本迭代很快,但教学场景追求的是稳定性与文档完备性。我们锁定 Hadoop 3.3.6(截至2024年中最新稳定版),原因有三:第一,它彻底移除了对 JDK 7 的支持,强制要求 JDK 8u161+ 或 JDK 11,这迫使你直面现代 Java 环境的配置,避免陷入“为什么我的 JDK 7 跑不起来”的无谓争论;第二,它默认启用了纠删码(Erasure Coding)和基于容器的 YARN 调度,虽然教学中我们暂时不用,但配置文件里能看到dfs.namenode.ec.system.default.policy这样的新参数,让你感知到技术演进的方向;第三,它的官方文档和社区问答(Stack Overflow、Hadoop 用户邮件列表)关于 3.3.x 的内容最丰富,遇到报错,Google 一下错误码,90% 的答案都是针对这个版本的。有人会问为什么不选最新的 3.4.x?因为新版本往往伴随一些未被广泛验证的默认行为变更,比如某个 RPC 超时参数的默认值调整,可能导致你在某台特定配置的虚拟机上莫名卡住。教学的第一目标是“可预期”,而不是“尝鲜”。就像学游泳,先确保能在浅水区站稳,再考虑深水区的蝶泳技巧。

3. 核心细节解析与实操要点:那些配置文件里藏着的魔鬼细节

3.1 Java 环境:不是装了 JDK 就万事大吉,关键是“谁在用哪个 JDK”

Hadoop 对 Java 的依赖极其苛刻。它不是一个普通 Java 应用,而是一个由多个子项目(HDFS、YARN、MapReduce)组成的巨无霸,每个子项目都可能有自己的 JVM 启动参数。很多人卡在第一步:hadoop version报错JAVA_HOME is not set,明明echo $JAVA_HOME显示路径正确。问题出在Shell 环境变量的作用域。Hadoop 的启动脚本(如start-dfs.sh)会重新加载自己的环境配置,它读取的是$HADOOP_HOME/etc/hadoop/hadoop-env.sh里的JAVA_HOME,而不是你.bashrc里设置的那个。所以,你必须在hadoop-env.sh文件顶部,取消注释并精确填写:

export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64

注意:路径必须是 JDK 的根目录,不是 JRE 目录;必须用绝对路径,不能用~;必须确认该路径下存在bin/java和lib/rt.jar(JDK 11 后是lib/modules)。我踩过的最大坑是:在 Ubuntu 上用apt install openjdk-11-jdk安装后,JAVA_HOME默认指向/usr/lib/jvm/java-11-openjdk-amd64,但如果你的系统是 ARM 架构(比如树莓派),路径末尾应该是-arm64,写错一个字母,hadoop-daemon.sh就会静默退出,日志里只有一行JAVA_HOME not found。验证方法很简单:在hadoop-env.sh修改后,执行source $HADOOP_HOME/etc/hadoop/hadoop-env.sh && echo $JAVA_HOME,确保输出和你写的完全一致。这是所有后续操作的基石,宁可在这里花十分钟确认,也不要等到start-dfs.sh失败后再回头翻日志。

3.2 SSH 免密登录:不是为了省事,而是分布式通信的“信任握手”

Hadoop 集群启动时,主控节点(NameNode/ResourceManager 所在机器)需要通过 SSH 无密码登录到所有工作节点(DataNode/NodeManager 所在机器),去启动对应的守护进程。这不是一个便利性功能,而是分布式协调的底层机制。start-dfs.sh脚本的实质,就是遍历slaves文件(Hadoop 3.x 改名为workers)里的主机名,对每一台执行ssh hostname 'hadoop-daemon.sh start datanode'。如果 SSH 需要输密码,脚本就卡在那里,永远不会继续。配置步骤看似简单,但细节决定成败:首先,在主控节点生成密钥对ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa,-P ''表示空密码,这是关键;其次,把公钥id_rsa.pub的内容,用ssh-copy-id -i ~/.ssh/id_rsa.pub user@worker1命令追加到每个工作节点的~/.ssh/authorized_keys文件末尾;最后,也是最容易被忽略的:确保所有节点的~/.ssh目录权限是 700,authorized_keys文件权限是 600。Linux 的 SSH 服务极其严格,如果authorized_keys权限是 644,它会直接拒绝使用该密钥,报错Authentication refused: bad ownership or modes for directory /home/user/.ssh。我曾经在一个 CentOS 7 虚拟机上折腾了两小时,就是因为scp传输时自动把权限改成了 644。解决方法是登录到工作节点,执行chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys。记住,这不是一次性的配置,每次你重建虚拟机或重装系统,都必须重复这个过程。

3.3 HDFS 核心配置:core-site.xml和hdfs-site.xml的参数哲学

HDFS 的配置文件不是参数罗列,而是一套分布式共识协议的文本化表达。core-site.xml定义了整个 Hadoop 生态的“世界观”,其中最关键的参数是fs.defaultFS:

<property> <name>fs.defaultFS</name> <value>hdfs://node1:9000</value> </property>

这个值告诉所有 Hadoop 客户端:“默认的文件系统是运行在 node1 主机 9000 端口上的 HDFS”。注意,这里写的是node1,不是localhost或127.0.0.1。因为在完全分布模式下,DataNode 进程启动后,会向node1:9000发起注册请求,如果这里写localhost,DataNode 就会试图连接自己本机的 9000 端口,而那个端口上根本没有 NameNode 在监听。hdfs-site.xml则定义了 HDFS 自身的“宪法”,核心参数是dfs.namenode.name.dir和dfs.datanode.data.dir:

<property> <name>dfs.namenode.name.dir</name> <value>file:///opt/hadoop/data/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:///opt/hadoop/data/datanode</value> </property>

这两个路径,一个是 NameNode 存储元数据(文件系统树、块映射关系)的地方,一个是 DataNode 存储实际数据块的地方。它们必须是绝对路径,且目录必须存在、可写。我建议统一放在/opt/hadoop/data/下,而不是默认的/usr/local/hadoop/...,因为/opt是 Linux 标准的第三方软件数据存放目录,语义清晰。创建目录后,务必执行chown -R hadoop:hadoop /opt/hadoop/data(假设你用hadoop用户运行服务),否则启动时会报Permission denied。还有一个隐藏陷阱:dfs.replication默认值是 3,意思是每个文件块会复制三份。但在单节点伪分布模式下,你只有 1 个 DataNode,HDFS 会拒绝写入,报错File /test.txt could only be replicated to 0 nodes instead of minReplication (=3)。解决方案是在伪分布模式下,临时将dfs.replication改为1,等切换到三节点集群时,再改回3。这个参数的调整,就是理解“副本数”与“可用 DataNode 数量”之间硬约束的最好课堂。

3.4 YARN 核心配置:yarn-site.xml里的资源博弈

YARN 是 Hadoop 的资源管家,它负责把集群的 CPU、内存切分成一个个“容器”(Container),分给 MapReduce、Spark 等计算框架使用。yarn-site.xml的配置,本质上是在回答一个问题:“我有多少资源可以分,怎么分才公平?”最关键的三个参数是:

<property> <name>yarn.resourcemanager.hostname</name> <value>node1</value> </property> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.nodemanager.resource.memory-mb</name> <value>4096</value> </property>

第一个参数yarn.resourcemanager.hostname,和core-site.xml里的fs.defaultFS一样,必须写主机名node1,不能写localhost,否则 NodeManager 无法注册到 ResourceManager。第二个参数yarn.nodemanager.aux-services,值必须是mapreduce_shuffle,这是 MapReduce 任务 Shuffle 阶段(Map 输出传给 Reduce 输入)所依赖的辅助服务,如果写错或漏掉,hadoop jar运行 WordCount 就会卡在ACCEPTED状态,永远不变成RUNNING。第三个参数yarn.nodemanager.resource.memory-mb,定义了每个 NodeManager 节点最多能提供多少内存给容器使用。假设你的工作节点有 8GB 内存,这里设为4096(4GB)是安全的,因为操作系统、Hadoop 自身进程、DataNode 进程都需要内存。设得太高,会导致节点 OOM(内存溢出);设得太低,又浪费资源。一个经验法则是:为每个工作节点预留 2GB 给系统和其他服务,剩下的给 YARN。这个参数的调整,会让你第一次真切感受到“资源调度”不是玄学,而是可以用数字精确计算的工程实践。

4. 实操过程与核心环节实现:从零开始,一步步把集群点亮

4.1 环境准备:三台虚拟机的标准化初始化(以 Ubuntu 22.04 为例)

我们以最通用的 Ubuntu 22.04 LTS 为操作系统,创建三台最小化安装的虚拟机(VMware Workstation 或 VirtualBox 均可)。每台分配 2 核 CPU、4GB 内存、40GB 硬盘。初始化步骤必须严格一致,这是集群稳定的基础:

  1. 更新系统并安装基础工具:

    sudo apt update && sudo apt upgrade -y sudo apt install -y openjdk-11-jdk ssh curl wget vim net-tools

    注意:openjdk-11-jdk是必须的,ssh客户端和服务端都要装(sudo apt install -y openssh-server openssh-client),net-tools提供ifconfig和netstat,比ip命令更直观。

  2. 创建专用用户并配置 sudo 权限:

    sudo adduser hadoop sudo usermod -aG sudo hadoop

    强烈建议不要用 root 用户运行 Hadoop!创建hadoop用户,既符合安全规范,又能避免因权限混乱导致的奇奇怪怪的错误(比如日志文件属主不对)。

  3. 配置静态 IP 和主机名映射: 编辑/etc/netplan/00-installer-config.yaml(Ubuntu 22.04 使用 Netplan),为每台机器分配固定 IP:

    • Node1(主控):192.168.56.101
    • Node2(工作):192.168.56.102
    • Node3(工作):192.168.56.103

    然后编辑/etc/hosts,在所有三台机器上添加:

    192.168.56.101 node1 192.168.56.102 node2 192.168.56.103 node3

    这是 Hadoop 集群的“电话簿”,所有组件都靠这个映射来互相寻址。IP 和主机名之间必须用 Tab 键分隔,不能用空格,否则某些旧版 Hadoop 会解析失败。

  4. 关闭防火墙(教学环境):

    sudo ufw disable

    生产环境当然要精细配置端口白名单,但教学阶段,关掉防火墙能避免 90% 的“连不上”问题。Hadoop 需要开放的端口非常多(NameNode 9870, 9000; DataNode 9864, 9866; ResourceManager 8088; NodeManager 8042),逐一配置太耗时。

完成以上四步,三台机器就变成了一个干净、统一、可预测的“画布”,我们可以开始绘制 Hadoop 这幅巨作了。

4.2 Hadoop 安装与分发:解压、配置、同步的流水线

  1. 下载与解压: 在 Node1 上,用wget下载 Hadoop 3.3.6 二进制包(hadoop-3.3.6.tar.gz),然后解压到/opt/目录:

    cd /opt sudo wget https://downloads.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz sudo tar -xzf hadoop-3.3.6.tar.gz sudo mv hadoop-3.3.6 hadoop sudo chown -R hadoop:hadoop /opt/hadoop

    关键点:chown必须在解压后立即执行,确保hadoop用户拥有整个目录的完全控制权。

  2. 配置hadoop-env.sh: 编辑/opt/hadoop/etc/hadoop/hadoop-env.sh,找到export JAVA_HOME=这一行,修改为:

    export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64

    并取消注释export HADOOP_OPTS="-Djava.security.krb5.conf=/etc/krb5.conf"这一行(即使不用 Kerberos,也要保留,避免某些发行版报错)。

  3. 配置核心 XML 文件:

    • core-site.xml:设置fs.defaultFS为hdfs://node1:9000
    • hdfs-site.xml:设置dfs.namenode.name.dir和dfs.datanode.data.dir为/opt/hadoop/data/...,dfs.replication设为1(伪分布)或3(完全分布)
    • yarn-site.xml:设置yarn.resourcemanager.hostname为node1,yarn.nodemanager.aux-services为mapreduce_shuffle
    • workers文件:在完全分布模式下,删除localhost,写入node2和node3(每行一个)
  4. 分发到所有节点: 在 Node1 上,用scp把整个/opt/hadoop目录同步到 Node2 和 Node3:

    scp -r /opt/hadoop hadoop@node2:/opt/ scp -r /opt/hadoop hadoop@node3:/opt/

    注意:scp命令本身也依赖 SSH 免密登录,所以这一步能成功,就证明你的 SSH 配置已经 OK 了。同步完成后,登录到 Node2 和 Node3,执行chown -R hadoop:hadoop /opt/hadoop,确保权限一致。

4.3 伪分布模式启动与验证:用五个命令建立信心

伪分布模式是信心的起点。在 Node1 上,以hadoop用户身份执行以下命令:

  1. 格式化 NameNode:

    /opt/hadoop/bin/hdfs namenode -format

    这是 HDFS 的“初始化硬盘”操作,它会在dfs.namenode.name.dir指定的路径下创建初始的元数据文件。首次运行会输出一大段日志,最后一行是Storage directory ... has been successfully formatted.,看到这个,你就成功了一半。

  2. 启动 HDFS:

    /opt/hadoop/sbin/start-dfs.sh

    这个脚本会启动 NameNode(在本机)和 DataNode(也在本机)。执行后,用jps命令查看进程:

    jps # 应该看到:NameNode, DataNode, Jps
  3. 启动 YARN:

    /opt/hadoop/sbin/start-yarn.sh

    同样用jps查看:

    jps # 应该看到:NameNode, DataNode, ResourceManager, NodeManager, Jps
  4. 验证 HDFS 健康状态:

    /opt/hadoop/bin/hdfs dfsadmin -report

    输出中,Configured Capacity应该是一个正数,DFS Used%应该是 0%,Live datanodes数量应该是 1。如果看到Dead datanodes,说明 DataNode 没起来,回去检查hadoop-env.sh和hdfs-site.xml。

  5. 运行一个经典测试:

    echo "Hello Hadoop World" > input.txt /opt/hadoop/bin/hdfs dfs -mkdir -p /user/hadoop/input /opt/hadoop/bin/hdfs dfs -put input.txt /user/hadoop/input/ /opt/hadoop/bin/hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar wordcount /user/hadoop/input /user/hadoop/output /opt/hadoop/bin/hdfs dfs -cat /user/hadoop/output/part-r-00000

    这个 WordCount 例子会把input.txt上传到 HDFS,运行 MapReduce 计算,把结果写回 HDFS,最后打印出来。如果最终输出Hello 1Hadoop 1World 1,恭喜你,你的伪分布集群已经活了!这五个命令,就是 Hadoop 的“Hello World”,它比任何理论讲解都更能让你触摸到分布式计算的脉搏。

4.4 完全分布模式启动与排障:从单机到集群的跃迁

当伪分布稳定运行后,我们进行最关键的跃迁:把 DataNode 和 NodeManager 进程,从 Node1 迁移到 Node2 和 Node3。

  1. 修改配置,切换模式:

    • 在hdfs-site.xml中,把dfs.replication从1改为3
    • 在workers文件中,确保只有node2和node3(删除localhost)
    • 在所有节点的core-site.xml和yarn-site.xml中,确认fs.defaultFS和yarn.resourcemanager.hostname都指向node1
  2. 清理旧数据,重新格式化: 因为现在是多节点,NameNode 的元数据和 DataNode 的数据块必须重新对齐。在 Node1 上:

    # 清理 NameNode 数据 rm -rf /opt/hadoop/data/namenode/* # 清理所有 DataNode 数据(需要分别登录到 node2 和 node3 执行) ssh node2 "rm -rf /opt/hadoop/data/datanode/*" ssh node3 "rm -rf /opt/hadoop/data/datanode/*" # 重新格式化 /opt/hadoop/bin/hdfs namenode -format
  3. 启动集群: 在 Node1 上,依次执行:

    /opt/hadoop/sbin/start-dfs.sh # 启动 HDFS,NameNode 在 node1,DataNode 在 node2/node3 /opt/hadoop/sbin/start-yarn.sh # 启动 YARN,ResourceManager 在 node1,NodeManager 在 node2/node3
  4. 核心验证命令:

    • hdfs dfsadmin -report:应该显示Live datanodes = 2,并且node2和node3的 IP 和状态都正常。
    • yarn node -list:应该显示两个RUNNING状态的 NodeManager。
    • hdfs dfs -ls /:应该能列出根目录,证明 HDFS 可读。
    • hadoop fs -du -h /:查看 HDFS 各目录的磁盘使用情况,确认数据真的分布在不同节点上。

如果hdfs dfsadmin -report显示Dead datanodes,这就是典型的“排障练兵场”。我总结了一个快速排查流程表:

现象可能原因排查命令解决方案
node2显示Dead,但node3正常node2的 DataNode 进程未启动ssh node2 "jps"登录node2,执行/opt/hadoop/sbin/hadoop-daemon.sh start datanode
node2和node3都Deadnode1的 NameNode 没起来,或workers文件配置错误jpson node1;cat /opt/hadoop/etc/hadoop/workers检查 NameNode 进程;确认workers文件里没有空行或多余字符
node2Dead,jps显示 DataNode 进程存在DataNode 无法连接 NameNodessh node2 "telnet node1 9000"检查node1的防火墙;检查node1的/etc/hosts是否正确解析node1

这个表格,是我过去三年在实验室里,帮学员解决的前 100 个问题的精华浓缩。它不教你理论,只告诉你“看到什么,就做什么”,这才是工程实践的真谛。

5. 常见问题与排查技巧实录:那些让你抓狂,却又无比珍贵的“坑”

5.1 “Connection refused” 错误:网络层的无声杀手

这是完全分布模式下最常见、也最容易让人崩溃的错误。当你在 Node1 上执行start-dfs.sh,日志里疯狂刷Connection refused,或者hdfs dfsadmin -report一直卡住不动。别急着重装,先做三件事:

  1. 确认 NameNode 端口是否监听:在 Node1 上执行ss -tuln | grep 9000。如果没有任何输出,说明 NameNode 根本没起来。这时候去看/opt/hadoop/logs/hadoop-hadoop-namenode-node1.log的最后 20 行,通常会看到java.net.BindException: Address already in use,意思是 9000 端口被其他程序占用了。解决方案:sudo lsof -i :9000找出 PID,sudo kill -9 PID杀掉它。

  2. 确认 DataNode 能否访问 NameNode:在 Node2 上执行telnet node1 9000。如果显示Connected to node1,说明网络通;如果显示Connection refused,说明要么node1的防火墙开着,要么node1的 NameNode 进程没起来,要么node1的/etc/hosts里node1解析到了错误的 IP(比如127.0.1.1)。telnet是最原始、也最可靠的网络连通性测试工具,比ping有用得多,因为它测试的是 TCP 端口。

  3. 确认主机名解析是否正确:在 Node2 上执行getent hosts node1。它应该返回192.168.56.101 node1。如果返回空,或者返回了错误的 IP,问题就出在/etc/hosts文件。Linux 的getent命令会按/etc/nsswitch.conf的顺序查询,能准确反映系统真实的解析行为,比ping node1更可靠。

这三个命令,构成了一个坚不可摧的“网络三叉戟”,90% 的连接问题,都能被它斩于马下。记住,分布式系统的问题,80% 出在网络和配置上,而不是代码逻辑上。

5.2 日志文件:你最忠实、也最啰嗦的“技术顾问”

Hadoop 的日志,是解决问题的唯一真相来源。它的日志文件分散在$HADOOP_HOME/logs/目录下,命名规则是hadoop-<user>-<daemon>-<hostname>.log。比如hadoop-hadoop-namenode-node1.log就是 Node1 上 NameNode 的日志。新手常犯的错误是:一出错就百度错误信息,结果被各种过时的、针对旧版本的解决方案带偏。正确的做法是:打开日志,从最后一行往前看,找到第一个ERROR或FATAL级别的记录,然后仔细读它前面的几行上下文。日志不是小说,它是按时间倒序写的“事故报告”。

举个真实案例:某学员的 DataNode 总是启动几秒后就自动退出,jps看不到它。他翻遍了 Google,试了各种“修改 ulimit”、“增加 swap”的方案,都没用。我让他发给我hadoop-hadoop-datanode-node2.log的最后 50 行。里面有一行:

ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: Exception in secureMain java.io.IOException: All directories in dfs.datanode.data.dir are invalid: ...

再往前翻,看到:

WARN org.apache.hadoop.util.DiskChecker: Incorrect permission for /opt/hadoop/data/datanode, expected: rwxr-xr-x, current: rwxrwxr-x

真相大白:他用chmod 777给了datanode目录满权限,而 Hadoop 的安全策略要求 DataNode 目录必须是755,不能有w权限给 group 和 others。解决方案:chmod 755 /opt/hadoop/data/datanode。这个错误,任何搜索引擎都很难精准匹配,但日志里清清楚楚写着。所以,我的第一条实操心得是:养成习惯,任何问题,先看日志;任何日志,先看 ERROR 行;任何 ERROR 行,先看它前面的 WARN 和 INFO 行。日志是你最好的老师,只是它说话有点啰嗦。

5.3 “Safe mode” 陷阱:NameNode 的自我保护机制

当你执行 `hdfs dfsadmin -safemode get

RELATED READING

延伸阅读

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