利用QJM实现HDFS的HA策略部署与验证工作记录分享

1、概述 

Hadoop2.X中的HDFS(Vsersion2.0)相比于Hadoop1.X增加了两个重要功能,HA和Federation。HA解决了Hadoop1.X  Namenode中一直存在的单点故障问题,HA策略通过热备的方式为主NameNode提供一个备用者,并且这个备用者的状态一直和主Namenode的元数据保持一致,一旦主NameNode挂了,备用NameNode可以立马转换变换为主NameNode,从而提供不间断的服务。另外,Federation特性,主要是允许一个 HDFS 集群中存在多个 NameNode 同时对外提供服务,这些 NameNode 分管一部分目录(水平切分),彼此之间相互隔离,但共享底层的 DataNode 存储资源。本文档主要是总结我自己个人利用为QJM(Quorum Journal Manager)为公司测试集群(hadoop2.2.0)部署HA策略的过程以及自己在部署过程中遇到的一些问题。

2、HDFSHA基本架构

    先来看个手动挡切换的HA架构图:

在一个典型的 HDFS  HA 场景中,通常由两个NameNode 组成,一个处于Active状态,另一个处于Standby状态。Active NameNode 对外提供服务,比如处理来自客户端的 RPC 请求,而 Standby NameNode 则不对外提供服务,仅同步 Active NameNode的状态,以便能够在它失败时快速进行切换。

为了能够实时同步 Active 和 Standby 两个 NameNode 的元数据信息(实际上editlog),需提供一个共享存储系统,可以是 NFSQJ(Quorum Journal Manager)或者 Bookeeper,Active  NameNode 将数据写入共享存储系统,我们可以在Active  NameNode的50070端口上看到相应的NameNode Journal  Status信息:

同时Standby NameNode监听该系统(QJM管理下的Journalnode进程对应的存储路径),一旦发现有新数据写入,则读取这些数据,并加载到自己内存中,以保证自己内存状态与 Active NameNode 保持基本一致,那么在紧急情况下 standby NameNode便可快速切为Active NameNode。另外,在Hadoop1.X中的Secondary NameNode或者自己通过nfs热备的NameNode信息在Hadoop2.X中已经不再需要了,他们被Standby NameNode取代了。 在Yarn的官网中,我还看到一段关于JournalNode错误兼容性信息:

大概意思是主备NameNode 之间通过一组JournalNode 同步元数据信息(我的通俗理解就是QJM类似一个数据池,池里边装着多个JournalNode进程存储editlog,Active NameNode往池里边的JournalNode进程写editlog,StandBy NameNode向池里边的JournalNode取数据同步),一条数据只要成功写入多数 JournalNode 即认为写入成功。启动的JournalNode的个数必须为奇数个。如果你的HA策略中启动了N个JournalNode进程那么整个QJM最多允许(N-1)/2个进程死掉,这样才能保证editLog成功完整地被写入。比如 3个 JournalNode 时,最多允许 1 个 JournalNode挂掉,5 个 JournalNode 时,最多允许 2 个 JournalNode 挂掉。

3、  HDFS HA部署

3.1、部署和测试环境

HDFS HA的部署和验证是在公司的测试集群中完成,其中测试集群中数据节点一共有4个主机名分别为hadoop-slave1、hadoop-slave02、hadoop-slave03、hadoop-slave04,master节点的主机名为hadoop-master。因为JournalNode和Zookeeper进程是非常轻量级的,可以其他服务共用节点。现在的部署情况是:

hadoop-master:作为Active NameNode

haoop-slave01:  作为StandBy NameNode

hadoop-slave02: 作为DataNode,并且启动一个JournalNode、启动一个Zookeeper

hadoop-slave03: 作为DataNode,并且启动一个JournalNode、启动一个Zookeeper

hadoop-slave04: 作为DataNode,并且启动一个JournalNode、启动一个Zookeeper

其他软件:

Apache Hadoop 2.2.0、JDK1.6

3.2、修改配置文件

主要配置${HADOOP_HOME}/etc/hadoop/下的hdfs-site.xml。下面是一些配置参数以及说明:

(1)      dfs.nameservices

