一、HA概述
1、所谓HA(High Available),即高可用(7*24小时不中断服务)。
2、实现高可用最关键的策略是消除单点故障。HA严格来说应该分成各个组件的HA机制:HDFS的HA和YARN的HA。
3、hadoop1.0之前,在HDFS集群中NameNode存在单点故障(SPOF)。
4、NameNode主要在以下两个方面影响HDFS集群:
1)NameNode机器发生意外,如宕机,集群将无法使用,直到管理员重启;
2)NameNode机器需要升级,包括软件、硬件升级,此时集群也将无法使用;
解决方式:HDFS HA功能通过配置Active/Standby两个NameNodes实现在集群中对NameNode的热备来解决上述问题。如果出现故障,如机器崩溃或机器需要升级维护,这时可通过此种方式将NameNode很快的切换到另外一台机器。
二、HDFS的HA使用
1、HDFS-HA工作机制:
通过双NameNode消除单点故障,一台宕机自动切换至另一台NameNode;
2、HDFS-HA工作要点:
1)隔离(Fence),即同一时刻仅有一个NameNode对外提供服务
2)必须保证两个NameNode之间能够ssh无密码登录
3)元数据管理方式需要改变:
(3.1)两台NameNode内存中各自保存一份元数据;
(3.2)共享的Edits放在一个共享存储中管理(qjournal和NFS两个主流实现);
(3.3)Edits日志只有Active状态的NameNode节点可以做写操作;
(3.4)两个NameNode都可以读取Edits;
4)需要一个状态管理功能模块
:实现了一个zkfailover,常驻在每一个namenode所在的节点,每一个zkfailover负责监控自己所在NameNode节点,利用zk进行状态标识,当需要进行状态切换时,由zkfailover来负责切换,切换时需要防止brain split现象的发生。
3、HDFS-HA自动故障转移工作机制
自动故障转移为HDFS部署增加了两个新组件:ZooKeeper和ZKFailoverController(ZKFC)进程,ZooKeeper是维护少量协调数据,通知客户端这些数据的改变和监视客户端故障的高可用服务。
3.1、HA的自动故障转移依赖于ZooKeeper的以下功能:
1)故障检测
:集群中的每个NameNode在ZooKeeper中维护了一个持久会话,如果机器崩溃,ZooKeeper中的会话将终止,ZooKeeper通知另一个NameNode需要触发故障转移。
2)现役NameNode选择
:ZooKeeper提供了一个简单的机制用于唯一的选择一个节点为active状态。如果目前现役NameNode崩溃,另一个节点可能从ZooKeeper获得特殊的排外锁以表明它应该成为现役NameNode。
3.2、ZKFC是自动故障转移中的另一个新组件,是ZooKeeper的客户端,也监视和管理NameNode的状态。每个运行NameNode的主机也运行了一个ZKFC进程,ZKFC负责:
1)健康监测:
ZKFC使用一个健康检查命令定期地ping与之在相同主机的NameNode,只要该NameNode及时地回复健康状态,ZKFC认为该节点是健康的。如果该节点崩溃,冻结或进入不健康状态,健康监测器标识该节点为非健康的。
2)ZooKeeper会话管理
:当本地NameNode是健康的,ZKFC保持一个在ZooKeeper中打开的会话。如果本地NameNode处于active状态,ZKFC也保持一个特殊的znode锁,该锁使用了ZooKeeper对短暂节点的支持,如果会话终止,锁节点将自动删除。
3)基于ZooKeeper的选择:如果本地NameNode是健康的,且ZKFC发现没有其它的节点当前持有znode锁,它将为自己获取该锁
。如果成功,则它已经赢得了选择,并负责运行故障转移进程以使它的本地NameNode为Active。故障转移进程与前面描述的手动故障转移相似,首先如果必要保护之前的现役NameNode,然后本地NameNode转换为Active状态。
三、HDFS-HA架构
1、环境介绍:
2、结合上图环境部署来看下图:
3、故障转移图解:
![在这里插入图片描述]()
4、故障转移流程解释:
由上图可以看出左边的nn是当前主namenode,当它发生意外时故障转移流程。
1.当左namenode进程死掉后,左zkfc与定期检查namenode发现它已经死亡时,会释放zk排外锁,接着通知备机namenode的zkfc。
2.备机zkfc接到通知后,会与zk服务的联系并尝试取得 排他锁,当取得锁后会去主机杀死namenode进程,防止出现脑裂现象,接着会激活备用namenode,切换为active状态继续工作。
3.当故障转移完成后,启动左namenode后,它就会变为备用namenode,再当右边namenode死亡后,再由右边来接替。
四、HDFS-HA搭建
1、环境介绍:
在之前搭建的hadoop集群上做调整,可以去看之前 博客-hadoo集群搭建,因为我本地有一套环境了,所以复制到另一个文件夹移除数据,修改配置即可,其实跟重新搭建区别不大。
重新解压的安装包只需要按照如下的2.4配置开始即可。
2、环境准备:
HDFS故障移除分为自动与手动,下面先介绍手动模式,自动是在手动的基础上配置的。
2.1在opt目录下创建一个ha文件夹 mkdir ha
[root@hadoop102 opt]# mkdir ha
[root@hadoop102 ha]# pwd
/opt/ha
2.2 将/opt/app/下的 hadoop-2.7.2拷贝到/opt/ha目录下
[root@hadoop102 ha]# cp -r /opt/module/hadoop-2.7.2/ /opt/ha/
2.3 删除历史数据
[root@hadoop102 hadoop-2.7.2]# rm -rf data/ logs/
2.4 配置hadoop-env.sh,我这里是复制的已经配置过了,如果是重新解压的需要配置。
export JAVA_HOME=/opt/module/jdk1.8.0_144
2.5 配置core-site.xml,将以前的配置移除,如果是新解压的直接按照如下配置即可
<configuration>
<!-- 把两个NameNode)的地址组装成一个集群mycluster
mycluster是集群名称 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
<!-- 指定hadoop运行时产生文件的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/ha/hadoop-2.7.2/data/tmp</value>
</property>
</configuration>
2.6 配置hdfs-site.xml,移除之前配置,配置如下内容,需要注意dfs.ha.fencing.ssh.private-key-files配置,这个是自己的当前用户配置
<configuration>
<!-- 完全分布式集群名称 -->
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<!-- 集群中NameNode节点都有哪些 -->
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
<!-- nn1的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>hadoop102:9000</value>
</property>
<!-- nn2的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>hadoop103:9000</value>
</property>
<!-- nn1的http通信地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>hadoop102:50070</value>
</property>
<!-- nn2的http通信地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>hadoop103:50070</value>
</property>
<!-- 指定NameNode元数据在JournalNode上的存放位置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hadoop102:8485;hadoop103:8485;hadoop104:8485/mycluster</value>
</property>
<!-- 配置隔离机制,即同一时刻只能有一台服务器对外响应 -->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<!-- 使用隔离机制时需要ssh无秘钥登录-->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>
<!-- 声明journalnode服务器存储目录-->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/opt/ha/hadoop-2.7.2/data/jn</value>
</property>
<!-- 关闭权限检查-->
<property>
<name>dfs.permissions.enable</name>
<value>false</value>
</property>
<!-- 访问代理类:client,mycluster,active配置失败自动切换实现方式-->
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
</configuration>
2.7 拷贝配置好的hadoop环境到其他节点
[root@hadoop102 ha]# xsync hadoop-2.7.2/
注意:
如上配置如果是重新解压的hadoop安装包,直接按照如上配置一步步即可,因为我这里是之前配置的集群,所以需要将配置文件里面内容先移除掉;还需要注意ssh的路径;自己需要放置的数据目录位置。
记录一次配置问题:我当时没有将snn配置去掉导致namenode格式化失败,由于snn是辅助nn完成备份,所以效果与HA一样,所以如果配置snn与ha冲突了。
3、zookeeper搭建
由于HA需要zookeeper结合所以需要搭建一个zk集群
搭建过程:
4、HDFS手动故障转移测试
4.1 在各个JournalNode节点上,输入以下命令启动journalnode服务
#102 演示
[root@hadoop102 hadoop-2.7.2]# pwd
/opt/ha/hadoop-2.7.2
[root@hadoop102 hadoop-2.7.2]# sbin/hadoop-daemon.sh start journalnode
[root@hadoop103 hadoop-2.7.2]# sbin/hadoop-daemon.sh start journalnode
[root@hadoop104 hadoop-2.7.2]# sbin/hadoop-daemon.sh start journalnode
4.2 在[nn1]上,对其进行格式化,并启动,也就是102
[root@hadoop102 hadoop-2.7.2]# bin/hdfs namenode -format
启动nn
[root@hadoop102 hadoop-2.7.2]# sbin/hadoop-daemon.sh start namenode
4.3 在[nn2]上,同步nn1的元数据信息
[root@hadoop103 hadoop-2.7.2]# bin/hdfs namenode -bootstrapStandby
4.4 启动[nn2]
[root@hadoop103 hadoop-2.7.2]# sbin/hadoop-daemon.sh start namenode
4.5查看web页面显示,当前两个namenode都是备用状态
4.6在[nn1]上,启动所有datanode
[root@hadoop102 hadoop-2.7.2]# sbin/hadoop-daemons.sh start datanode
4.7 将[nn1]切换为Active
[root@hadoop102 hadoop-2.7.2]# bin/hdfs haadmin -transitionToActive nn1
4.8 查看是否Active
[root@hadoop102 hadoop-2.7.2]# bin/hdfs haadmin -getServiceState nn1
active
上面就是手动切换namenode的介绍,由于手动模式两个nn都是备机状态,只需要手动修改一个为当前主机状态即可
5、配置HDFS-HA自动故障转移
5.1修改配置文件
(1)在hdfs-site.xml中增加
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
(2)在core-site.xml文件中增加
<property>
<name>ha.zookeeper.quorum</name>
<value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value>
</property>
(3)同步配置文件
5.2 启动集群环境测试
(1)关闭所有HDFS服务:环境以及关闭或者重启过,不用关闭了
[root@hadoop102 hadoop-2.7.2]# sbin/stop-dfs.sh
(2)启动Zookeeper集群:如下命令是我的zk集群管理脚本
[root@hadoop102 hadoop-2.7.2]# /opt/module/zookeeper-3.4.10/zk.sh start
(3)初始化HA在Zookeeper中状态:
[root@hadoop102 hadoop-2.7.2]# bin/hdfs zkfc -formatZK
(4)启动HDFS服务:
[root@hadoop102 hadoop-2.7.2]# sbin/start-dfs.sh
(5)在各个NameNode节点上启动DFSZK Failover Controller,先在哪台机器启动,哪个机器的NameNode就是Active NameNode
sbin/start-dfs.sh:有可能将zkfc已经启动,则不用在启动了
[root@hadoop102 hadoop-2.7.2]# sbin/hadoop-daemon.sh start zkfc
[root@hadoop103 hadoop-2.7.2]# sbin/hadoop-daemon.sh start zkfc
(6)验证故障自动转移,我这里当前102是主机active状态,103是备机
--6.1 将Active NameNode进程kill,并将机器断开网络
[root@hadoop102 hadoop-2.7.2]# jps
12337 NameNode
28482 Jps
8204 QuorumPeerMain
9228 DFSZKFailoverController
6765 DataNode
7069 JournalNode
[root@hadoop102 hadoop-2.7.2]# kill -9 6765
[root@hadoop102 hadoop-2.7.2]# service network stop
如上操作完成后103就会自动变成active状态开始工作,再将102网络打开,nn启动会发现102变为备机状态。
五、YARN-HA工作机制
1、YARN-HA工作机制
1.1、官方文档:
1.2、YARN-HA工作机制,如图
2、配置YARN-HA集群
2.1、规划集群
2.2、具体配置
(1)yarn-site.xml
<configuration>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!--启用resourcemanager ha-->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!--声明两台resourcemanager的地址-->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>cluster-yarn1</value>
</property>
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>hadoop102</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>hadoop104</value>
</property>
<!--指定zookeeper集群的地址-->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value>
</property>
<!--启用自动恢复-->
<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
<!--指定resourcemanager的状态信息存储在zookeeper集群-->
<property>
<name>yarn.resourcemanager.store.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
</configuration>
(2)同步更新其他节点的配置信息
[root@hadoop102 hadoop-2.7.2]# xsync etc/hadoop/yarn-site.xml
2.3、启动zk、hdfs、yarn
2.3.1、先启动zk、再启动hdfs,当使用sbin/start-dfs.sh时发现有个别节点未启动需要单独去启动
2.3.2、启动YARN
(1)在hadoop102中执行:
[root@hadoop102 hadoop-2.7.2]# sbin/start-yarn.sh
(2)在hadoop104中执行:由于104是yarn备机所以需要单独启动
[root@hadoop104 hadoop-2.7.2]# sbin/yarn-daemon.sh start resourcemanager
(3)查看服务状态
[root@hadoo102 hadoop-2.7.2]# bin/yarn rmadmin -getServiceState rm1
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/opt/ha/hadoop-2.7.2/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/module/hbase/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
active
如上图:yarn的web页面,其实104也启动着,但是访问http://hadoop104:8088/cluster 会自动跳转至102
2.3.3、YARN-HA测试
1.kill掉当前工作的yarnmanager
[root@hadoop102 hadoop-2.7.2]# jps
10256 DataNode
6000 NodeManager
10818 DFSZKFailoverController
20755 NameNode
10548 JournalNode
31734 Jps
8823 QuorumPeerMain
10777 ResourceManager
[root@hadoop102 hadoop-2.7.2]# kill -9 10777
2. 查看备机是否转正
[root@hadoop104 hadoop-2.7.2]# bin/yarn rmadmin -getServiceState rm2
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/opt/ha/hadoop-2.7.2/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/module/hbase/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
active
3.此时启动102 yarn,102就变成了备机