前言

Hadoop HA 是什么?

hadoop2.x版本中可以有多个namenode结点,一个是活跃(active)状态,一个是准备(standby)状态。(haoop 1.x不存在此特性)

HA可以干什么?

1.1 HDFS HA背景

HDFS集群中NameNode 存在单点故障(SPOF)。对于只有一个NameNode的集群,如果NameNode机器出现意外情况,将导致整个集群无法使用,直到NameNode 重新启动。

影响HDFS集群不可用主要包括以下两种情况:一是NameNode机器宕机,将导致集群不可用,重启NameNode之后才可使用;二是计划内的NameNode节点软件或硬件升级,导致集群在短时间内不可用。

为了解决上述问题,Hadoop给出了HDFS的高可用HA方案:HDFS通常由两个NameNode组成,一个处于active状态,另一个处于standby状态。Active NameNode对外提供服务,比如处理来自客户端的RPC请求,而Standby NameNode则不对外提供服务,仅同步Active NameNode的状态,以便能够在它失败时快速进行切换。

1.2 HDFS HA架构

一个典型的HA集群,NameNode会被配置在两台独立的机器上,在任何时间上,一个NameNode处于活动状态,而另一个NameNode处于备份状态,活动状态的NameNode会响应集群中所有的客户端,备份状态的NameNode只是作为一个副本,保证在必要的时候提供一个快速的转移。

为了让Standby Node与Active Node保持同步,这两个Node都与一组称为JNS的互相独立的进程保持通信(Journal Nodes)。当Active Node上更新了namespace,它将记录修改日志发送给JNS的多数派。Standby noes将会从JNS中读取这些edits,并持续关注它们对日志的变更。Standby Node将日志变更应用在自己的namespace中,当failover发生时,Standby将会在提升自己为Active之前,确保能够从JNS中读取所有的edits,即在failover发生之前Standy持有的namespace应该与Active保持完全同步。

为了支持快速failover,Standby node持有集群中blocks的最新位置是非常必要的。为了达到这一目的,DataNodes上需要同时配置这两个Namenode的地址,同时和它们都建立心跳链接,并把block位置发送给它们。

任何时刻,只有一个Active NameNode是非常重要的,否则将会导致集群操作的混乱,那么两个NameNode将会分别有两种不同的数据状态,可能会导致数据丢失,或者状态异常,这种情况通常称为“split-brain”(脑裂,三节点通讯阻断,即集群中不同的Datanodes却看到了两个Active NameNodes)。对于JNS而言,任何时候只允许一个NameNode作为writer;在failover期间,原来的Standby Node将会接管Active的所有职能,并负责向JNS写入日志记录,这就阻止了其他NameNode基于处于Active状态的问题。

基于QJM的HDFS HA方案如上图所示,其处理流程为:集群启动后一个NameNode处于Active状态,并提供服务,处理客户端和DataNode的请求,并把editlog写到本地和share editlog(这里是QJM)中。另外一个NameNode处于Standby状态,它启动的时候加载fsimage,然后周期性的从share editlog中获取editlog,保持与Active节点的状态同步。为了实现Standby在Active挂掉后迅速提供服务,需要DataNode同时向两个NameNode汇报,使得Stadnby保存block to DataNode信息,因为NameNode启动中最费时的工作是处理所有DataNode的blockreport。为了实现热备,增加FailoverController和Zookeeper,FailoverController与Zookeeper通信,通过Zookeeper选举机制,FailoverController通过RPC让NameNode转换为Active或Standby。

1.3 HDFS HA配置要素

NameNode机器:两台配置对等的物理机器,它们分别运行Active和Standby Node。

JouralNode机器:运行JouralNodes的机器。JouralNode守护进程相当的轻量级,可以和Hadoop的其他进程部署在一起,比如NameNode、DataNode、ResourceManager等,至少需要3个且为奇数,如果你运行了N个JNS,那么它可以允许(N-1)/2个JNS进程失效并且不影响工作。

在HA集群中,Standby NameNode还会对namespace进行checkpoint操作(继承Backup Namenode的特性),因此不需要在HA集群中运行SecondaryNameNode、CheckpointNode或者BackupNode。

