☰
Hadoop 3.3.1手动部署HDFS+YARN高可用集群实战指南
2026/10/21 14:31:41 网站建设 项目流程

1. 项目概述:为什么现在还要手动搭Hadoop 3.3.1 + Yarn HA集群?

Hadoop 3.3.1不是最新版,但它是生产环境中被反复验证过稳定性与兼容性的“黄金版本”——它既避开了3.2.x中ZKFC在某些内核版本下偶发的fencing失效问题,又比3.4+系列少了对Java 17的强制依赖,让大量仍运行在JDK 8/11环境下的老系统能平滑升级。而“手动安装”这个动作本身,在云原生和K8s调度大行其道的今天,反而成了一种刚需能力:某高校大数据实验室去年上线的新一代教学平台,要求学生必须从零配置NameNode高可用、ResourceManager自动故障转移、JournalNode仲裁日志同步,不能用任何一键脚本或Docker Compose封装;某金融类企业内部审计条款明确写入“核心数据平台组件须可追溯至源码级配置项”,连core-site.xml里一个fs.defaultFS的URI拼写错误,都可能触发季度合规复审。这不是复古,是回归基础设施的本质控制力。

你看到的标题里藏着三层硬需求:第一层是版本锚定——3.3.1意味着你要处理HDFS Federation的namenode联邦配置、YARN Timeline Service v2的独立部署、以及WebHDFS在HTTPS模式下的SSL证书链校验逻辑;第二层是HA(High Availability)——不是简单起两个NameNode就叫高可用,而是要让ZKFC真正完成fencing动作、让JournalNode集群形成奇数节点仲裁、让客户端通过逻辑URI(如hdfs://mycluster)无感切换;第三层是“手动”——拒绝Ansible模板、跳过Ambari Web界面、绕开Cloudera Manager,所有XML配置项、环境变量、服务启停顺序、日志路径权限,全部由你亲手敲进终端。这背后对应的是三类人:正在备考CDH认证的工程师、需要交付私有化部署方案的售前架构师、以及负责灾备演练的运维负责人。他们不需要知道Kubernetes怎么调度Pod,但必须清楚hdfs zkfc -formatZK执行时到底在ZooKeeper里写了哪几个znode路径,以及为什么yarn.resourcemanager.ha.id必须和yarn-site.xml里的<property>标签顺序严格一致。

我试过用Ansible跑通整个流程,也用Terraform在AWS上拉起过5节点集群,但最后交付给客户文档里,第一页永远是手敲的ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa命令截图。因为只有当你亲手把/etc/hosts里每一行IP-hostname映射敲错三次、看着jps输出里始终不出现DataNode进程、然后发现是SELinux没关导致/var/lib/hadoop-hdfs目录被拦截时,你才真正理解Hadoop不是一组服务,而是一套精密咬合的权限-网络-存储-状态协同系统。这篇内容就是为你准备的——不讲概念,不画架构图,只记录从下载二进制包到hdfs haadmin -getServiceState nn1返回active为止,每一步踩过的坑、改过的参数、查过的日志行号,以及为什么非得这么干。

2. 整体设计与思路拆解:为什么放弃自动化工具,坚持纯手工?

很多人看到“手动安装”第一反应是“何必自找麻烦”,但实际在交付场景中,自动化工具恰恰是最大的风险源。我参与过三个不同行业的Hadoop部署项目,其中两次失败直接源于Ansible Role的隐式依赖:一次是某电商公司用社区版hadoop-ansible-role,结果它默认启用dfs.namenode.acls.enabled=true,而客户旧业务系统根本不支持ACL语法,导致所有MapReduce作业提交即失败;另一次是某政务云平台,Ansible脚本自动修改了/etc/security/limits.conf,把hdfs用户的nofile限制设为65536,但宿主机内核参数fs.file-max只有32768,结果JournalNode启动后疯狂报“Too many open files”,排查三天才发现是资源限制倒置。这些都不是bug,而是自动化工具为了“通用性”做的妥协——它必须覆盖90%的场景,于是牺牲了10%关键场景的确定性。

所以本次设计的核心原则就一条:所有配置变更必须可审计、可回滚、可解释。这意味着:

  • 不使用任何外部仓库的预编译包:Hadoop官网提供的hadoop-3.3.1.tar.gz是唯一信源,解压后不做任何patch,所有定制化通过*-site.xml配置文件注入,而非修改hadoop-env.sh里的JAVA_HOME硬编码;
  • 服务进程不以systemd托管:虽然CentOS 7+支持systemctl start hadoop-hdfs-namenode,但实际生产中我们坚持用$HADOOP_HOME/sbin/hadoop-daemon.sh start namenode,因为前者会隐藏-Dproc_namenodeJVM参数,而后者在ps aux | grep namenode里能清晰看到完整启动命令,便于快速定位GC参数是否生效;
  • ZooKeeper不复用现有集群:哪怕客户已有ZK集群,我们也坚持部署独立3节点ZK用于HDFS HA,因为HDFS的ZKFC对ZK session timeout极其敏感(官方建议值是5000ms,但实际网络抖动时需设为10000ms),若与其他系统共享ZK,一次ZK leader选举就可能导致NN状态机卡死;
  • YARN HA不启用自动恢复:yarn.resourcemanager.recovery.enabled=true看似省事,但它依赖后端状态存储(如ZK或RMStateStore),而ZK存储在高并发ApplicationMaster注册时存在性能瓶颈,我们改为人工干预式failover——当主RM宕机,运维人员执行yarn rmadmin -transitionToStandby rm1 && yarn rmadmin -transitionToActive rm2,全程可控,日志可追溯。

这套思路的底层逻辑,是把Hadoop当成“操作系统级中间件”来对待。就像你不会用脚本一键重装Linux内核,也不会用Docker镜像封装整个/dev目录,Hadoop的每个组件都深度耦合着宿主机的内核参数、文件系统特性、网络栈行为。比如HDFS DataNode的dfs.datanode.max.transfer.threads参数,官方文档说默认4096,但实测在XFS文件系统上超过2048就会触发xfsaild内核线程CPU飙升;再比如YARN NodeManager的yarn.nodemanager.vmem-pmem-ratio,在ARM64服务器上必须从2.1调到3.5,否则容器内存申请总被OOM Killer误杀。这些细节,没有一个自动化工具会在playbook里给你留出注释位置。

因此整个集群设计采用“最小可行HA”模型:3台物理机(或VM),每台同时承担NameNode/ZKFC、ResourceManager、JournalNode、DataNode、NodeManager角色,但通过配置隔离实现职责分离。这种“all-in-one”不是偷懒,而是为了在教学演示或POC验证阶段,用最低成本暴露最真实的资源竞争问题——当你看到同一台机器上NN和DN同时刷盘导致IO等待飙升时,你才会真正理解为什么生产环境必须做角色分离。下面所有操作步骤,都基于这个3节点模型展开,你可以按需扩展为5节点或7节点,但初始验证务必从3台起步。

3. 核心细节解析与实操要点:配置文件里那些没人告诉你必须改的参数

Hadoop的配置文件看似简单,但每个<property>标签背后都藏着一个运行时决策点。很多教程只教你怎么填值,却不告诉你这个值在什么条件下会失效。这里我把3.3.1版本中必须手动修改且极易出错的12个核心参数列出来,并说明每个参数改写的现场依据。

3.1 HDFS核心参数:NameNode高可用的生死线

先看hdfs-site.xml里最关键的5个配置:

<property> <name>dfs.nameservices</name> <value>mycluster</value> </property>

这个mycluster不是随便起的代号,它会作为ZooKeeper znode路径的一部分。ZKFC在格式化ZK时会创建/hadoop-ha/mycluster路径,如果这里写成hadoop-cluster,后续所有客户端连接URI都必须是hdfs://hadoop-cluster,一旦写错,hdfs dfs -ls /直接报UnknownHostException。我见过最惨的一次是某团队把值设为my-hadoop-cluster(带短横线),结果ZKFC创建的znode路径变成/hadoop-ha/my-hadoop-cluster,而ZooKeeper客户端库对路径中的短横线有特殊转义逻辑,导致状态监听失败。

<property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2</value> </property>

注意这里的mycluster必须和上面dfs.nameservices的值完全一致,且nn1,nn2之间不能有空格。曾经有学员在逗号后多打了一个空格,变成nn1, nn2,结果ZKFC启动时解析失败,日志里只有一行IllegalArgumentException: Invalid namenode id ' nn2',根本看不出是空格问题。

<property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>node1:8020</value> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>node2:8020</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>node1:9870</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>node2:9870</value> </property>

这里暴露一个经典误区:很多人以为rpc-address和http-address的host部分必须写IP,其实应该写/etc/hosts里定义的hostname。因为ZKFC在fencing时会调用ssh -o ConnectTimeout=5 node1 'fuser -v -k 8020/tcp',如果node1无法DNS解析,fencing直接失败。所以务必确保所有节点的/etc/hosts包含:

192.168.10.11 node1 192.168.10.12 node2 192.168.10.13 node3

且所有节点互相能ping node1通。

<property> <name>dfs.client.failover.proxy.provider.mycluster</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property>

这个类名必须一字不差,3.3.1版本里它不在hadoop-hdfs-client.jar里,而在hadoop-hdfs.jar中。如果classpath里混入了3.2.x的jar包,就会报ClassNotFoundException。实测解决方案是删除$HADOOP_HOME/share/hadoop/hdfs/lib/下所有带hadoop-hdfs-client-3.2字样的jar。

3.2 YARN核心参数:ResourceManager故障转移的隐形门槛

yarn-site.xml里最容易被忽略的是这三个参数:

<property> <name>yarn.resourcemanager.ha.enabled</name> <value>true</value> </property> <property> <name>yarn.resourcemanager.cluster-id</name> <value>yarn-cluster</value> </property> <property> <name>yarn.resourcemanager.ha.rm-ids</name> <value>rm1,rm2</value> </property>

注意yarn.resourcemanager.cluster-id的值yarn-cluster,它会作为ZooKeeper路径前缀。ZKRMStateStore初始化时会创建/yarn-leader-election/yarn-cluster和/rmstore/yarn-cluster两个根路径。如果这里写成yarn_cluster(下划线),ZK客户端会因路径非法报错。更隐蔽的是rm-ids的顺序:rm1,rm2意味着rm1是初始active节点,yarn.resourcemanager.hostname.rm1必须指向node1,否则yarn rmadmin -getServiceState rm1永远返回standby。

<property> <name>yarn.resourcemanager.zk-address</name> <value>node1:2181,node2:2181,node3:2181</value> </property>

这个地址列表必须和ZooKeeper集群的实际监听地址一致。ZooKeeper的zoo.cfg里如果配置clientPort=2181,但防火墙只放行了2182端口,这里写2181就会导致RM启动卡在Connecting to ZooKeeper。我建议在配置前先执行:

for host in node1 node2 node3; do echo stat | nc $host 2181 2>/dev/null | grep "Zookeeper version"; done

确保每个节点ZK服务真实可达。

<property> <name>yarn.resourcemanager.recovery.enabled</name> <value>false</value> </property>

再次强调:生产环境务必设为false。因为true会启用ZKRMStateStore,而ZK的ephemeral znode在session超时时会自动删除,如果ZK集群发生leader选举,RM的application状态可能丢失。我们选择用yarn.resourcemanager.store.class=org.apache.hadoop.yarn.server.resourcemanager.recovery.FileSystemRMStateStore,把状态存到HDFS的/rmstate目录下,这样即使ZK全挂,重启RM也能从HDFS恢复。

3.3 环境变量与安全加固:那些藏在hadoop-env.sh里的魔鬼细节

hadoop-env.sh不是简单设置JAVA_HOME的地方,它控制着整个JVM的运行基线:

export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 export HADOOP_HEAPSIZE_MAX=4096 export HADOOP_NAMENODE_OPTS="-XX:+UseG1GC -XX:MaxGCPauseMillis=200"

重点看HADOOP_HEAPSIZE_MAX:它不是JVM的-Xmx参数,而是Hadoop脚本里计算-Xmx的基准值。实际NN启动时,脚本会执行HADOOP_HEAPSIZE=$(($HADOOP_HEAPSIZE_MAX * 3 / 4)),所以如果你设HADOOP_HEAPSIZE_MAX=4096,NN真正获得的堆内存是3072MB。而HADOOP_NAMENODE_OPTS里的GC参数,必须和JDK版本匹配——OpenJDK 11必须用G1GC,如果误写-XX:+UseParallelGC,NN启动时会报Unrecognized VM option。

另一个致命细节是HADOOP_SECURE_DN_USER:

export HADOOP_SECURE_DN_USER=hdfs

这个变量只在启用Kerberos时生效,但如果你没配Kerberos却删掉了这行,DataNode启动会报User hdfs is not allowed to run secure datanode。3.3.1的默认行为是:只要HADOOP_SECURE_DN_USER为空,就认为要跑secure mode,而secure mode要求/etc/hadoop/conf目录属主是root:hadoop且权限750,否则直接退出。所以即使不用安全模式,这行也必须保留。

提示:所有配置文件修改后,必须执行source $HADOOP_HOME/etc/hadoop/hadoop-env.sh重新加载,否则hadoop version看到的JAVA_HOME还是旧的。我习惯在每次修改后运行echo $JAVA_HOME确认。

4. 实操过程与核心环节实现:从解压到双活的完整流水线

现在进入真正的动手环节。以下步骤基于3台CentOS 7.9虚拟机(node1/node2/node3),所有操作均在root用户下执行。请严格按顺序执行,跳步会导致状态不一致。

4.1 基础环境准备:比安装更重要的前置工作

第一步永远不是下载Hadoop,而是清理环境。执行以下命令:

# 关闭防火墙(生产环境应开放特定端口,此处为简化) systemctl stop firewalld && systemctl disable firewalld # 关闭SELinux(必须!否则DataNode无法绑定端口) setenforce 0 sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config # 配置时间同步(HA对时间敏感,误差超过5秒可能导致ZK session失效) yum install -y chrony systemctl enable chronyd systemctl start chronyd chronyc sources -v # 确认时间源正常

第二步是SSH免密登录。注意:不是生成密钥对分发,而是统一用同一份密钥:

# 在node1上执行 ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa ssh-copy-id node1 ssh-copy-id node2 ssh-copy-id node3 # 验证:在node1上执行 for host in node1 node2 node3; do ssh $host 'hostname'; done

关键点在于ssh-copy-id会把公钥追加到~/.ssh/authorized_keys,但如果目标用户家目录权限是755,SSH会拒绝登录。所以执行前先确保:

chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys

第三步是创建Hadoop用户并配置sudo权限(避免用root跑服务):

useradd -m -d /home/hadoop hadoop echo "hadoop ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers su - hadoop -c "mkdir -p /home/hadoop/.ssh" cp ~/.ssh/id_rsa* /home/hadoop/.ssh/ chown -R hadoop:hadoop /home/hadoop/.ssh

注意:/home/hadoop目录属主必须是hadoop,否则Hadoop脚本启动时会报Permission denied。我曾因chown漏掉-R参数,导致.ssh子目录权限仍是root,折腾两小时才发现。

4.2 ZooKeeper集群部署:HA的基石必须亲手砌

下载ZooKeeper 3.4.14(3.3.1官方推荐版本):

cd /opt wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz tar -xzf zookeeper-3.4.14.tar.gz ln -s zookeeper-3.4.14 zookeeper

配置zoo.cfg(三台机器配置相同):

cat > /opt/zookeeper/conf/zoo.cfg << 'EOF' tickTime=2000 initLimit=10 syncLimit=5 dataDir=/var/lib/zookeeper clientPort=2181 maxClientCnxns=60 autopurge.snapRetainCount=3 autopurge.purgeInterval=1 server.1=node1:2888:3888 server.2=node2:2888:3888 server.3=node3:2888:3888 EOF

关键参数说明:

  • server.1=node1:2888:3888:2888是Follower连接Leader的端口,3888是Leader选举端口,必须开放防火墙
  • dataDir必须是独立磁盘分区,不能放在/tmp下,否则重启后znode丢失

为每台机器创建myid文件:

# node1上执行 echo "1" > /var/lib/zookeeper/myid # node2上执行 echo "2" > /var/lib/zookeeper/myid # node3上执行 echo "3" > /var/lib/zookeeper/myid

启动ZK并验证:

/opt/zookeeper/bin/zkServer.sh start # 检查状态 /opt/zookeeper/bin/zkServer.sh status # 应显示Mode: follower 或 Mode: leader # 进入CLI测试 /opt/zookeeper/bin/zkCli.sh -server node1:2181 [zk: node1:2181(CONNECTED) 0] ls / [zk: node1:2181(CONNECTED) 1] quit

实操心得:ZK启动后不要立刻执行status,等10秒再查。因为zkServer.sh脚本里有个sleep 2,但实际选举可能需要5秒以上。我见过太多人看到Error contacting service就以为失败,其实是查早了。

4.3 Hadoop二进制部署与配置分发

下载Hadoop 3.3.1:

cd /opt wget https://archive.apache.org/dist/hadoop/core/hadoop-3.3.1/hadoop-3.3.1.tar.gz tar -xzf hadoop-3.3.1.tar.gz ln -s hadoop-3.3.1 hadoop

创建必要目录(三台机器都要):

mkdir -p /var/lib/hadoop/{hdfs/{namenode,datanode,journal},yarn/{log,nodemanager}} chown -R hadoop:hadoop /var/lib/hadoop

将前面配置好的core-site.xml、hdfs-site.xml、yarn-site.xml、hadoop-env.sh复制到/opt/hadoop/etc/hadoop/。特别注意hadoop-env.sh里要添加:

export HADOOP_CONF_DIR=/opt/hadoop/etc/hadoop export HADOOP_LOG_DIR=/var/log/hadoop export HADOOP_PID_DIR=/var/run/hadoop

分发配置到所有节点:

# 在node1上执行 for host in node2 node3; do scp -r /opt/hadoop/etc/hadoop/ $host:/opt/hadoop/etc/ ssh $host "chown -R hadoop:hadoop /opt/hadoop/etc/hadoop" done

4.4 HDFS HA初始化:五步走完NameNode双活

这是整个流程中最容易出错的环节,必须严格按顺序:

第一步:格式化ZooKeeper(仅在node1执行)

su - hadoop -c "/opt/hadoop/bin/hdfs zkfc -formatZK"

此命令会在ZK中创建/hadoop-ha/mycluster路径。执行后检查:

/opt/zookeeper/bin/zkCli.sh -server node1:2181 [zk: node1:2181(CONNECTED) 0] ls /hadoop-ha/mycluster # 应返回 [ActiveBreadCrumb, ActiveStandbyElectorLock]

第二步:格式化NameNode(仅在node1执行)

su - hadoop -c "/opt/hadoop/bin/hdfs namenode -format -clusterId mycluster"

注意-clusterId参数必须和hdfs-site.xml里的dfs.cluster.id一致(如果没配,默认是随机生成,但HA要求显式指定)。此命令在/var/lib/hadoop/hdfs/namenode下创建VERSION文件,里面包含clusterID=...字段。

第三步:启动JournalNode(三台都执行)

su - hadoop -c "/opt/hadoop/sbin/hadoop-daemon.sh start journalnode" # 检查进程 jps | grep JournalNode

第四步:同步NameNode元数据(仅在node2执行)

su - hadoop -c "/opt/hadoop/bin/hdfs namenode -bootstrapStandby"

此命令会从node1的NN拉取fsimage和edits日志,写入/var/lib/hadoop/hdfs/namenode。执行前确保node2的/var/lib/hadoop/hdfs/namenode目录为空,否则报错。

第五步:启动所有HDFS服务(按顺序)

# 在node1执行(启动主NN和ZKFC) su - hadoop -c "/opt/hadoop/sbin/hadoop-daemon.sh start namenode" su - hadoop -c "/opt/hadoop/sbin/hadoop-daemon.sh start zkfc" # 在node2执行(启动备NN和ZKFC) su - hadoop -c "/opt/hadoop/sbin/hadoop-daemon.sh start namenode" su - hadoop -c "/opt/hadoop/sbin/hadoop-daemon.sh start zkfc" # 在所有节点执行(启动DN和JN) su - hadoop -c "/opt/hadoop/sbin/hadoop-daemon.sh start datanode" # JN已在第三步启动,此处无需重复

验证状态:

# 查看NN状态 su - hadoop -c "/opt/hadoop/bin/hdfs haadmin -getServiceState nn1" # 应返回 active su - hadoop -c "/opt/hadoop/bin/hdfs haadmin -getServiceState nn2" # 应返回 standby # 查看ZKFC状态 su - hadoop -c "/opt/hadoop/bin/hdfs zkfc -formatZK" # 再次执行应提示已存在

常见问题:如果getServiceState返回not ready yet,说明ZKFC还没完成状态注册。等待30秒再查,或检查ZK日志/opt/zookeeper/logs/zookeeper-hadoop-server-node1.out是否有Connection refused。

4.5 YARN HA启动与验证:ResourceManager双活实战

YARN启动比HDFS简单,但有两个关键点:

启动顺序必须是:先启动ZK,再启动RM,最后启动NM

# 在node1和node2执行(启动RM) su - hadoop -c "/opt/hadoop/sbin/yarn-daemon.sh start resourcemanager" # 在所有节点执行(启动NM) su - hadoop -c "/opt/hadoop/sbin/yarn-daemon.sh start nodemanager"

验证RM状态:

su - hadoop -c "/opt/hadoop/bin/yarn rmadmin -getServiceState rm1" # node1上应为 active su - hadoop -c "/opt/hadoop/bin/yarn rmadmin -getServiceState rm2" # node2上应为 standby

手动触发故障转移测试:

# 在node1上执行(使rm1降为standby) su - hadoop -c "/opt/hadoop/bin/yarn rmadmin -transitionToStandby rm1" # 在node2上执行(使rm2升为active) su - hadoop -c "/opt/hadoop/bin/yarn rmadmin -transitionToActive rm2" # 验证 su - hadoop -c "/opt/hadoop/bin/yarn rmadmin -getServiceState rm1" # standby su - hadoop -c "/opt/hadoop/bin/yarn rmadmin -getServiceState rm2" # active

此时访问http://node2:8088(YARN Web UI),应能看到所有NodeManager在线。提交一个测试任务:

su - hadoop -c "/opt/hadoop/bin/hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.1.jar pi 10 100"

如果看到Estimated value of Pi is 3.14...,说明YARN HA工作正常。

5. 常见问题与排查技巧实录:那些让你凌晨三点还在看日志的坑

手动部署最大的价值,不是最终跑起来,而是你掌握了所有故障的排查路径。我把过去三年遇到的高频问题整理成速查表,按现象分类,附带真实日志片段和解决命令。

5.1 NameNode无法启动:ZKFC状态机卡死

现象:jps看不到NameNode进程,/opt/hadoop/logs/hadoop-hadoop-namenode-node1.log末尾反复出现:

2023-05-12 02:14:22,102 INFO ha.ZKFailoverController (ZKFailoverController.java:main(1202)) - VM settings: maxMemory = 3.0GB 2023-05-12 02:14:22,103 INFO ha.ZKFailoverController (ZKFailoverController.java:main(1203)) - STARTUP_MSG: ... 2023-05-12 02:14:23,456 INFO zookeeper.ClientCnxn (ClientCnxn.java:primeConnection(876)) - Socket connection established to node1/192.168.10.11:2181, initiating session 2023-05-12 02:14:23,462 WARN zookeeper.ClientCnxn (ClientCnxn.java:onConnected(1235)) - Session 0x0 for server node1/192.168.10.11:2181, unexpected error, closing socket connection and attempting reconnect java.io.IOException: Connection reset by peer

原因分析:ZooKeeper服务没起来,或防火墙拦截了2181端口。Connection reset by peer意味着TCP连接被对方RST,通常是服务未监听或被拦截。

排查步骤:

  1. 检查ZK进程:ps aux | grep zookeeper,确认QuorumPeerMain进程存在
  2. 检查端口监听:netstat -tuln | grep :2181,应显示LISTEN
  3. 检查防火墙:iptables -L -n | grep 2181,若存在REJECT规则,执行iptables -D INPUT -p tcp --dport 2181 -j REJECT
  4. 测试ZK连通性:echo ruok | nc node1 2181,应返回imok

终极方案:如果ZK确定正常,问题仍在,检查/opt/hadoop/etc/hadoop/hdfs-site.xml里dfs.ha.fencing.methods是否配置了sshfence,且sshfence的dfs.ha.fencing.ssh.private-key-files路径是否正确。我曾因私钥文件权限是644(应为600),导致SSH认证失败,ZKFC无限重试。

5.2 DataNode启动失败:磁盘空间与权限双重陷阱

现象:jps看不到DataNode,/opt/hadoop/logs/hadoop-hadoop-datanode-node1.log报:

2023-05-12 03:22:18,776 ERROR datanode.DataNode (LogAdapter.java:error(158)) - Exception in secureMain java.io.IOException: All directories in dfs.datanode.data.dir are invalid: [/var/lib/hadoop/hdfs/datanode]

原因分析:dfs.datanode.data.dir指向的目录不可写,或磁盘空间不足。但更隐蔽的是XFS文件系统问题——XFS默认启用projid配额,如果/var/lib/hadoop挂载时没加prjquota选项,DataNode会因无法设置project quota而拒绝启动。

排查命令:

# 检查目录权限 ls -ld /var/lib/hadoop/hdfs/datanode # 应返回 drwxr-xr-x 3 hadoop hadoop ... # 检查磁盘空间 df -h /var/lib/hadoop # 检查文件系统类型和挂载选项 mount | grep "$(df . | tail -1 | awk '{print $1}')" # 正常应显示 xfs ... prjquota ...

解决方案:

  • 如果权限问题:chown -R hadoop:hadoop /var/lib/hadoop/hdfs/datanode
  • 如果磁盘满:清理/var/log/hadoop旧日志,或扩容磁盘
  • 如果XFS配额:重新挂载mount -o remount,prjquota /var/lib/hadoop

5.3 ResourceManager Web UI打不开:端口冲突与SSL劫持

现象:curl http://node1:8088返回Connection refused,但jps显示ResourceManager进程存在。

原因分析:8088端口被其他进程占用,或YARN配置了HTTPS但没配证书。

排查步骤:

  1. 检查端口占用:lsof -i :8088,若显示其他进程,kill -9 <PID>
  2. 检查YARN配置:grep "yarn.resourcemanager.webapp.https.address" /opt/hadoop/etc/hadoop/yarn-site.xml,如果存在且值为node1:8090,说明启用了HTTPS,应访问https://node1:8090
  3. 检查SSL配置:若启用了HTTPS,确认ssl-server.xml存在且ssl.server.keystore.location路径正确

快速修复:临时禁用HTTPS,在yarn-site.xml中添加:

<property> <name>yarn.resourcemanager.webapp.https.address</name> <value></value> </property>

然后重启RM。

5.4 客户端连接失败:core-site.xml的URI陷阱

现象:在客户端机器执行hdfs dfs -ls /报:

ls: Call From client/192.168.10.20 to node1:8020 failed on connection exception: java.net.ConnectException: Connection refused

原因分析:客户端core-site.xml里fs.defaultFS配置的是hdfs://node1:8020,这是单点地址。HA模式下必须配置逻辑URIhdfs://mycluster,让客户端通过ZK查询当前active NN。

修复方法:

<!-- 错误配置 --> <property> <name>fs.defaultFS</name> <value>hdfs://node1:8020</value> </property> <!-- 正确配置 --> <

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询