HDFS的命名服务逻辑名称,可以自己定义。在已经配置HA策略的HDFS会用到这个逻辑名称,同时该名称也会被基于HDFS的系统用,例如HBASE等。另外,如果需要启动HDFS Federation的话,可以通过该参数指定多个服务逻辑名称,用“,”作为分隔符。

我的配置如下:

<property>
   <name>dfs.nameservices</name>
    <value>mycluster</value>
    <description>Logical name forthis new nameservice</description>
</property>

(2)     dfs.ha.namenodes.[$nameserviceID]

命名服务下面包含的NameNode列表,可为每个NameNode 指定一个自定义的 ID 名称,比如命名服务 testCluster 下有两个 NameNode,分别命名为 nn1 和 nn2(到目前为止一个命名服务下最多包含2个NameNode),我的配置如下:

<property>    <name>dfs.ha.namenodes.testCluster</name>    <value>nn1,nn2</value>    <description>Unique identifiers for each NameNode in the nameservice </description></property>

(3)      dfs.namenode.rpc-address.[$nameserviceID].[$name node ID]

这个参数很容易理解,主要是为每个NameNode设置RPC地址,我的配置如下:

<property>
   <name>dfs.namenode.rpc-address.testCluster.nn1</name>
    <value>hadoop-master:8020</value>
</property>
<property>
   <name>dfs.namenode.rpc-address.testCluster.nn2</name>
   <value>hadoop-slave01:8020</value>
</property>

(4)      dfs.namenode.http-address.[$nameserviceID].[$name node ID]

这个参数主要是为NameNode设置对外的HTTP地址, 通过此配置的指定你可以执行在浏览器中管理HDFS界面等操作。我的配置如下:

<property>
    <name>dfs.namenode.http-address.testCluster.nn1</name>
    <value>hadoop-master:50070</value>
</property>
<property>
    <name>dfs.namenode.http-address.testCluster.nn2</name>
    <value>hadoop-slave01:50070</value> 
</property>

(5)      dfs.namenode.shared.edits.dir

设置一组JournalNode的URL地址,ActiveNameNode会将Edit Log写入这些JournalNode所配置的本地目录(可以用nfs等共享文件系统,由参数dfs.journalnode.edits.dir控制)中,而StandByNameNode通过DataNode的心跳通知去读取这些Edit Log,并且作用在内存中的目录树中,其配置格式为:qjournal://host1:port1;host2:port2;host3:port3/journalId,我的配置如下:

<property>
       <name>dfs.namenode.shared.edits.dir</name>
       <value>qjournal://hadoop-slave02:8485;hadoop-slave03:8485;hadoop-slave04:8485/testcluster</value>
        <description>journalNodeList</description>
</property>

(6)      dfs.journalnode.edits.dir

这个就是刚刚提到的JournalNode所在节点上的一个目录,用于存放 editlog 和其他状态信息,该参数只能设置一个目录,你可以对磁盘做 RIAD 提高数据可靠性。

<property>
       <name>dfs.journalnode.edits.dir</name>
        <value>/home/hadoop/hadoop-2.2.0/journal/node/local/data</value>
</property>

(7)      dfs.client.failover.proxy.provider.[$nameserviceID]

该参数设置HDFS客户端与ActiveName进行交互的JAVA实现类,HDFS客户端通过该参数来寻找到集群中的Active NameNode,此类默认实现ConfiguredFailoverProxyProvider,我的配置如下:

<property>
        <name>dfs.client.failover.proxy.provider.testcluster</name>
       <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>

(8)      dfs.ha.fencing.methods

这个参数比较重要,主要用于在主备节点切换时实现隔离机制的,在官方网站中做了相当详细的配置说明,其大概意思为:主备架构解决单点故障问题时,必须要认真解决的是脑裂问题,即出现两个 master 同时对外提供服务,导致系统处于不一致状态,可能导致数据丢失等潜在问题。在 HDFS HA中,JournalNode 只允许一个 NameNode 写数据,不会出现两个 Active NameNode 的问题,但是,当主备切换时,之前的 Active NameNode 可能仍在处理客户端的 RPC 请求,为此,需要增加隔离机制(fencing)将之前的 Active NameNode 杀死。HDFS 允许用户配置多个隔离机制,当发生主备切换时,将顺次执行这些隔离机制,直到一个返回成功。Hadoop 2.0 内部打包了两种类型的隔离机制,分别是 shell  和 sshfence。