1.5 HDFS自动故障转移

HDFS的自动故障转移主要由Zookeeper(Zookeeper很重要啊)和ZKFC两个组件组成。

Zookeeper集群作用主要有:

一:是故障监控。每个NameNode将会和Zookeeper建立一个持久session,如果NameNode失效,那么此session将会过期失效,此后Zookeeper将会通知另一个Namenode,然后触发Failover;

二:是NameNode选举。ZooKeeper提供了简单的机制来实现Acitve Node选举,如果当前Active失效,Standby将会获取一个特定的排他锁,那么获取锁的Node接下来将会成为Active。

ZKFC是一个Zookeeper的客户端,它主要用来监测和管理NameNodes的状态,每个NameNode机器上都会运行一个ZKFC程序,它的职责主要有:一是健康监控。ZKFC间歇性的ping NameNode,得到NameNode返回状态,如果NameNode失效或者不健康,那么ZKFS将会标记其为不健康;二是Zookeeper会话管理。当本地NaneNode运行良好时,ZKFC将会持有一个Zookeeper session,如果本地NameNode为Active,它同时也持有一个“排他锁”znode,如果session过期,那么次lock所对应的znode也将被删除;三是选举。当集群中其中一个NameNode宕机,Zookeeper会自动将另一个激活。

1.6 YARN HA架构

YARN的HA架构和HDFS HA类似,需要启动两个ResourceManager,这两个ResourceManager会向ZooKeeper集群注册,通过ZooKeeper管0理它们的状态(Active或Standby)并进行自动故障转移。

集群规划

我们本次使用三台虚拟机来配置Hadoop的HA,如下表所示:

主机名 ip地址 安装环境 jdk
master 192.168.128.160 hadoop,zookeeper 1.8.0_131
slave1 192.168.128.161 hadoop,zookeeper 1.8.0_131
slave2 192.168.128.162 hadoop,zookeeper 1.8.0_131

我们在HA搭建之前,需要对于集群上的点进行规划,如图:

这些就是我们配置完namenode HA和resourcemanager HA后,开启集群应该有的节点

(注:本文更注重于修改配置文件,在下文中有明显的倾向)

在hadoop下etc/hadoop下的目录中放着我们hadoop的主要配置文件,我们配置HA主要修改这几个文件:

hdfs-site.xml:Hadoop守护进程的配置项

core-site.xml:Hadoop Core的配置项

hadoop-env.sh:配置java路径,同时也记录了脚本中要用到的环境变量,以运行hadoop

slaves:记录的是集群里所有DataNode的主机名

yanr-site.xml:主要记录了resourcemanager的配置文件

mapred-site.xml:MapReduce守护进程的配置项

namenode的HA

在hdfs-site.xml文件中,我们需要添加这些:

<configuration>
<property>
<name> dfs.replication </name>
<value>3</value>
</property>
<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>master:8020</value>
</property>

<!-- nn2的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>slave1:8020</value>
</property>

<!-- nn1的http通信地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>master:50070</value>
</property>

<!-- nn2的http通信地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>slave1:50070</value>
</property>
<!-- 指定NameNode元数据在JournalNode上的存放位置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://master:8485;slave1:8485;slave2:8485/mycluster</value>
</property>

<!-- 配置隔离机制,即同一时刻只能有一台服务器对外响应 -->

<property>
<name>dfs.ha.fencing.methods</name>
<value>shell(/bin/true)</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/modules/hadoop-2.6.0/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>





在mapred-site.xml文件中添加这些:

<!--指定运行mapreduce的环境是yarn-->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>

在core-site.xml文件中添加这些:

<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>

<property>
<name>hadoop.tmp.dir</name>
<value>/opt/modules/hadoop-2.6.0/data</value>
</property>
</configuration>

在hadoop-env.sh中配置一下java的路径,如图

在slaves中,修改为

master
slave1
slave2

配置文件要三台都配置完成

配置完成后要先启动zookpeeper,zookeeper的配置在下一篇文章写,这里就不过多解释了

