资讯动态

Hadoop完全分布式+ZooKeeper+NameNode HA+YARN HA集群搭建与高可用验证实战

发布时间:2026/10/19 17:08:44 来源:尧图企业网站定制
1. 为什么这套组合拳值得每个大数据从业者死磕刚入行那会儿我觉得伪分布式跑通了就算入门了直到第一次面对生产环境的机房断电演练才发现单点故障有多要命。hadoop完全分布式zookeeper集群NameNode HAyarn HA这套组合说白了就是把Hadoop从能跑推到敢用的必经之路。它解决的核心问题只有一个当关键进程挂掉时整个集群不能跟着陪葬。这套方案适合谁如果你已经能独立搭建伪分布式环境能看懂core-site.xml和hdfs-site.xml的基本配置但一提到JournalNode、ZKFC、ResourceManager状态切换就发怵那这篇内容就是写给你的。我会把每个组件的角色、每个配置项背后的意图、以及我踩过的坑全部摊开来讲。先给个全局认知完全分布式解决的是数据分散存储和计算的问题ZooKeeper解决的是分布式协调的问题NameNode HA解决的是元数据单点的问题YARN HA解决的是资源调度单点的问题。四者叠加才构成一个具备基础高可用能力的大数据平台底座。缺了任何一环你的集群在真实故障面前都是纸糊的。我见过太多人把HA配好了但从来没真正触发过主备切换也不知道切换后客户端要做什么。这种配置层面的HA毫无意义。所以下面我会重点讲怎么验证HA真的生效以及切换过程中哪些细节会让你前功尽弃。2. 集群规划与基础环境准备2.1 节点角色分配与硬件考量先定节点。我建议至少5台机器3台用于ZooKeeper和JournalNode2台作为NameNode和ResourceManager的主备。如果资源紧张可以压缩到3台但ZooKeeper必须保持奇数节点这是Paxos类协议的基本要求。节点别名角色分配最低配置node01NameNode(Active)、ResourceManager(Active)、ZKFC、ZK、JN4C8Gnode02NameNode(Standby)、ResourceManager(Standby)、ZKFC、ZK、JN4C8Gnode03DataNode、NodeManager、ZK、JN2C4Gnode04DataNode、NodeManager2C4Gnode05DataNode、NodeManager2C4G注意JournalNode至少需要3台且必须是奇数。它存储的是NameNode的EditLog相当于元数据变更的账本。如果JN挂到只剩1台NameNode会停止写入整个HDFS变成只读。硬件上有个容易忽略的点NameNode对内存的需求远大于DataNode。因为整个文件系统的元数据都加载在内存里1000万个文件大约消耗3GB堆内存。所以node01和node02的内存不能省否则GC停顿会让你误以为是HA切换了。2.2 系统层基础配置所有节点统一执行以下操作别偷懒我见过因为时间不同步导致ZK选主失败的案例。# 关闭防火墙内网环境 systemctl stop firewalld systemctl disable firewalld # 设置主机名以node01为例 hostnamectl set-hostname node01 # 配置hosts所有节点保持一致 cat /etc/hosts EOF 192.168.1.101 node01 192.168.1.102 node02 192.168.1.103 node03 192.168.1.104 node04 192.168.1.105 node05 EOF # 时间同步 yum install -y chrony systemctl start chronyd systemctl enable chronyd # 关闭swapHadoop对内存交换极其敏感 swapoff -a sed -i /swap/s/^/#/ /etc/fstabJDK选择上Hadoop 3.x推荐JDK 8或JDK 11。我实测下来JDK 11在G1 GC下表现更稳但部分老版本Hadoop对JDK 11支持不完整所以生产环境建议JDK 8省心。# 配置JDK环境变量 cat /etc/profile EOF export JAVA_HOME/usr/local/jdk1.8.0_381 export PATH$JAVA_HOME/bin:$PATH EOF source /etc/profile2.3 SSH免密与集群分发脚本NameNode需要能免密登录到所有节点这是启动和停止集群的前提。# 在node01生成密钥对 ssh-keygen -t rsa -N -f ~/.ssh/id_rsa # 分发公钥到所有节点 for i in {101..105}; do ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.1.$i done写一个xsync脚本后面分发配置文件全靠它#!/bin/bash if [ $# -lt 1 ]; then echo Usage: xsync file... exit 1 fi for host in node01 node02 node03 node04 node05; do if [ $host ! $(hostname) ]; then rsync -av --delete $ $host:$PWD fi done提示rsync的--delete参数会删除目标端多余文件分发目录时慎用分发单个文件时没问题。3. ZooKeeper集群搭建与核心参数调优3.1 为什么HA离不开ZooKeeper很多人把ZooKeeper当成配HA时顺便装的东西这是误解。在Hadoop HA架构里ZK承担三个关键职责Active节点选举、状态存储、故障通知。ZKFCZooKeeper Failover Controller会持续向ZK发送心跳谁先抢到/hadoop-ha/nameservice/ActiveStandbyElectorLock这个临时节点谁就是Active。一旦Active失联临时节点自动消失Standby的ZKFC收到通知后发起新一轮选举。所以ZK集群的稳定性直接决定HA的可靠性。ZK挂了HA就瞎了。3.2 ZooKeeper配置实操# 解压到/opt/module tar -zxvf apache-zookeeper-3.8.4-bin.tar.gz -C /opt/module/ cd /opt/module mv apache-zookeeper-3.8.4-bin zookeeper # 创建数据目录和日志目录 mkdir -p /opt/module/zookeeper/zkData mkdir -p /opt/module/zookeeper/zkLogs # 配置zoo.cfg cat /opt/module/zookeeper/conf/zoo.cfg EOF tickTime2000 initLimit10 syncLimit5 dataDir/opt/module/zookeeper/zkData dataLogDir/opt/module/zookeeper/zkLogs clientPort2181 maxClientCnxns60 autopurge.snapRetainCount3 autopurge.purgeInterval1 server.1node01:2888:3888 server.2node02:2888:3888 server.3node03:2888:3888 EOF # 在node01上创建myid echo 1 /opt/module/zookeeper/zkData/myidtickTime是ZK的基本时间单元initLimit10意味着Follower启动时最多等待10个tick20秒与Leader同步。如果集群数据量大这个值要调大否则Follower会因为超时被踢出。autopurge这两个参数我强烈建议加上。ZK的snapshot和事务日志会无限增长我见过一个跑了半年的ZKdataDir占了80GB最后磁盘满了导致整个集群不可用。分发到node02和node03分别修改myid为2和3xsync /opt/module/zookeeper # 在node02执行 echo 2 /opt/module/zookeeper/zkData/myid # 在node03执行 echo 3 /opt/module/zookeeper/zkData/myid3.3 启动验证与常见坑# 三个节点分别启动 zkServer.sh start # 验证状态 zkServer.sh status # 应该看到一台leader两台follower注意如果三台都显示standalone说明没读到集群配置检查zoo.cfg里server.x的IP和myid是否对应。如果一直选不出leader先看时间是否同步再看2888/3888端口是否被占用。我踩过最坑的一次是dataDir路径写错ZK在错误路径下创建了myid导致每台机器都认为自己是1号选主永远失败。所以启动前一定确认myid文件在dataDir指定的目录下。4. Hadoop完全分布式与HA配置全流程4.1 core-site.xml定义集群身份configuration !-- 指定HDFS的nameservice这是HA的核心标识 -- property namefs.defaultFS/name valuehdfs://mycluster/value /property !-- 临时目录NameNode和DataNode共用 -- property namehadoop.tmp.dir/name value/opt/module/hadoop/data/tmp/value /property !-- ZooKeeper集群地址ZKFC和RM都依赖 -- property nameha.zookeeper.quorum/name valuenode01:2181,node02:2181,node03:2181/value /property /configurationfs.defaultFS写mycluster而不是具体主机名这是HA的关键。客户端拿到这个逻辑名后会通过dfs.nameservices找到对应的NameNode列表再逐个尝试连接。如果写死node01那HA就形同虚设。4.2 hdfs-site.xmlNameNode HA核心配置configuration !-- nameservice逻辑名与core-site对应 -- property namedfs.nameservices/name valuemycluster/value /property !-- 两个NameNode的别名 -- property namedfs.ha.namenodes.mycluster/name valuenn1,nn2/value /property !-- nn1的RPC和HTTP地址 -- property namedfs.namenode.rpc-address.mycluster.nn1/name valuenode01:8020/value /property property namedfs.namenode.http-address.mycluster.nn1/name valuenode01:9870/value /property !-- nn2的RPC和HTTP地址 -- property namedfs.namenode.rpc-address.mycluster.nn2/name valuenode02:8020/value /property property namedfs.namenode.http-address.mycluster.nn2/name valuenode02:9870/value /property !-- JournalNode地址列表 -- property namedfs.namenode.shared.edits.dir/name valueqjournal://node01:8485;node02:8485;node03:8485/mycluster/value /property !-- 故障转移代理类客户端靠它找到Active -- property namedfs.client.failover.proxy.provider.mycluster/name valueorg.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider/value /property !-- 隔离机制防止脑裂 -- property namedfs.ha.fencing.methods/name valuesshfence/value /property property namedfs.ha.fencing.ssh.private-key-files/name value/root/.ssh/id_rsa/value /property !-- 自动故障转移 -- property namedfs.ha.automatic-failover.enabled/name valuetrue/value /property /configurationdfs.ha.fencing.methods这个配置极其重要。当ZKFC决定切换时它必须先确保旧的Active真的死了否则两个NameNode同时写EditLog会导致数据损坏。sshfence会通过SSH登录到旧Active节点执行kill命令。如果SSH不通切换会失败集群进入无Active状态。提示生产环境建议用shell或自定义fencing脚本sshfence在SSH服务异常时会成为单点。4.3 yarn-site.xmlResourceManager HA配置configuration !-- 开启RM HA -- property nameyarn.resourcemanager.ha.enabled/name valuetrue/value /property property nameyarn.resourcemanager.cluster-id/name valueyarn-cluster/value /property property nameyarn.resourcemanager.ha.rm-ids/name valuerm1,rm2/value /property property nameyarn.resourcemanager.hostname.rm1/name valuenode01/value /property property nameyarn.resourcemanager.hostname.rm2/name valuenode02/value /property !-- ZK存储RM状态 -- property nameyarn.resourcemanager.zk-address/name valuenode01:2181,node02:2181,node03:2181/value /property property nameyarn.resourcemanager.recovery.enabled/name valuetrue/value /property property nameyarn.resourcemanager.store.class/name valueorg.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore/value /property !-- NodeManager辅助服务 -- property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property /configurationyarn.resourcemanager.recovery.enabled必须为true否则RM切换后之前提交的任务状态全丢。ZKRMStateStore把应用状态存在ZK里新Active RM启动后能从ZK恢复。4.4 workers与分发配置# workers文件列出所有DataNode和NodeManager节点 cat /opt/module/hadoop/etc/hadoop/workers EOF node03 node04 node05 EOF # 分发Hadoop目录到所有节点 xsync /opt/module/hadoop5. 集群初始化与HA切换验证5.1 启动顺序不能乱启动顺序错了会出现各种诡异问题。正确顺序是ZK → JournalNode → NameNode → ZKFC → DataNode → ResourceManager → NodeManager。# 1. 启动ZK三个节点分别执行 zkServer.sh start # 2. 启动JournalNodenode01/02/03 hdfs --daemon start journalnode # 3. 格式化HDFS仅在node01执行一次 hdfs namenode -format # 4. 启动node01的NameNode hdfs --daemon start namenode # 5. 在node02同步元数据 hdfs namenode -bootstrapStandby # 6. 启动node02的NameNode hdfs --daemon start namenode # 7. 格式化ZKFC仅在node01执行一次 hdfs zkfc -formatZK # 8. 启动ZKFCnode01和node02 hdfs --daemon start zkfc # 9. 启动DataNodenode03/04/05 hdfs --daemon start datanode # 10. 启动YARN start-yarn.sh # node02手动启动RM yarn --daemon start resourcemanager注意hdfs zkfc -formatZK只能在第一次搭建时执行。如果重复执行会清空ZK里的HA状态导致两个NameNode都变成Standby。5.2 验证NameNode HA真的生效别只看Web UI显示Active/Standby就完事要实际触发一次切换。# 查看当前状态 hdfs haadmin -getServiceState nn1 hdfs haadmin -getServiceState nn2 # 手动切换 hdfs haadmin -transitionToStandby nn1 hdfs haadmin -transitionToActive nn2 # 验证切换后HDFS仍可读写 hdfs dfs -mkdir /ha-test hdfs dfs -put /etc/profile /ha-test/ hdfs dfs -cat /ha-test/profile | head -5如果切换后读写正常说明HA配置成功。如果报Connection refused检查dfs.client.failover.proxy.provider是否配错。5.3 验证YARN HA# 查看RM状态 yarn rmadmin -getServiceState rm1 yarn rmadmin -getServiceState rm2 # 手动切换 yarn rmadmin -transitionToStandby rm1 yarn rmadmin -transitionToActive rm2 # 提交一个任务验证 yarn jar /opt/module/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar pi 2 4任务能正常跑完说明RM切换后状态恢复没问题。6. 常见故障排查与避坑指南6.1 HA切换失败排查表现象可能原因排查方法两个NN都是StandbyZKFC未启动或ZK连接失败jps查看ZKFC进程检查ha.zookeeper.quorum切换后HDFS只读JournalNode不足半数hdfs dfsadmin -report查看JN状态脑裂两个Activefencing未生效检查dfs.ha.fencing.methods和SSH免密RM切换后任务丢失recovery未开启确认yarn.resourcemanager.recovery.enabledtrueZKFC反复重启时间不同步chronyc sources检查时间源6.2 我踩过的三个深坑第一个坑hadoop.tmp.dir用了默认值。默认是/tmp/hadoop-${user.name}而/tmp在某些系统上会被定期清理。结果某次重启后NameNode的元数据全没了。所以一定要改成持久化路径并且确保该路径在所有节点上存在且权限正确。第二个坑JournalNode磁盘写满。JN的EditLog会持续增长如果没配清理策略磁盘满了之后NameNode无法写入整个HDFS挂起。解决方案是监控JN目录大小或者配置dfs.journalnode.edits.dir到独立的大容量磁盘。第三个坑ZKFC的SSH fencing超时。默认SSH连接超时时间较短网络抖动时fencing失败切换卡住。可以在dfs.ha.fencing.ssh.connect-timeout里调大超时时间比如30000毫秒。6.3 日常运维检查清单每天检查ZK集群是否有LeaderzkServer.sh status每周检查JournalNode磁盘使用率超过70%要清理每月手动触发一次HA切换确保fencing和恢复机制正常关注NameNode的Heap使用率超过80%要考虑扩容或优化7. 性能调优与扩展建议7.1 NameNode JVM调优NameNode的GC停顿直接影响HA切换速度。我建议用G1 GC并设置合理的堆大小。# 在hadoop-env.sh中配置 export HDFS_NAMENODE_OPTS-Xmx8g -Xms8g -XX:UseG1GC -XX:MaxGCPauseMillis200 -XX:PrintGCDetails -Xloggc:/opt/module/hadoop/logs/nn-gc.log-Xmx和-Xms设成一样避免堆动态扩展带来的抖动。MaxGCPauseMillis200是目标值G1会尽量达成但不是硬保证。7.2 ZooKeeper会话超时调整默认tickTime2000会话超时是2*tickTime4秒。在网络不稳定的环境里4秒太短容易误判节点死亡。可以在zoo.cfg里加maxSessionTimeout60000 minSessionTimeout4000同时在Hadoop侧调整ha.zookeeper.session-timeout.ms保持两边一致。7.3 后续扩展方向这套架构跑稳之后可以往两个方向扩展一是加HDFS Federation用多个nameservice分担元数据压力二是引入Router-based Federation实现跨集群的透明访问。不过那是另一个话题了先把当前这套的HA切换练熟再说。我个人在实际操作中的体会是HA配置本身不难难的是验证它真的能在故障时生效。很多人配完看到Web UI显示Active/Standby就以为万事大吉结果真出故障时发现fencing没配、ZK连不上、JN磁盘满了。所以我的建议是每季度至少做一次故障演练手动kill掉Active NameNode观察集群是否在30秒内完成切换客户端是否无感知。这个习惯比任何配置都重要。

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

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

免费获取报价 →
↑