1)sshfence方式

sshfence 通过 ssh 登录到前一个 ActiveNameNode 并将其杀死。为了让该机制成功执行,需配置免密码 ssh 登陆(注意:这个为主备节点配置双向的RSA免密码登陆),这可通过参数 dfs.ha.fencing.ssh.private-key-files 指定一个私钥文件。我的配置如下:

<property>
        <name>dfs.ha.fencing.methods</name>
       <value>sshfence</value>
</property>
<property>
       <name>dfs.ha.fencing.ssh.private-key-files</name>
       <value>/home/hadoop/.ssh/id_rsa</value>
</property>

另外,在设置一个超时时间,一旦 ssh 超过该时间,则认为执行失败。我的配置如下:

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

2)  shell方式(我没有采用这种方式)

执行自定义的Shell脚本命令隔离旧的ActiveNameNode。相比于sshfence方式,个人认为这种方式有个好处就是,你在shell脚本里边可以将之前的 Active NameNode 直接kill掉,然后立马启动NameNode,此时刚刚启动的NameNode就是立马处于一个StandBy状态,立马就可以进入HA状态,如果采用sshfence方式还要手动自己重启刚刚被kill掉的NameNode从而才能进入HA(这些的前提都是,采用手动HA方式,之前的Acitve NameNode不是宕机而仅仅是NameNode进程挂掉)。配置可以为:

<property>
   <name>dfs.ha.fencing.methods</name>
   <value>shell(/path/to/my/script.sh arg1 arg2 ...)</value>
</property>

注意, Hadoop 中所有参数将以环境变量的形似提供给该 shell,但所有的“.”被替换成了“_”,比如“dfs.namenode.rpc-address.ns1.nn1”变为“dfs_namenode_rpc-address”。

3.3、启动各种服务

HDFS集群进程启动的大概顺序为:启动所有的JournalNodeà启动nn1和nn2à启动所有DataNode。具体详细步骤如下:

(1)          启动所有JournalNode

在所有的配置有JournalNode的服务节点上,以我的配置就是在hadoop-slave02、hadoop-slave03和hadoop-slave04上分别执行:

$HADOOP_HOME/sbin/hdfs-daemon.sh startjournalnode

(2)          初始化JournalNode

此步骤要注意的是,如果你是将非HA HDFS的集群转化成为HA HDFS那么这一步骤就需要,如果都是HA HDFS就不需要执行此步骤。该步骤的主要作用是将非HA HDFS中NameNode的edit log去初始化JourNalnodes。具体操作在nn1上执行:

$HADOOP_HOME/bin/hdfs namenode -initializeSharedEdits [-force | -nonInteractive]。

此命令默认是交互式的,需要用户输入各种YOR N,如果嫌麻烦就直接执行:

$HADOOP_HOME/bin/hdfs namenode–initializeSharedEdits –force

(3)          启动nn1和nn2

子步骤1:

进入nn1,如果是新集群则format(注意,如果不是新集群千万不要format):

$HADOOP_HOME/bin/hadoop namenode -format

子步骤2:进入nn1,接着启动nn1:

hadoop-daemon.sh start namenode

子步骤3:进入nn2,执行下面命令让nn2从nn1上将最新的FSimage信息拉回来:

注意:如果是nn2的NameNode已经是被format掉了或者是将非HA HDFS的集群转化成为HA HDFS则不需要执行这一个步骤。

$HADOOP_HOME/bin/hdfs namenode -bootstrapStandby -force

子步骤4进入nn2,然后启动nn2:

hadoop-daemon.sh start namenode

子步骤5启动所有的DataNode

在各个DataNode节点执行:

hadoop-daemon.sh start datanode

或者直接在nn1节点直接执行:

hadoop-daemons.sh start namenode

各个服务到现在为止已经启动完毕,主备节点都还处于StandBy状态。我们可以看到主备节点的信息:

在这里说说一个遇到的“错误”问题,我在分别启动nn1和nn2之后,还没有将其中一个切换为Acive NameNode时,在nn1和nn2的日志上都报了以下这个“错误”:

