原生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之间网络有问题,则会造成他们之前数据的同步出问题。
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的失败。
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。
-
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 |
配置
对于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/
第二步 建立文件目录 /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配置完毕,可以统计浏览器访问:
NameNode 'weekend01:9000' (active)
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也是上面的道理