原生Hadoop HA集群搭建配置

1. 概述 

在hadoop2.0之前,namenode只有一个,存在单点问题(虽然hadoop1.0有secondarynamenode,checkpointnode,buckcupnode这些,但是单点问题依然存在),在hadoop2.0引入了HA机制。hadoop2.0的HA机制官方介绍了有2种方式,一种是NFS(Network File System)方式,另外一种是QJM(Quorum Journal Manager)方式

2 基本原理 

hadoop2.0的HA 机制有两个namenode,一个是active namenode,状态是active;另外一个是standby namenode,状态是standby。两者的状态是可以切换的,但不能同时两个都是active状态,最多只有1个是active状态。只有active namenode提供对外的服务,standby namenode是不对外服务的。active namenode和standby namenode之间通过NFS或者JN(journalnode,QJM方式)来同步数据。

active namenode会把最近的操作记录写到本地的一个edits文件中(edits file),并传输到NFS或者JN中。standby namenode定期的检查,从NFS或者JN把最近的edit文件读过来,然后把edits文件和fsimage文件合并成一个新的fsimage,合并完成之后会通知active namenode获取这个新fsimage。active namenode获得这个新的fsimage文件之后,替换原来旧的fsimage文件。

这样,保持了active namenode和standby namenode的数据的实时同步,standby namenode可以随时切换成active namenode(譬如active namenode挂了)。而且还有一个原来hadoop1.0的secondarynamenode,checkpointnode,buckcupnode的功能:合并edits文件和fsimage文件,使fsimage文件一直保持更新。所以启动了hadoop2.0的HA机制之后,secondarynamenode,checkpointnode,buckcupnode这些都不需要了。

3. NFS方式 

NFS作为active namenode和standby namenode之间数据共享的存储。active namenode会把最近的edits文件写到NFS,而standby namenode从NFS中把数据读过来。这个方式的缺点是,如果active namenode或者standby namenode有一个和NFS之间网络有问题,则会造成他们之前数据的同步出问题。

原生Hadoop HA集群搭建配置

4 QJM(Quorum Journal Manager )方式 

QJM的方式可以解决上述NFS容错机制不足的问题。active namenode和standby namenode之间是通过一组journalnode(数量是奇数,可以是3,5,7...,2n+1)来共享数据。active namenode把最近的edits文件写到2n+1个journalnode上,只要有n+1个写入成功就认为这次写入操作成功了,然后standby namenode就可以从journalnode上读取了。可以看到,QJM方式有容错的机制,可以容忍n个journalnode的失败。

原生Hadoop HA集群搭建配置

5 主备节点的切换

active namenode和standby namenode可以随时切换。当active namenode挂掉后,也可以把standby namenode切换成active状态,成为active namenode。可以人工切换和自动切换。人工切换是通过执行HA管理的命令来改变namenode的状态,从standby到active,或者从active到standby。自动切换则在active namenode挂掉的时候,standby namenode自动切换成active状态,取代原来的active namenode成为新的active namenode,HDFS继续正常工作。

 

主备节点的自动切换需要配置zookeeper。active namenode和standby namenode把他们的状态实时记录到zookeeper中,zookeeper监视他们的状态变化。当zookeeper发现active namenode挂掉后,会自动把standby namenode切换成active namenode。

原生Hadoop HA集群搭建配置

  • QJM方式有明显的优点,一是本身就有fencing的功能,二是通过多个journal节点增强了系统的健壮性,所以建议在生成环境中采用QJM的方式。

  • journalnode消耗的资源很少,不需要额外的机器专门来启动journalnode,可以从hadoop集群中选几台机器同时作为journalnode。

 

node5

172.17.14.205

zookeeper,datanode,nodemanager

node6

172.17.14.206

zookeeper,datanode,nodemanager

node7

172.17.14.207

zookeeper,datanode,nodemanager

node8

172.17.14.208

namenode,resourcemanager

node9

172.17.14.209

namenode,resourcemanager

 

配置

原生Hadoop HA集群搭建配置

对于HA集群而言,确保同一时刻只有一个NameNode处于active状态是至关重要的。否则,两个NameNode的数据状态就会产生分歧,可能丢失数据,或者产生错误的结果。为了保证这点,JNs必须确保同一时刻只有一个NameNode可以向自己写数据。 

第一步 安装Hadoop,去官网下载tar.gz,使用tar -zxvf  hadoop-2.10.0.tar.gz  -C  /指定目录

https://mirror.bit.edu.cn/apache/hadoop/common/hadoop-2.10.0/

原生Hadoop HA集群搭建配置

第二步 建立文件目录 /home/hadoop/hadooptmp 创建文件夹data,存放数据、日志文件,haooop原文件,zookeeper原文件

第三步修改配置文件