其实这个错误信息完全可以不用管,出现这个问题原因上面信息已经很明显了,只要接下来将其中一个切换成Acive NameNode就ok了。

3.4、手动切换Active NameNode

nn1和nn2启动后都处于StandBy状态,此时都不能够对外提供服务,现在需要将nn1切换为Active NameNode,进入nn1节点输入:

$HADOOP_HOME/bin/hdfs haadmin-transitionToActive nn1

切换后我们再看看50070页面,nn1已经被切换为Active了:

在来看看之前还没有切换Acive NameNode的“错误”信息已经消失了,下面分别是nn1和nn2的日志信息,非常正常:

另外,如果你现在想将nn2转化为Acive NameNode,则在进入nn2所在节点,输入命令:

$HADOOP_HOME/bin/hdfs haadmin-failover --forcefence --forceactive nn1 nn2

看看nn2上的日志:

在这里说说我在切换时遇到过的几个小问题:

  • 在住备节点上一定要配置双向的RSA免密码登陆,不然再切换时会出错,sshfence方式不能找到旧的Active NameNode,直接被reject掉。
  • 第二,在切换的过程中我遇到了这个错误:

这个是权限问题,解决方法是直接在core-site.xml文件添加下面权限控制选项:

<property>
   <name>hadoop.http.filter.initializers</name>
    <value>org.apache.hadoop.security.AuthenticationFilterInitializer</value>
</property>
<property>
   <name>hadoop.http.authentication.type</name>
    <value>simple</value>
</property>
<property>
   <name>hadoop.http.authentication.token.validity</name>
    <value>36000</value>
</property>
<property>
   <name>hadoop.http.authentication.signature.secret.file</name>
    <value>/home/hadoop/hadoop-http-auth-signature-secret</value>
</property>
<property>
   <name>hadoop.http.authentication.cookie.domain</name>
    <value></value>
</property>
<property>
   <name>hadoop.http.authentication.simple.anonymous.allowed</name>
    <value>true</value>
</property>

然后建立/home/hadoop/hadoop-http-auth-signature-secret文件,并且在文件写入访问用户,我写入的是hadoop,然后将这个文件scp到各个节点,问题解决。

  • 如果你将Active NameNode从nn1转到nn2后,在各个DataNode日志出现一个“错误”信息:

其实这个是我意料之中的“错误”信息,其实是没有任何问题的。因为,当你的Acive NameNode从nn1切换至nn2时,nn1就会被kill(即hadoop-msater中的NameNode进程会被kill掉),在上面切换日志我标注红方框的地方已经很清楚了。此时,各个DataNode还是会同时向Active NameNode和StandBy NameNode同时发送心跳信息的,因为nn1已经被kill掉了,所有会报这个信息,对系统没有任何影响,切换后正常使用,如果你重启nn1则不会再报信息了,新启动的nn1是处于StandBy模式的。

我们知道,StandByNameNode是不处理DataNode的RPC请求的,那么各个DataNode为什么还会同时向Active NameNode和StandBy NameNode同时发送心跳呢?这是因为这2个心跳的用途是不同的,各个DataNode向Active NameNode发送心跳主要是汇报数据块的状态信息,而向StandBy NameNode发心跳的主要目的是通知StandBy NameNode告诉它Active NameNode元数据发生了改变,要求StandBy NameNode去QJM区下载更改过的Edit Log信息。

3.5、配置自动切换模式

自动切换模式的实现需要下面两个组建的额支持:

(1)      Zookeeper实例

需要质数个Zookeeper实例,在本集群我一个启用了3个Zookeeper实例,分别部署在hadoop-slave02、hadoop-slave03、hadoop-slave04中。

(2)      ZKFailoverController(简称“ZKFC”)

ZKFC 是一个 Zookeeper客户端,负责监控和管理 NameNode 的状态,每台运行 NameNode的机器上也会运行一个 ZKFC 进程。

  • 健康状况监控:

ZKFC 周期性地与本地的NameNode 交互,执行一些健康状况监测命令。

  • Zookeeper session 管理:

如果本地 NameNode 是健康的,则会持有Zookeeper 上一个 znode,如果它是 Active 的,会持有 zookeeper 的仅有的一个特殊 znode,该 znode 类型为 ephemeral,一旦 namenode 挂掉后,会自动消失。

  • 基于 zookeeper 的选举:

