ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Hadoop2高可用集群搭建实战:从规划到排错的全流程解析

Hadoop2高可用集群搭建实战:从规划到排错的全流程解析 提到Hadoop集群搭建尤其是Hadoop2这一代很多人第一反应是“网上教程多的是照着敲一遍就行”但真正落到自己服务器上总会碰到进程起不来、NameNode切换失败、YARN跑任务卡死这类问题。这篇博文不打算重复那些贴了又贴的命令清单而是把一个完整的Hadoop2集群从规划到上线、从配置到排查的过程拆开讲包括我实际踩过的坑和最终验证可用的参数组合。无论你是准备搭一个生产可用的HA集群还是只想在实验室环境里把HDFS、YARN的协作关系彻底搞明白这篇内容都能给你一个比较扎实的参考。1. 整体设计与集群搭建前的关键考量1.1 为什么要搭Hadoop2集群很多朋友会问Hadoop都发展这么多代了为什么还要回头折腾2.x这里要先说清楚一个背景——Hadoop2是HDFS Federation和HA机制真正成型的一代也是YARN从MRv1里独立出来的起点。Hadoop1里JobTracker又要管调度又要管任务执行单点压力太大而Hadoop3虽然在性能、稳定性、纠删码等方面做了不少升级但大量企业内部存量系统和周边组件Hive、Spark、HBase的某些版本依然跑在2.x上尤其是2.7、2.8、2.9这几个版本生态兼容性非常成熟。这篇文章选择Apache Hadoop 2.x来搭建还有一个更实际的原因它能把“分布式系统的基础组件如何协作”这件事暴露得足够清楚。你会接触JournalNode、ZooKeeper、FailoverController、YARN ResourceManager HA等一批核心概念这些机制在后来的Hadoop3中仍然保留。换句话说把Hadoop2集群彻底搞明白后面上手任何一套分布式存储与计算架构都会轻松很多。而且很多人在搜索“spark集群搭建”时其实也绕不开Hadoop2——Spark任务跑起来之后要读写HDFS要由YARN来分配资源底层还是得先把这套基础设施立起来。1.2 集群角色规划从“半分布式”到“高可用”的权衡搭建集群之前先要把角色规划清楚。很多教程一上来就给你三台机器或者五台机器但没解释为什么要这个数量。我的建议是学习环境最少三台机器生产环境按高可用标准至少五台。原因很简单——HDFS NameNode在Hadoop2里要做到自动故障转移就需要让两个NameNode节点都保持“热备”状态同时还需要三个JournalNode节点来同步编辑日志ZooKeeper集群至少需要三个节点来选举否则ZooKeeper自身就成单点了。所以一个典型的高可用集群规划是这样节点运行角色说明node1NameNode(Active)、ResourceManager、ZooKeeper、JournalNode主控节点node2NameNode(Standby)、ResourceManager、ZooKeeper、JournalNode备用主控节点node3ZooKeeper、JournalNode、DataNode、NodeManager协调与存储节点node4DataNode、NodeManager计算与存储节点node5DataNode、NodeManager计算与存储节点这里有个常见的误区以为ResourceManager和NameNode必须绑在一起。其实它们可以分开部署生产环境往往会把YARN的ResourceManager单独放到两台机器上避免和NameNode争抢内存。但对于大部分中小规模集群把ZK、NameNode、ResourceManager混部在三到五个节点上是很常见而且划算的做法。关键是要控制好内存分配别让一个节点上跑的进程把内存吃满。我自己的实验环境只有四台物理机内存分别是32G、16G、16G、16G。我选择把node1、node2作为主控节点node3作为协调与存储节点node4作为纯存储计算节点。进程分配上ZooKeeper三个节点分别部署在node1、node2、node3JournalNode也放在相同位置DataNode和NodeManager则部署全部四台机器。这样的好处是每一类组件都有冗余同时又没有把本可以复用的资源浪费掉。1.3 版本选型Apache Hadoop 2.x 到底选哪个确定好架构下一步是选具体版本。Apache Hadoop 2.x的最终版本是2.10.x社区还出了2.10.2这样一个相对稳定的收尾版本。如果你不是为了复现老项目我建议直接选2.10.2它修复了大量堆内存泄漏、RPC超时、HDFS性能方面的问题同时保留了完整的2.x API兼容性。很多公司线上跑的其实也是2.7或2.8系列但新搭建的集群没必要再选这些老版本因为2.10.2在安全补丁上明显更完整。还需要确认配套软件的版本JDK必须用Java 8Oracle JDK 8u202或OpenJDK 8都可以这是Hadoop2官方构建时使用的Java版本用JDK 11以上会遇到RPC协议兼容问题反正我实测过用高版本JDK编译过的Hadoop包会出现各种莫名其妙的加密算法异常。ZooKeeper选用3.4.14这个版本在Hadoop2时代是经过大量生产验证的ZooKeeper 3.5以上虽然可以用但和Hadoop2的HDFS HA客户端配合时会遇到“四字命令需显式开启”这类额外配置没必要给自己加戏。2. 核心组件与关键配置原理解析2.1 HDFS HA的工作机制为什么需要JournalNode和ZooKeeper配置Hadoop2 HA之前一定要先理解HDFS的EditLog同步机制否则配置项写到一半会犯迷糊。在单NameNode时代NameNode把每一次元数据修改都追加写入本地磁盘的edits文件定期和fsimage合并形成一个checkpoint。一旦NameNode宕机只能靠管理员手动恢复SecondaryNameNode的元数据恢复时间动辄几小时。Hadoop2引入了QJMQuorum Journal Manager方案让Active NameNode每做一次修改都同时写入多个JournalNode节点的共享日志目录只要多数派一般是3个里写2个返回成功就认为这次修改已经提交。Standby NameNode做的事情是持续从JournalNode上读取edits合并进自己的内存元数据从而保证Standby的命名空间和Active实时同步。当Active宕机时借助ZooKeeper的临时节点和选举机制ZooKeeper会检测到Active节点失联然后通知Standby切换为Active。为了不发生“双主”脑裂Hadoop2还引入了Fencing机制切换前会调用配置好的fence脚本把旧的Active强制隔离比如通过SSH执行kill命令或者直接调用真实机器的IPMI断电接口。这套机制复杂但你只要抓住了“多数派日志同步 选主 隔离旧主”这条主线所有配置项就都对应得上了。2.2 ZooKeeper在集群中的角色与配置要点ZooKeeper在这个架构里的角色简单说就是一个分布式协调器。它本质上是维护一个层次化的数据节点树并提供临时节点的能力。Active NameNode会在ZooKeeper里创建一个类似于/hadoop-ha/mycluster/ActiveBreadCrumb的临时节点当NameNode进程异常退出或者网络分区发生ZooKeeper的会话超时机制会发现这个临时节点已经过期这时Standby节点通过竞争创建另一个临时节点谁创建成功谁就成为新的Active。配置ZooKeeper的时候有几个容易被忽略的点一是myid文件必须放在data目录下而且每台机器的内容不能相同二是zoo.cfg里的server.1host:2888:3888这类配置前面的端口是集群内部数据同步端口后面的端口是选举端口如果系统防火墙没放行这两个端口整个ZooKeeper集群虽然在但永远选不出Leader三是maxClientCnxns参数不要设成0否则会限制Hadoop的ZooKeeper客户端连接数。很多教程会把ZooKeeper和Hadoop的配置文件分开写这是对的。我见过有人图省事把ZK集群各节点的IP写错结果HDFS自动故障转移怎么测都失败最后用zkCli.sh连上去发现连Leader都没有。记住ZooKeeper集群的健康是一切自动切换的前提。2.3 YARN资源调度模型除了MR任务还能跑什么Hadoop2最被低估的设计其实是YARN它把集群资源的分配从MapReduce里彻底抽离出来变成了一套通用的资源调度框架。ResourceManager全局管理所有资源NodeManager负责每个节点上的资源监控与任务容器启动ApplicationMaster则负责单个应用程序的任务拆分、资源申请和进度汇报。这个模型的意义在于MapReduce不再是唯一能跑在集群上的计算框架Spark、Flink、Tez都可以通过实现YARN的接口来共享同一套HDFS存储和同一批节点资源。在做集群配置时需要把握好YARN的几个核心参数yarn.nodemanager.resource.memory-mb决定单个节点上NodeManager可用的总物理内存yarn.scheduler.maximum-allocation-mb决定单个任务容器能申请的最大内存这两个值如果设置过大或过小都会出现资源浪费或任务OOM。我见过不少集群DataNode内存和NodeManager内存互相“顶牛”直接把物理机撑爆。后面第三部分我会给出我验证过的一套配置组合配套说明怎么算这些值。3. 完整实操从零搭建一个Hadoop2高可用集群3.1 基础环境初始化JDK、SSH免密、hosts映射、时钟同步强烈建议先把所有服务器的hostname和/etc/hosts一次性配好。我不止一次见到有人因为hostname和/etc/hosts不一致导致NameNode和DataNode互相认识不了DataNode进程起来了但一直没注册到NameNode。这里我给一个标准做法# 每台机器都要配注意替换成实际IP cat /etc/hosts EOF 192.168.1.10 node1 192.168.1.11 node2 192.168.1.12 node3 192.168.1.13 node4 EOF # 设置hostname以node1为例 hostnamectl set-hostname node1接下来安装JDK 8。我用的是OpenJDK 8直接系统包管理器装就行或者从厂商下载tar包解压到/usr/local/java。安装完成之后检查一下java -version # 期望输出 java version 1.8.0_xxx然后配置SSH免密登录。这是集群最基础但非常烦人的一步。建议在所有机器上都执行一次ssh-keygen -t rsa生成密钥然后把每台机器的公钥都追加到authorized_keys中。简单起见我一般先把node1的公钥分发到所有机器再从node2分发一次确保双向都免密。配置好之后一定要测试从node1执行ssh node2 date不输密码才算完成。注意这里的坑如果.ssh目录权限是777SSH会直接拒绝使用密钥必须保证.ssh是700、authorized_keys是600。再一个是时钟同步。Hadoop内部很多通信依赖时间戳如果各节点时间差超过一定阈值ZooKeeper会误判心跳超时HDFS租约会被错误回收。生产环境用NTP服务统一对时实验环境可以简单用crontab定时执行ntpdate ntp.aliyun.com。这一步虽然不起眼但往往就是集群“偶尔正常、偶尔抽风”的根源。3.2 ZooKeeper集群安装与配置ZooKeeper的安装相对简单但也最容易出问题。把zookeeper-3.4.14.tar.gz解压到/opt/zookeeper然后修改conf/zoo.cfgtickTime2000 dataDir/data/zookeeper clientPort2181 initLimit10 syncLimit5 server.1node1:2888:3888 server.2node2:2888:3888 server.3node3:2888:3888然后在每台机器的/data/zookeeper目录下创建myid文件# node1上写 1node2上写 2node3上写 3 echo 1 /data/zookeeper/myid启动方式就是到bin目录执行./zkServer.sh start。启动后一定要用./zkServer.sh status确认角色其中一台会是leader另外两台是follower。很多教程跳过了这个验证直接往下配Hadoop结果后面排查HDFS HA时才发现ZK压根没成功组队。注意如果status命令显示连接失败先检查2181端口是否被防火墙拦截再检查另外两个端口2888、3888是否也能互通。3.3 Hadoop安装与目录规划Hadoop二进制包解压到/opt/hadoop后建议创建专门的目录/data/hadoop用于HDFS数据存储/data/journal用于JournalNode日志存储/data/namenode用于NameNode元数据/data/tmp用于临时文件。把这些目录分开一是避免系统盘写满二是后续扩容或换盘时不会牵连到NameNode元数据。每台机器都要设置环境变量在/etc/profile里添加export HADOOP_HOME/opt/hadoop export PATH$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin export HADOOP_CONF_DIR$HADOOP_HOME/etc/hadoop需要格外注意的是JAVA_HOME也要导出。Hadoop的脚本会通过JAVA_HOME去找java但不是所有版本的脚本都能自动探测到路径。我建议直接把JAVA_HOME和HADOOP_HOME写死避免系统同时存在多个JDK时脚本挑错版本。3.4 核心配置文件逐个拆解这里开始进入配置的“重头戏”。所有配置都在/opt/hadoop/etc/hadoop目录下。先把workers文件写好2.x里叫slaves2.10里已经改成workers不过兼容旧名称# workers node1 node2 node3 node4然后逐项配置。先看core-site.xmlconfiguration property namefs.defaultFS/name valuehdfs://mycluster/value /property property namehadoop.tmp.dir/name value/data/tmp/value /property property nameha.zookeeper.quorum/name valuenode1:2181,node2:2181,node3:2181/value /property /configuration这里fs.defaultFS用逻辑名称mycluster而不是固定指向某一个NameNode。这个逻辑名字会在hdfs-site.xml里映射到两个真实节点。用逻辑名称的好处是客户端访问HDFS时不感知哪个NameNode是Active。ha.zookeeper.quorum则告诉HDFS客户端和NameNode进程到哪里去找ZooKeeper。接下来是hdfs-site.xml这套配置是所有配置里最考验理解力的configuration property namedfs.nameservices/name valuemycluster/value /property property namedfs.ha.namenodes.mycluster/name valuenn1,nn2/value /property property namedfs.namenode.rpc-address.mycluster.nn1/name valuenode1:8020/value /property property namedfs.namenode.rpc-address.mycluster.nn2/name valuenode2:8020/value /property property namedfs.namenode.http-address.mycluster.nn1/name valuenode1:50070/value /property property namedfs.namenode.http-address.mycluster.nn2/name valuenode2:50070/value /property property namedfs.namenode.shared.edits.dir/name valueqjournal://node1:8485;node2:8485;node3:8485/mycluster/value /property property namedfs.journalnode.edits.dir/name value/data/journal/value /property property namedfs.ha.automatic-failover.enabled/name valuetrue/value /property 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.fencing.ssh.connect-timeout/name value30000/value /property property namedfs.ha.fencing.ssh.known-hosts-file/name value/root/.ssh/known_hosts/value /property property namedfs.replication/name value2/value /property property namedfs.namenode.name.dir/name valuefile:///data/namenode/value /property property namedfs.datanode.data.dir/name valuefile:///data/hadoop/value /property property namedfs.blocksize/name value134217728/value /property property namedfs.namenode.handler.count/name value100/value /property /configuration重点解释几个容易理解错的配置项。dfs.ha.namenodes.mycluster定义了这个nameservice下有两个NameNode逻辑ID分别是nn1和nn2后面的IP映射都围绕这两个ID展开。dfs.namenode.shared.edits.dir用的是qjournal协议三个JournalNode通过分号分隔这个地址表示所有NameNode共享的edit log存储位置而不是某个单独目录。dfs.ha.fencing.methods选的是sshfence它会在切换时通过SSH登录到旧的Active节点执行类似kill -9的操作把老进程杀掉如果配置不正确切换时会出现“brain split”也就是两个NameNode同时认为自己是Active这是极其危险的情况。dfs.replication我设为2是因为实验环境只有4个DataNode副本数为2能节省空间又不至于完全失去冗余生产环境一般保持3。yarn-site.xml的配置决定了ResourceManager的高可用和NodeManager的资源限制configuration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property property nameyarn.nodemanager.aux-services.mapreduce_shuffle.class/name valueorg.apache.hadoop.mapred.ShuffleHandler/value /property property nameyarn.resourcemanager.ha.enabled/name valuetrue/value /property property nameyarn.resourcemanager.cluster-id/name valueyarn-ha-cluster/value /property property nameyarn.resourcemanager.ha.rm-ids/name valuerm1,rm2/value /property property nameyarn.resourcemanager.hostname.rm1/name valuenode1/value /property property nameyarn.resourcemanager.hostname.rm2/name valuenode2/value /property property nameyarn.resourcemanager.webapp.address.rm1/name valuenode1:8088/value /property property nameyarn.resourcemanager.webapp.address.rm2/name valuenode2:8088/value /property property nameyarn.resourcemanager.zk-address/name valuenode1:2181,node2:2181,node3:2181/value /property property nameyarn.nodemanager.resource.memory-mb/name value8192/value /property property nameyarn.scheduler.maximum-allocation-mb/name value4096/value /property property nameyarn.scheduler.minimum-allocation-mb/name value512/value /property /configurationyarn.resourcemanager.ha.enabled被设为true后ResourceManager同样依赖ZooKeeper完成选主yarn.resourcemanager.zk-address就是告诉RM去哪里竞选。注意ResourceManager的HA不像HDFS那样需要JournalNode它直接把状态写入ZooKeeper所以配置文件相对简洁。yarn.nodemanager.resource.memory-mb这个值我填的是8192意思是每个NodeManager最多管理8G物理内存给YARN容器并非node上物理内存的总额。如果你的机器是16G内存还要跑DataNode和系统服务这个值可以适当调低到6G左右。容器内存的上下限也要和总内存匹配maximum-allocation-mb设4096表示单个任务最多要4Gminimum-allocation-mb设512表示一个任务至少会占512M这样YARN在做资源分配时粒度合理不会出现一个“贪心”容器把整台机器内存占光的情况。mapred-site.xml相对简单主要是把MapReduce框架绑定到YARN上configuration property namemapreduce.framework.name/name valueyarn/value /property property namemapreduce.jobhistory.address/name valuenode1:10020/value /property property namemapreduce.jobhistory.webapp.address/name valuenode1:19888/value /property /configuration3.5 集群初始化与首次启动配置文件写完接下来按顺序初始化。第一次启动前有一个关键动作在其中一个NameNode节点计划作为主NameNode的节点上执行格式化。如果是HA集群只需要在nn1这台机器上执行一次hdfs namenode -format格式化完成之后要把nn1的元数据同步给nn2方法有两类比较传统的是先启动nn1等nn2用hdfs namenode -bootstrapStandby自动从nn1拉取元数据也可以直接把nn1上/data/namenode目录的内容复制到nn2对应目录。我推荐用hdfs namenode -bootstrapStandby因为它能保证两边的fsimage和edits对齐。注意执行这个命令之前nn2上的NameNode进程不能启动否则端口被占会报错。ZooKeeper里也要初始化HA状态执行hdfs zkfc -formatZK这个命令会在ZooKeeper中创建/hadoop-ha/mycluster节点。如果漏了这步NameNode就算起来也无法参与自动故障转移。接下来启动的顺序很重要先是JournalNode再是NameNode。有一个很容易踩的坑start-dfs.sh脚本默认会把JournalNode也拉起来但有时候因为之前启动过导致状态残留我还是习惯手动逐个启动彻底可控。推荐手动启动的关键步骤# 在所有JournalNode节点上执行这里是node1、node2、node3 /opt/hadoop/sbin/hadoop-daemon.sh start journalnode # 在node1上启动NameNode并格式化为Active /opt/hadoop/sbin/hadoop-daemon.sh start namenode # 在node2上启动Standby NameNode /opt/hadoop/sbin/hadoop-daemon.sh start namenode # 在node1、node2上启动故障转移控制器ZKFC /opt/hadoop/sbin/hadoop-daemon.sh start zkfc # 在所有节点上启动DataNode /opt/hadoop/sbin/hadoop-daemon.sh start datanode # 在node1上启动ResourceManagernode2上启动ResourceManagerHA方式 /opt/hadoop/sbin/yarn-daemon.sh start resourcemanager # 在所有节点启动NodeManager /opt/hadoop/sbin/yarn-daemon.sh start nodemanager启动完成后分别在每台机器上执行jps命令确认进程。node1上应看到NameNode、DFSZKFailoverController、ResourceManager、JournalNodenode2上应看到NameNode、DFSZKFailoverController、ResourceManager、JournalNodenode3上应看到DataNode、NodeManager、JournalNodenode4和node5上则只有DataNode和NodeManager。如果你在node4、node5上意外看到了NameNode或ResourceManager多半是配置文件没同步或者workers文件写错了。然后用一行命令验证HDFS和YARN的基本状态hdfs dfsadmin -report hdfs haadmin -getAllServiceState yarn node -listhdfs haadmin -getAllServiceState能输出两个NameNode的状态一个active、一个standby是最理想的情况。如果两个都是standby说明ZKFC没有正常工作如果两个都是active赶紧检查fencing相关配置这已经是脑裂状态了。YARN同样可以用yarn rmadmin -getServiceState rm1来查RM状态。3.6 跑一个MapReduce任务验证全链路集群起来不是终点必须实际提交任务验证HDFS和YARN能用。一个最经典的验证方式是跑Hadoop自带的WordCount。先准备数据hdfs dfs -mkdir -p /test/input echo hello world hello hadoop hadoop hdfs yarn mapreduce | hdfs dfs -put - /test/input/word.txt然后跑示例Jar这是每次运维都要随身携带的技能hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.10.2.jar wordcount /test/input /test/output如果任务成功输出目录下会有_SUCCESS文件。之后在YARN的Web UInode1:8088或node2:8088能看到一个Finished的application记录。这件事的意义是打通了完整的链路客户端通过逻辑名称访问HDFSNameNode根据dfs.client.failover.proxy.provider.mycluster找到Active节点执行文件读写计算任务由ResourceManager启动ApplicationMaster再由ApplicationMaster向NodeManager申请容器执行Map和Reduce。4. 集群搭建中的常见问题与排查技巧4.1 进程起来了但DataNode一直显示“No live nodes”这可能是Hadoop新手遇到过最多的一个问题。jps能看到DataNode进程但hdfs dfsadmin -report里就是没有活节点。排查顺序有讲究先看/data/hadoop目录下DataNode的日志通常在$HADOOP_HOME/logs或$HADOOP_LOG_DIR下找到hadoop-hadoop-datanode-xxx.log打开后搜索ERROR或WARN。最常见的原因有两类一类是dfs.datanode.data.dir指定的目录不存在或没有写权限DataNode会反复尝试初始化失败另一类是DataNode的clusterID和NameNode不一致。什么是clusterID格式化NameNode时会在元数据目录下生成一个current/VERSION文件里面记录clusterIDDataNode第一次启动时也会生成本地的clusterID然后注册到NameNode。如果你把之前格式化过的NameNode元数据目录换了DataNode的clusterID就匹配不上了。解决办法是删除DataNode数据目录下的current目录让它重新初始化但前提是HDFS里没有重要数据。4.2 NameNode状态一直处于standby或切换失败搭建HA集群时发现NameNode始终不能变active这是最让人头大的问题。第一步先检查ZooKeeper用zkCli.sh -server node1:2181连进ZooKeeperls /hadoop-ha/mycluster看节点是否存在再get /hadoop-ha/mycluster/ActiveBreadCrumb看是否记录了一个Active节点。如果ZooKeeper里连路径都没有说明hdfs zkfc -formatZK没执行过或者执行错了集群名。第二步检查ZKFC进程。jps里必须有DFSZKFailoverController进程。如果进程存在但状态还是不对执行hdfs haadmin -getAllServiceState看两个NameNode的状态。如果都是standby常见原因是ZooKeeper客户端会话超时设置太短网络稍微抖动就导致临时节点反复创建删除可以适当调大zookeeper.session.timeout在hdfs-site.xml里加一个dfs.namenode.ha.zookeeper.session-timeout。还有一种比较隐蔽的情况dfs.ha.automatic-failover.enabled只在hdfs-site.xml的nameservices配置正确时才生效如果你启动了多个nameserviceZK只追踪其中一个也会支棱不起来。4.3 时钟不同步引发的“奇妙”故障我之前搭集群时遇到过一个问题YARN的任务时不时报Container killed on request. Exit code is 143或者HDFS的租约被莫名释放。排查半天才发现是三台机器时间不一致差别到了30秒以上。ZooKeeper的会话超时判定对时间很敏感NameNode和DataNode之间的心跳间隔也依赖时间。解决方法是配置NTP或crontab定时同步没有第二种更省事的办法。注意不要在同步过程中把时间往前跳太多否则可能会触发HDFS的lease恢复机制出现瞬间的大量重试。4.4 磁盘空间不足和NameNode安全模式DataNode磁盘满了或NameNode进入SafeMode是另一个高频场景。当NameNode数据目录所在磁盘剩余空间低于阈值默认dfs.namenode.resource.du.reserved是100M左右它会拒绝客户端写操作。遇到这种情况先hdfs dfsadmin -safemode get查看状态再清理磁盘空间。不要盲目执行hdfs dfsadmin -safemode leave因为在存储空间不足或DataNode上报块不到位的情况下强制离开安全模式可能导致数据写穿或副本不足。正确的做法是确认所有DataNode都正常注册且块报告比例达到要求再让NameNode自动退出安全模式。4.5 端口、防火墙和hosts问题Hadoop集群涉及的端口很多RPC 8020、HTTP 50070、ZK 2181/2888/3888、JN 8485、YARN 8088/8032等。很多“集群能起来但外部访问不了”的问题就是防火墙没放行端口。建议在实验环境直接把防火墙先停掉或者精确放行上述端口。还有/etc/hosts的坑我前面提过这里再重复一次hostname和IP不符NameNode和DataNode倒还能通信但YARN的ApplicationMaster在回报进度时经常会解析失败导致作业卡死。所有节点的/etc/hosts必须严格一致。5. 集群日常使用中的调优与经验5.1 内存参数到底怎么算集群配好只是开始真正影响使用体验的是内存参数。很多朋友会照着网上教程填一堆参数却不知道这些数值和物理内存的换算关系。以我的node节点物理内存16G为例DataNode默认堆内存通常设置2GNodeManager的yarn.nodemanager.resource.memory-mb设为10G系统本身还要占用1-2GZooKeeper和JournalNode各分配1G这样加起来已经接近16G了。如果你还在同一台节点上跑HBase或其他进程肯定会OOM。我推荐的计算方式是先确定每个进程的JVM堆内存再反推NodeManager可用内存。比如物理16G的节点分配DataNode 2G、NodeManager 8G、ZK 1G、JournalNode 1G、系统保留2G、剩余2G预留缓冲。这样yarn.nodemanager.resource.memory-mb就填8192。如果任务并发度不高可以在yarn-site.xml里把yarn.scheduler.maximum-allocation-vcores也调低防止应用申请过多虚拟核数导致资源碎片化。5.2 集群扩展怎么加一个新的DataNode集群用了一段时间磁盘吃紧想加一台机器进去。很多人会觉得直接装好Hadoop、改好配置、启动DataNode就行其实有几个坑要提前绕开。新节点上必须保持和旧节点一致的Hadoop版本、Java版本、/etc/hosts内容。然后修改主控节点的workers文件把新节点hostname加进去再分发配置到新节点。启动时先启动新节点的DataNode和NodeManager再在主控节点执行hdfs dfsadmin -refreshNodes刷新节点列表。如果新节点的DataNode还是注册不上去多半是之前4.1提到的clusterID不一致问题建议把新节点的数据目录清空再重启DataNode。5.3 监控和日志别等出事了才去看集群出了问题再去翻日志是最费时间的做法。我习惯把每天的巡检脚本用crontab跑一遍脚本检查核心进程是否在线、NameNode状态是active还是standby、磁盘用量是否超过80%、ZooKeeper集群是否有leader等。日志方面Hadoop的日志目录默认在$HADOOP_HOME/logs还要确认一下HADOOP_LOG_DIR没有被设置为某个容易丢的临时目录。每周看一眼NameNode的Web UI和YARN的ResourceManager Web UI对比过去几天的作业数量和失败率趋势往往能提前发现内存泄漏或网络异常。6. 写在最后的一点个人体会我搭这套Hadoop2集群时前后折腾了将近两个周末最深的感触是这套系统的难点不在单个组件而在组件之间的协作方式。NameNode、JournalNode、ZooKeeper、ResourceManager、NodeManager每个组件本身并不复杂复杂的是它们之间通过心跳、租约、选举、日志同步这些机制相互约束的关系。所以遇到问题别急着搜命令先从日志里确定到底是哪个环节失联了再顺着链路往上查。比如DataNode不注册先看NameNode日志有没有报错NameNode不切换先看ZooKeeper里有没有ActiveBreadCrumbYARN任务卡住先看NodeManager日志里有没有Container启动失败的记录。最后再分享一个小技巧每次改动配置或执行关键命令之前先把hdfs-site.xml、core-site.xml、yarn-site.xml备份一份带时间戳的副本。Hadoop的配置不像普通Web应用改完就能热加载任何配置错误都可能导致所有节点起不来有个备份能让你快速回滚省下大量排查时间。说实话分布式系统的运维经验不是靠看文档看出来的是依靠一次一次把集群弄挂、再一点一点把问题找出来堆出来的。希望这篇基于Hadoop2的实战分享能让你在搭自己第一套集群时少走几步弯路。
返回列表