先在各个journalnode节点上启动journalnode节点,在hadoop文件夹下输入

sbin/hadoop-daemon.sh start journalnode

启动journalnode节点

在master下进行格式化

bin/hdfs namenode -format

如上图所示,就是格式化成功

格式化成功完成后,在master机器上启动namenoed,启动master的namenode成功后

在slave1机器下进行数据的同步,在slave1的hadoop文件夹下输入

bin/hdfs namenode -bootstrapStandby

如图显示同步成功后:

就可以在slave1下启动namenode

我们在配置完这些文件后可以,使用web端来查看namenode的工作状态,如图:

现在两个namenode都是待命状态,这是因为我们还没有配置故障自动转移.

而我们可以手动选择那个namenode节点为active状态

bin/hdfs haadmin -transitionToActive nn1

我们可以输入这个命令来查看节点的工作状态

bin/hdfs haadmin -getServiceState nn1

如图所示

mark

我们也可以通过web端来查看namenode的状态

如图:

mark

如果需要配置HDFS的自动故障转移,需要在hdfs-site.xml和core-site.xml中添加两个属性

在hdfs-site.xml中添加

<!--自动故障转移-->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>

在core-site.xml中添加

<property>
<name>ha.zookeeper.quorum</name>
<value>master:2181,slave1:2181,slave2:2181</value>
</property>

添加完之后,依旧需要同步到其他两台机器上

然后我们需要初始化HA在hadoop中的状态栏中输入

bin/hdfs zkfc -formatZK

我们看到如图所示的时候代表初始化成功:

mark

这时我们可以进入zk的客户端,在zookpeeper目录下,输入:

bin/zkCli.sh 

进入这个页面

mark

输入;

ls /

我们可以看到一个hadoop-ha的节点

mark

这就代表我们的hadoop的ha在zookpeeper中的节点创建好了

我们的初始化成功后,就可以在hadoop的目录下启动HDFS的所有节点

在hadoop目录下输入

sbin/start-dfs.sh

我们应该能看到这些节点

mark

DFSZKFailoverController这个就是故障转移的主要负责节点

我们两台namenode中一台为active状态,一台为standby状态,如图:

mark

mark

我们可以手动kill掉正在active状态的namenode,看看standby状态的namenode会有什么变化

mark

这时候master上的namenode就已经停止了工作

我们可以在web端查看一下

mark

页面已经无法进入了,我们看看slave1的

mark

slave1的namenode显示处于active状态,这代表我们的namenode的HA配置成功,namenode会在发生故障的时候进行自动的故障转移.

resourcemanage的HA

下面我们开始配置resourcemanage的HA配置

resourcemanage的HA的配置文件主要与yarn-site.xml有关

在yarn-site.xml中修改

<configuration>

<!-- Site specific YARN configuration properties -->
<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>slave1</value>
</property>

<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>slave2</value>
</property>

<!--指定zookeeper集群的地址-->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>master:2181,slave1:2181,slave2: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>



配置文件要三台机器都配置完成

我们是在slave1和slave2上配置ResourceManager,我们需要在slave1上启动yarn,在slave1上输入

sbin/start-yarn.sh

这样就可以启动master上的nodemanage和salve1上的ResourceManager,slave2上的ResourceManager我们需要在slave2上启动,在slave2上输入

sbin/yarn-daemon.sh start resourcemanager

我们可以在web端查看一下

在浏览器上输入http://slave1:8088

我们应该可以看到这样的页面

mark

但是当我们去在浏览器中输入http://slave2:8088的时候将会自动跳转到http://slave1:8088的页面,会在页面上先显示这样一句话:

This is standby RM. Redirecting to the current active RM: http://slave1:8088/cluster

这是因为slave2的ResourceManager处于standby状态,会自动跳转到http://slave1:8088

这时候我们可以手动kill掉slave1的ResourceManager

mark

这个时候slave1上的ResourceManager就已经停止工作了

http://slave1:8088这个页面就无法打开

mark

然后在查看http://slave2:8088

这表明resourcemanager节点会在发生故障时,进行自动故障的转移.

本次的HA配置到这里就结束了,感谢大家的阅读.