如果本地 NameNode 是活的,而没有其他 Namenode持有特殊的 znode,ZKFC 将尝试获取这个 znode,一旦获取成功后,则认为它“赢得了选举”,进而隔离之前的Active namenode,自己转换为新的 Active namenode。其大概结构如下图:

具体配置步骤:

步骤1:关闭集群修改hdfs-site.xml配置文件,增加自动切换选项:

<property>

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

<value>true</value>

</property>

步骤2:编辑core-site.xml文件,添加Zookeeper实例:

<property>

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

<value>hadoop-slave02:2181,hadoop-slave03:2181,hadoop-slave04:2181</value>

</property>

步骤3:启动节点上的zookeeper实例:

分别进入hadoop-slave02、hadoop-slave03、hadoop-slave04节点执行:

$ZOOKEEPER_HOME/bin/zkServer.sh start

Zookeeper实例对应的进程名为:

步骤4:初始化zookeeper。

注意:这个步骤是针对第一次启动zookeeper实例用的,如果你的zookeeper实例不是第一次启动则不需要执行此命令。

$HADOOP_HOME/bin/hdfs zkfc -formatZK

步骤5:启动 JournalNode、NameNode 和 DataNode。

步骤6:启动ZKFC。

分别进入hadoop-master和hadoop-slave1即在各个 NameNode 节点上执行:

$HADOOP_HOME/sbin/hadoop-daemon.sh startzkfc

ZKFC对应的进程名为:

要注意的一点是:我们最先启动的NameNode为Active NameNode。现在为止配置完毕,验证请看下面一小节。

4、 HDFS HA机制的可用性验证

4.1手动切换模式验证

这里我使用的验证方法主要是模拟ActiveNameNode进程死掉的情况,另外Active NameNode所在节点发生宕机的情况也是一样的。现在集群中nn1为Active NameNode,nn2为StandBy NameNode,具体步骤:

步骤1:进入nn1所在节点即hadoop-master,运行kill -9  $NameNodePID将nn1杀死(此时集群中只有一个StandByNameNode)。

步骤2:往集群上传文件,或者执行hadoop fs相关命令提示连接不到(此时,集群中没有Active NameNode来处理客户端的RPC请求)。看错误信息:

步骤3:恢复集群,将StandBy NameNode转换为Active NameNode。进入nn2所在节点即hadoop-slave01执行:

$HADOOP_HOME/bin/hdfshaadmin -transitionToActive nn2

此时,nn2已经变成为Active NameNode,看50070:

步骤4:再次执行hadoop fs相关命令或者上传文件,一切正常。

步骤5:另外,不要忘记集群虽然是恢复了,但是此时已经没有了StandBy NameNode了,这是直接进入nn1所在节点启动NameNode进程,此时nn1为Standby NameNode。

当目前为止,一起验证以及恢复已经完成。各个服务的日志也恢复了正常。

4.2、自动切换模式验证

自动切换模式的验证和手动切换基本一样,还是手动kill掉Active NameNode进程,观察集群是否会自动恢复,将备用节点转换为Active NameNode。经过测试,当手动kill掉Active NameNode后,Standby NameNode成功地自动转换为Active NameNode继续服务于个个DataNode。

参考文献:

[1] http://hadoop.apache.org/docs/r2.2.0/hadoop-yarn/hadoop-yarn-site/HDFSHighAvailabilityWithQJM.html

[2] http://www.sizeofvoid.net/hadoop-2-0-namenode-ha-federation-practice-zh/

[3] http://yanbohappy.sinaapp.com/?p=205

时间: 2024-10-12 21:31:17

利用QJM实现HDFS的HA策略部署与验证工作记录分享的相关文章

利用QJM实现HDFS自动主从切换(HA Automatic Failover)源码详析

最近研究了下NameNode HA Automatic Failover方面的东西,当Active NN因为异常或其他原因不能正常提供服务时,处于Standby状态的NN就可以自动切换为Active状态,从而到达真正的高可用 NN HA Automatic Failover架构图 为了实现自动切换,需要依赖ZooKeeper和ZKFC组件,ZooKeeper主要用来记录NN的相关状态信息,zkfc组件以单独的JVM进程的形式运行在NN所在的节点上.下面首先分析下NN的启动流程,NN对象在实例化过