切换到hadoop的配置文件目录,分别打开以下文件,将以下内容直接插入到文件末尾

core-site.xml

 

 <!--hadoop.tmp.dir:hadoop很多路径都依赖他,namenode节点该目录不可以删除,否则需要重新格式化-->

<property>

    <name>hadoop.tmp.dir</name>

    <value>/home/hadoop/hadooptmp</value>

</property>

<!--这个配置文件描述了集群的namenode节点的url,这里采用HA代表默认逻辑名,集群中的每个datanode节点都需要知道namenode的地址,数据才可以被使用

和hdfs-site.xml 里的dfs.nameservices一致-->

<property>

    <name>fs.defaultFS</name>

    <value>hdfs://cluster</value>

</property>

<!-- zookeeper集群的地址和端口,最好保持基数个至少3台-->

 <property>

    <name>ha.zookeeper.quorum</name>

    <value>zk1:2181,zk2:2181,zk3:2181</value>

</property>

  

 

hdfs-site.xml

 

<!--hadoop namenode数据的存储目录,只是针对与namenode,包含了namenode的系统信息元数据信息-->

<property>

    <name>dfs.namenode.name.dir</name>

    <value>/home/hadoop/hadooptmp/nn</value>

</property>

<!--datanode 要存储到数据到本地的路径,不必每一台机器都一样,但是为了方便管理最好还是一样-->

<property>

    <name>dfs.datanode.data.dir</name>

    <value>/home/hadoop/hadooptmp/dn</value>

</property>

<!--系统中文件备份数量,系统默认是3分-->

<property>

    <name>dfs.replication</name>

    <value>3</value>

</property>

<!-- dfs.webhdfs.enabled 置为true,否则一些命令无法使用如:webhdfs的LISTSTATUS -->

<property>

    <name>dfs.webhdfs.enabled</name>

    <value>true</value>

</property>

<!--可选,关闭权限带来一些不必要的麻烦-->

<property>

     <name>dfs.permissions</name>

     <value>false</value>

</property>

<!--可选,关闭权限带来一些不必要的麻烦-->

<property>

     <name>dfs.permissions.enabled</name>

     <value>false</value>

</property>

<!--HA配置-->

<!--设置集群的逻辑名,与core-site.xml里的fs.defaultFS一致 -->

<property>

    <name>dfs.nameservices</name>

    <value>cluster</value>

</property>

<!--hdfs集群中的namenode节点逻辑名,该名称是可以让DataNode知道每个集群的所有NameNode-->

<property>

    <name>dfs.ha.namenodes.cluster</name>

    <value>nn1,nn2</value>

</property>

<!--hdfs namenode逻辑名中RPC配置,rpc 简单理解为序列化文件上传输出文件要用到-->

<property>

    <name>dfs.namenode.rpc-address.cluster.nn1</name>

    <value>master1:9000</value>

</property>

<property>

    <name>dfs.namenode.rpc-address.cluster.nn2</name>

    <value>master2:9000</value>

</property>

<!--配置hadoop页面访问端口端口-->

<property>

    <name>dfs.namenode.http-address.cluster.nn1</name>

    <value>master1:50070</value>

</property>

<property>

    <name>dfs.namenode.http-address.cluster.nn2</name>

    <value>master2:50070</value>

</property>

<!--建立与namenode的通信-->

<property>

 <name>dfs.namenode.servicerpc-address.cluster.nn1</name>

 <value>master1:53310</value>

</property>

<property>

 <name>dfs.namenode.servicerpc-address.cluster.nn2</name>

 <value>master2:53310</value>

</property>

<!--journalnode 共享文件集群-->

<property>

    <name>dfs.namenode.shared.edits.dir</name>

    <value>qjournal://zk1:8485;zk2:8485;zk3:8485/cluster</value>

</property>

 <!--journalnode对namenode的进行共享设置-->

<property>

 <name>dfs.journalnode.edits.dir</name>

 <value>/home/hadoop/hadooptmp/ha/journal</value>

</property>

<!--这里配置HDFS客户端连接到Active NameNode的一个java类 -->

<property>

    <name>dfs.client.failover.proxy.provider.cluster</name>

    <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>

</property>

<!--开启自动切换-->

<property>

    <name>dfs.ha.automatic-failover.enabled</name>

    <value>true</value>

</property>

<!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行-->

     <property>

      <name>dfs.ha.fencing.methods</name>

      <value>

       sshfence

       shell(/bin/true)

      </value>

     </property>

<!--ssh通信密码通信位置-->

<property>

    <name>dfs.ha.fencing.ssh.private-key-files</name>

    <value>/home/hadoop/.ssh/id_rsa</value>

</property>

<!-- 配置sshfence隔离机制超时时间 -->

<property>

 <name>dfs.ha.fencing.ssh.connect-timeout</name>

 <value>30000</value>

</property>

 