Datax与hadoop2.x兼容部署与实际项目应用工作记录分享

一.概述 Hadoop的版本更新挺快的,已经到了2.4,但是其周边工具的更新速度还是比较慢的,一些旧的周边工具版本对hadoop2.x的兼容性做得还不完善,特别是sqoop.最近,在为hadoop2.2.0找适合的sqoop版本时遇到了很多问题.尝试了多个sqoop1.4.x版本的直接简单粗暴的报版本不兼容问题,其中测了sqoop-1.4.4.bin__hadoop-0.23这个版本,在该版本中直接用sqoop的脚本export HDFS的数据是没有问题的,但是一旦调用JAVA API来进行对H

使用组策略部署Configuration Manager客户端

为了减少IT运维成本,管理员通常不希望手动安装Configuration Manager客户端,这时可以利用强大的组策略自动部署Configuration Manager客户端,不需要人为干预. 1. 登陆DC服务器,点击工具,点击组策略管理 2. 创建"部署Configuration Manager客户端"GPO 3. 右键GPO,点击编辑 4. 点击计算机配置,扩展策略,右键管理模板,选择添加/删除模板 5. 点击添加Configuration Manager客户端部署模板 Con

HDFS副本放置策略

前言 前一篇文章中刚刚分析完HDFS的异构存储以及相关的存储类型选择策略,浏览量还是不少的,说明大家对于HDFS的异构存储方面的功能还是很感兴趣的.但是其实一个文件Block块从最初的产生到最后的落盘,存储类型选择策略只是其中1步,因为存储类型选择策略只是帮你先筛选了一些符合存储类型要求的存储节点目录位置列表,通过这些候选列表,你还需要做进一步的筛选,这就是本文所准备阐述的另外一个主题,HDFS的副本放置策略.在写本文之前,我搜过网上关于此方面的资料与文章,还是有许多文章写的非常不错的,所以我会

6.HDFS的HA机制的运作机制

HDFS的HA机制的运作机制和如何搭建高可用的集群环境

组策略部署软件

1.软件自动安装 升级 卸载 2.绿色软件 有弹性 3.自动化安装msi exe不能实现自动安装 卸载 升级 4.创建软件发布点 (共享文件夹) 5.给用户和计算机部署软件的区别 给计算机部署软件 计算机启动时安装 给用户部署软件 用户用软件时 才触发安装 登录时不安装 6.给用户部署软件 分配 出现软件的快捷方式 发布 不出现软件的快捷方式 7.使用组策略部署exe软件,让用户在程序安装中手动安装 1.通过zap文件指定安装文件的位置,指定给用户部署软件 8.通过组策略实现office的自动化

Rancher Server部署方式及Rancher HA环境部署

类似Rancher这种的容器管理和编排工具,它可以很快地让每个组织获得高效的弹性集群管理能力.当前技术世界的发展形势就是让开发人员从繁琐的应用配置和管理中解放出来,使用容器镜像来处理复杂的程序运行依赖库的需求,保证代码运行环境的一致性. 基于Docker和Rancher来运行弹性集群的一大关键点,就是运行Rancher高可用模式.本文将在介绍Rancher Server的几种部署方式的基础上,重点演示如何部署Rancher HA 环境,文末还有视频链接,可直接观看Demo视频噢(划重点)! 单节

利用JavaAPI访问HDFS的文件

body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI",Tahoma,Helvetica,Sans-Serif,"Microsoft YaHei", Georgia,Helvetica,Arial,sans-serif,宋体, PMingLiU,serif; font-size: 10.5pt; line-height: 1.5;}

Netfilter/Iptables Layer7 应用层过滤策略部署

Netfilter/Iptables Layer7 应用层过滤策略部署 环境:内核版本:Linux version 2.6.32-431.el6.x86_64 iptables版本:iptables v1.4.7 gcc版本:4.6.1 软件准备:wget http://download.clearfoundation.com/l7-filter/netfilter-layer7-v2.23.tar.gz wget https://www.kernel.org/pub/linux/kernel/