yarn-site.xml

 

<!-- 开启RM高可用 -->

      <property>

         <name>yarn.resourcemanager.ha.enabled</name>

         <value>true</value>

      </property>

      <!-- 指定RM的cluster id -->

      <property>

         <name>yarn.resourcemanager.cluster-id</name>

         <value>yrc</value>

      </property>

      <!-- 指定RM的名字 -->

      <property>

         <name>yarn.resourcemanager.ha.rm-ids</name>

         <value>rm1,rm2</value>

      </property>

      <!-- 分别指定RM的地址 -->

      <property>

         <name>yarn.resourcemanager.hostname.rm1</name>

         <value>master1</value>

      </property>

      <property>

         <name>yarn.resourcemanager.hostname.rm2</name>

         <value>master2</value>

      </property>

      <!-- 指定zk集群地址 -->

      <property>

         <name>yarn.resourcemanager.zk-address</name>

         <value>zk1:2181,zk2:2181,zk3:2181</value>

      </property>

      <property>

         <name>yarn.nodemanager.aux-services</name>

         <value>mapreduce_shuffle</value>

      </property>

 

mapred-site.xml

 

<configuration>

     <!-- 指定mr框架为yarn方式 -->

     <property>

      <name>mapreduce.framework.name</name>

      <value>yarn</value>

     </property>

    </configuration> 

第四步

2.5启动zookeeper集群(分别在zk1、zk2、zk3上启动zk)

cd /weekend/zookeeper-3.4.5/bin/

./zkServer.sh start

#查看状态:一个leader,两个follower

./zkServer.sh status

2.6启动journalnode(分别在在zk1、zk2、zk3上执行)

cd /weekend/hadoop-2.4.1

sbin/hadoop-daemon.sh start journalnode

#运行jps命令检验,zk1、zk2、zk3上多了JournalNode进程

 

2.7格式化HDFS

#在weekend01上执行命令:

hdfs namenode -format

#格式化后会在根据core-site.xml中的hadoop.tmp.dir配置生成个文件,这里我配置的是/weekend/hadoop-2.4.1/tmp,然后将/weekend/hadoop-2.4.1/tmp拷贝到weekend02的/weekend/hadoop-2.4.1/下。

scp -r tmp/ weekend02:/home/hadoop/app/hadoop-2.4.1/

 

2.8格式化ZKFC(在weekend01上执行即可)

hdfs zkfc -formatZK

 

2.9启动HDFS(在weekend01上执行)

sbin/start-dfs.sh

 

2.10启动YARN(#####注意#####:是在weekend03上执行start-yarn.sh,

把namenode和resourcemanager分开是因为性能问题,

因为他们都要占用大量资源,所以把他们分开了,

他们分开了就要分别在不同的机器上启动)

sbin/start-yarn.sh

到此,hadoop-2.4.1配置完毕,可以统计浏览器访问:

http://192.168.1.201:50070

NameNode 'weekend01:9000' (active)

http://192.168.1.202:50070

NameNode 'weekend02:9000' (standby)

 

验证HDFS HA

首先向hdfs上传一个文件

hadoop fs -put /etc/profile /profile

hadoop fs -ls /

然后再kill掉active的NameNode

kill -9 <pid of NN>

通过浏览器访问:http://192.168.1.202:50070

NameNode 'weekend02:9000' (active)

这个时候weekend02上的NameNode变成了active

在执行命令:

hadoop fs -ls /

-rw-r--r--   3 root supergroup       1926 2014-02-06 15:36 /profile

刚才上传的文件依然存在!!!

手动启动那个挂掉的NameNode

sbin/hadoop-daemon.sh start namenode

通过浏览器访问:http://192.168.1.201:50070

NameNode 'weekend01:9000' (standby)

 

验证YARN:

运行一下hadoop提供的demo中的WordCount程序:

hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.4.1.jar wordcount /profile /out

测试集群工作状态的一些指令 :

bin/hdfs dfsadmin -report 查看hdfs的各节点状态信息

bin/hdfs haadmin -getServiceState nn1 获取一个namenode节点的HA状态

sbin/hadoop-daemon.sh start namenode  单独启动一个namenode进程

./hadoop-daemon.sh start zkfc   单独启动一个zkfc进程

   

nn需要给自己,第二个nn自己所有的dn配置互信,因为在start-dfs.sh运行的时候会ssh链接自己,第二个nn自己所有的nn启动服务,

rm只需给所有的dn配置互信,不用给自己配置,因为rm只是通过本地启动服务,而不是ssh

同时也不需要和第二个rm配置互信,第二个rm的服务需要单独启动

只要配置nn到其他nn及自己及dn的互信,反过来不用配置,因为ssh只是在启动服务的时候起作用,而集群运行后,是通过rpc执行的。

rm也是上面的道理