您的位置:首页 > 运维架构

使用QJM方式实现hadoop中的HA

2014-03-13 09:27 489 查看
好吧。。。我是文档控。。翻译了官网。。。。总觉得读官网才有原味。

HDFS 使用Quorum JournalManager实现高可用性(HA)

HDFS
High Availability Using the Quorum Journal Manager

Purpose

Note:
Using the Quorum Journal Manager or Conventional Shared Storage

Background

Architecture

Hardware resources

Deployment

Configuration overview

Configuration details

Deployment details

Administrative commands

Automatic Failover

Introduction

Components

Deploying ZooKeeper

Before you begin

Configuring
automatic failover
Initializing
HA state in ZooKeeper
Starting
the cluster with start-dfs.sh
Starting the
cluster manually
Securing access
to ZooKeeper
Verifying automatic
failover

Automatic Failover
FAQ

背景
Hadoop 2.0.0之前的版本, namenode存在单点失败问题. 一个namenode挂了,那整个集群都得等着救世主。
主要有两种原因导致namenode损坏:

机器受损,集群都不能重启namenode.
计划内的维护,比如软件或硬件的升级导致.

HDFS HA 特性通过使用多个namenode来解决上述问题,在用一个集群中,使用 Active的一个namenode以及多个standby的namenode..
架构(江湖)
在传统的HA 集群中, 两个分离的机器被配置为 NameNodes. 在任意时点,一定有一个namenode是Active 状态的(老大), 并且另一个是Standby 状态. 处于Active 状态的NameNode负责集群中所有的客户端请求, 而Standby状态的namenode只要像一个datanode似的, 调整好自己的状态随时准备着挺上一线战斗.
为保证两个namenode信息同步, 所有的节点都要和一组叫做"JournalNodes" (JNs董事会)的守护线程通信。当Active的那个namenode有任何变动,它都要通知这些JournalNodes的多数成员。而Standby状态的namenode就一直观察JournalNodes,只需读取JournalNodes的edit日志就可以了。当它看到这些日志,就在自己的namespace中执行相同命令。如果老大牺牲了,standby就能够保证自己成为老大前,已经有了和老大相同的实力。这就保证了这个集群,始终有老大,而且实力永远不减当年。
为了让交接位子的时间更短,standby必须掌握小弟弟们的最新信息,也就是集群中所有block的位置。为了达到这个目标,datanode就要知道所有namenode的位置,同时给所有的namenode发送信息。(这帮不忠诚的小弟。。。)
HA集群的操作必须要保证在任何时点只能有一个老大存在。否则,可能会出现数据丢失或者其他恶果。为了保证这个,防止所谓的一山有二虎(大脑分离)的情景出现,JournalNodes每次就只允许一个NameNode写数据。在交接过程中,即将成为老大的namenode会告诉JournalNodes一声,我要成为老大了,以防其他的standby的namenode对老大的位置也有野心。
硬件资源
要发布HA 集群, 作如下准备:

NameNode机器 - 所有的namenode的配置应该相同.

JournalNode machines - JournalNodes的守护进程是相当轻量级的, 所以这些守护线程或许会被客户的包括在其他hadoop守护线程里, 例如NameNodes, the JobTracker, 或者YARN资源管理器. 注意: 最少要有3个JournalNode守护线程, 这样才能实现edit日志写进多数的JNs. 如果有更多的节点的话,最好是单数个
(i.e. 3, 5, 7, etc.). 当有N个 JournalNodes时, 系统的容错量是(N - 1) / 2.

注意,standby的namenode也有对于namespace信息的checkpoints, 因此在HA集群中,Secondary NameNode, CheckpointNode, orBackupNode是不必要的. 事实上, 这样会出错. 这允许一个以前没有而现在正在使用HA的集群能够重用当前使用着的Secondary NameNode.
发布
配置概览
类似于Federation的配置, HA配置是向后兼容的并且当前节点不需要改变. The new configuration is designed such that all the nodes in the clustermay have the same configuration without the need for deploying differentconfiguration files to different machines based on the type
of the node.
就像HDFS Federation, HA clusters使用 nameservice ID 来标识一个单独的可能由许多namenode构成的HDFS实例。另外, NameNode ID 被用来区分不同的namenode。为实现单节点配置所有NameNodes, 相应参数以 nameservice ID也就是NameNode ID为后缀 .
配置细节
需要在 hdfs-site.xml 加几个参数.
顺序不重要, dfs.nameservicesdfs.ha.namenodes.[nameservice ID] 的值会决定一切. 因此,在其他参数之前,你应该考虑好以上两个变量的值.

dfs.nameservices - nameservice的逻辑命名

为nameservice起一个逻辑命名, 例如"mycluster", 然后使用这个逻辑命名去配置其他的参数. 可以随意命名. 它会被配置信息所用,也会在使用HDFS绝对路径访问当前集群时作为认证条件
注意: 如果你也在使用HDFS Federation, 这个配置应该也包含其他nameservices, HA或者其他的,以逗号隔开.
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>

dfs.ha.namenodes.[nameservice ID] - nameservice的唯一标识符

用逗号将nameservices隔开. 这个参数会被DataNodes用来识别集群中自己跟随的namenode. 例如,如果你使用"mycluster" 当做nameservice ID, 你想使用 "nn1" and "nn2" 当做这个nameservice中不同的NameNodes, 那就这样配置:
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
Note: 目前,每个 nameservice只能配置两个namenode;.

dfs.namenode.rpc-address.[nameservice ID].[name node ID] - 每个namenode监听的RPC address 的全路径

所有当前配置的NameNode IDs都需要设置. 这会有两个不同的配置. 如:
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>machine1.example.com:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>machine2.example.com:8020</value>
</property>
Note: 和这儿差不多,你现在也可以配置"servicerpc-address".
//下面的类似配置参考上面

dfs.namenode.http-address.[nameservice ID].[name node ID] - the fully-qualified HTTP address for each NameNode to listen on

Similarly to rpc-address above, set the addresses for both NameNodes' HTTP servers to listen on.For example:
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>machine1.example.com:50070</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>machine2.example.com:50070</value>
</property>
Note: 如果你打开了hadoop的安全特性, 那么也应该为每个namenode设置类似的https-address .

dfs.namenode.shared.edits.dir - 用来指明JNs的参数,NameNodes会读写这里的edits文件

虽然你必须指定几个JournalNode 的地址, you should onlyconfigure one of these URIs. URI格式: "qjournal://host1:port1;host2:port2;host3:port3/journalId".Journal ID是nameservice的唯一标识符, JournalNodes通过它来保证联邦系统的存储.
即便不是必须的,最好还是重用nameservice ID作为这个标识符.
例如, 如果当前集群的JournalNodes 在"node1.example.com","node2.example.com", 和 "node3.example.com" 运行,nameservice ID 是 "mycluster", 你应该设置如下值(JournalNode默认端口是 8485):
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://node1.example.com:8485;node2.example.com:8485;node3.example.com:8485/mycluster</value>
</property>

dfs.client.failover.proxy.provider.[nameservice ID] - HDFS 客户端用来和 Active NameNode通信的java类

配置一个java类,能够被DFS Client用来判断当前哪个namenode是active状态,也就是当前能为客户端提供服务的NameNode. 目前hadoop中的唯一实现类是 ConfiguredFailoverProxyProvider, 所以如果你不是自己写一个实现类的话就用它吧. 例子:
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>

dfs.ha.fencing.methods - 一系列用来防止Active NameNode失败的scripts

在任何给定时间,都应该只有一个active的namenode. 以下这点很重要, 当使用Quorum Journal Manager的时候, 只有一个NameNode能够向JournalNodes写数据,所以不可能出现大脑分裂(一山有二虎)导致文件系统错误.可是,当failover发生时,当前的Active NameNode 还是可以接受客户端的读信息的,所以有可能客户端会读到已经过期的数据。因此, 即便使用了Quorum Journal
Manager ,还是建议配置一些防护方法. 然而, 为了提高防护机制系统的可靠性, 建议配置防护方法来返回防护方法列表中的最后一个防护方法的成功信息. 如果你没有选择使用一些实际防护方法,你还是必须要为这个参数配置一些东西,比如说 "shell(/bin/true)".
这些防护方法被配置成运输和返回分离的列表,这样它们会保持顺序直到一个方法表名防护成功。Hadoop中有两种防护方法: shel和sshfence. 如果想了解怎么是限定值得防护方法,请参照theorg.apache.hadoop.ha.NodeFencer 类.

sshfence - SSH连接到Active NameNode杀死进程

sshfence 连接到目标节点杀死监听在服务TCP端口的进程. 为了使这个防护方法生效,必须实现免密码登陆。因此必须配置秘钥—— 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/exampleuser/.ssh/id_rsa</value>
</property>
也可以配置一个非标准的用户名或者端口来连接SSH. 为SSH配置一个以毫秒为单位的倒计时,如果超过这段时间就认为防护方法失败了。 配置如下:
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence([[username][:port]])</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>

shell - 跑任意一个shell命令来防护Active NameNode

The shell fencing method runs an arbitrary shell command. It may be configured likeso:
<property>
<name>dfs.ha.fencing.methods</name>
<value>shell(/path/to/my/script.sh arg1arg2 ...)</value>
</property>
'(' 和 ')'之间的字符串直接传进一个bash shell脚本,也可能不再括号里面。
这个shell脚本可以使用环境变量中的hadoop相关的变量, 使用'_' 替换配置参数中的每一个'.'. The configuration used has alreadyhad any namenode-specific configurations promoted to their generic forms -- 比如dfs_namenode_rpc-address 会包含目标节点的RPC地址, 尽管配置里已经指定了变量dfs.namenode.rpc-address.ns1.nn1.
Additionally, the following variables referring to the target node to befenced are also available:

$target_host
hostname of the node to be fenced
$target_port
IPC port of the node to be fenced
$target_address
the above two, combined as host:port
$target_nameserviceid
the nameservice ID of the NN to be fenced
$target_namenodeid
the namenode ID of the NN to be fenced
These environment variables mayalso be used as substitutions in the shell command itself. For example:
<property>
<name>dfs.ha.fencing.methods</name>
<value>shell(/path/to/my/script.sh--nameservice=$target_nameserviceid $target_host:$target_port)</value>
</property>
If the shell command returns an exit code of 0, the fencing is determinedto be successful. If it returns any other exit code, the fencing was notsuccessful and the next fencing method in the list will be attempted.
Note: This fencing method does not implement any timeout. If timeouts arenecessary, they should be implemented in the shell script itself (eg by forkinga subshell to kill its parent in some number of seconds).

fs.defaultFS - 当没有写啥的时候hadoopFS客户端默认使用的前缀。就是以前的fs.default.name

你现在可以为Hadoop clients 配置默认的路径,配置成新的启用HA的逻辑URI。如果我们以前使用"mycluster"作为nameservice ID, 那它就应该是我们所有HDFS路径认证的一部分. 在core-site.xml文件中应该这样配置:
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>

dfs.journalnode.edits.dir - JournalNode守护进程存储本地状态的目录

这应该是JournalNode机器上存储edits和其他本地信息的存储目录。 我们应该只是用一个目录。这个数据的冗余由多个分离的JournalNodes实现, 或者配置这个目录到一个本地的磁盘队列. 比如:
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/path/to/journal/node/local/data</value>
</property>
部署细节
当所有必须的配置信息都被配置好了以后,我们可以启动所有的JournalNode守护线程. 使用命令"hdfs-daemon.sh journalnode",然后等着每个对应机器上的守护线程都启动了。
一旦JournalNodes 启动, 有一个一点要初始同步两个HA NameNodes'的元数据信息.

如果你在搭建一个新的HDFS 集群, 就应该在某个namenode上先运行格式化命令 (hdfs namenode -format).

如果你已经格式化了NameNode, 或者正在转化一个集群到支持HA的集群, 就应复制原来的namenode上的元数据信息的目录到新的namenode上面,使用命令反格式化NameNode "hdfs namenode -bootstrapStandby"在未被格式化的NameNode上. 这个命令也能保证那些包含足够edits 动作的JournalNodes (dfs.namenode.shared.edits.dir)
能够启动所有的NameNodes.
如果你试图把一个不支持HA的NameNode转为支持, 运行命令 "hdfs -initializeSharedEdits", 它会初始化利用本地NameNode 的edits目录初始化 JournalNodes.

现在你可以启动所有的HA NameNodes.
你可以通过不同的HTTP地址分别查看每个NameNodes' 的web 界面. You should notice that next to theconfigured address will be the HA state of the NameNode (either"standby" or "active".) 任何时候HA NameNode启动后, 它都是一个standby.
管理员命令
Now that your HA NameNodes are configured and started, you will haveaccess to some additional commands to administer your HA HDFS cluster.Specifically, you should familiarize yourself with all of the subcommands ofthe "hdfs haadmin"
command. Running this command without anyadditional arguments will display the following usage information:
Usage: DFSHAAdmin[-ns <nameserviceId>]
[-transitionToActive <serviceId>]
[-transitionToStandby <serviceId>]
[-failover [--forcefence] [--forceactive]<serviceId> <serviceId>]
[-getServiceState <serviceId>]
[-checkHealth <serviceId>]
[-help <command>]
This guide describes high-level uses of each of these subcommands. Forspecific usage information of each subcommand, you should run "hdfshaadmin -help <command>".

transitionToActive and transitionToStandby - 状态之间的转变

These subcommands cause a given NameNode to transition to the Active orStandby state, respectively. 这些命令不会被防护,所以很少使用. 相反,"hdfs haadmin -failover" 应该被频繁的使用才对.

failover -在两个NameNodes之间开始 failover(失效备援)

这个命令会产生一个failover. 如果第一个NameNode 是Standby 状态, 这个命令仅仅会无错误地使第二个namenode过渡成为Active state状态. 如果第一个 NameNode是Active 状态, 它会优雅地把自己转成Standby状态. 如果这个命令失败, 防护方法就会按照顺序执行,直到成功 (as configured by dfs.ha.fencing.methods). 第二个NameNode 必须经过这个过程才能被转化为Active状态.如果防护方法一个都没成功,
第二个 NameNode就转不成Active, 而且还会返回错误信息.

getServiceState - 得到当前NameNode的状态信息。Active或者Standby

Connect to the provided NameNode to determine its current state, printingeither "standby" or "active" to STDOUT appropriately. 这个命令可能会用来执行基于namenode当前状态的 cron jobs 或者监听脚本.

checkHealth - check the health of the given NameNode

Connect to the provided NameNode to check its health. NameNode有自我诊断能力, 包括检查自己的内部服务是否如期运行着. 返回0代表健康,否则相反. 一般也是在监控namenode时使用这个方法.
Note: 目前这个命令官方还没有完成,除非NameNode 完全关闭, 不然总是返回成功信息.
自动 Failover(失效备援)
介绍
以上介绍了怎么手动Failover. 在那个模式, 当active的namonode出现故障,系统不会自动触发failover,转变standby状态的 NameNode为active. 这一部分就是介绍如果实现系统自动failover了.
组件
Automatic failover 加入了两个新的组件HDFS deployment: 一个是ZooKeeper quorum, 另一个就是ZKFailoverController 线程 (简称ZKFC).
Apache ZooKeeper能够为维护少量合作数据提供高可用性的服,他会通知客户端这些少量数据中的任何变化. Automaticfailover就是依靠ZooKeeper 来实现:

Failure detection -每一个NameNode机器都与ZooKeeper维持着一个长对话. 如果这个机器down了, 它与ZooKeeper的对话就会过期, ZooKeeper就会通知其他NameNode是时候来顶替老大的位置了.

Active NameNode 选举 - ZooKeeper提供一个简单的机制来选举老大. 另一个拥有排它锁的namenode会得到 ZooKeeper的赏识成为下一个老大active.

ZKFailoverController (ZKFC)是一个新的ZooKeeper客户端,用来监控和管理NameNode的状态. 每一个NameNode的机器上 都有 ZKFC, 它的任务是:

健康监视Health monitoring - ZKFC 会在指定时间段使用一个健康检查方法pings本地的NameNode. 只有NameNode在一定时间内返回一个健康的状态, ZKFC才会认为它是健康的. 如果当前节点down掉了, 冻结了, 或者进去其他不健康的状态,ZKFC这个监听者就把它标记为非健康状态.

ZooKeeper session 管理 - 本地NameNode健康的时候, ZKFC会与ZooKeeper保持一个长对话. 如果本地NameNode是active, 它会有一个特殊"lock"的 znode. This lock uses ZooKeeper's support for "ephemeral" nodes; 如果对话过期, 这把锁会自动删除.

ZooKeeper-选举- 如果本地NameNode 是健康态, ZKFC 发现没有其他节点拿到 lock znode, 它就会获取这个 lock. 如果成功获取, 它就赢得了选举,负责运行一个failover来让本地namenode接替老大的位置. failover 过程和前面手动的一样: 首先, 如果需要防护的话,那以前的active就被防护着, 然后本地NameNode转变到active 状态.

For more details on the design of automatic failover, refer to the designdocument attached to HDFS-2185 on the Apache HDFS JIRA.
部署 ZooKeeper
In a typical deployment, ZooKeeper daemons are configured to run on threeor five nodes. Since ZooKeeper itself has light resource requirements, it isacceptable to collocate the ZooKeeper nodes on the same hardware as the HDFSNameNode and Standby
Node. Many operators choose to deploy the third ZooKeeperprocess on the same node as the YARN ResourceManager. It is advisable toconfigure the ZooKeeper nodes to store their data on separate disk drives fromthe HDFS metadata for best performance and isolation.
The setup of ZooKeeper is out of scope for this document. We will assumethat you have set up a ZooKeeper cluster running on three or more nodes, andhave verified its correct operation by connecting using the ZK CLI.
开始之前
关闭集群先,然后配置,之后重启才行.
配置automatic failover
在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>zk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181</value>
</property>
这是所有运行着的ZooKeeper 的列表.
就像前面文档中描述的一样,这些配置参数也可以为每个不同的nameservice配置不同的信息。比如,在一个联邦集群中,可以仅仅指定一个nameservices的automatic failover: dfs.ha.automatic-failover.enabled.my-nameservice-id.
初始化ZooKeeper中的 HA 状态
在任意一个NameNode的主机运行如下命令.
$ hdfs zkfc -formatZK
这回在ZooKeeper中建立一个znode,automatic failover系统把它的数据存在这个znode中.
启动集群 start-dfs.sh
配置好以上信息后,start-dfs.sh会在每一个NameNode上自动启动一个 ZKFC 守护线程. ZKFCs启动后, 它们会自动选一个NameNodes 作为老大active.
启动集群
如果你在你的集群上手动管理这些服务,那就在每个namendoe上手动启动这些ZKFS守护线程。:
$ hadoop-daemon.shstart zkfc
安全访问ZooKeeper
如果你正在运行一个启动安全机制的cluster, 那你会希望ZooKeeper 上储存的数据也是安全的. 这样能防止一些恶意的客户端修改ZooKeeper上存储的元数据信息,或者蓄意触发错误的failover。
在core-site.xml中添加如下参数:
<property>
<name>ha.zookeeper.auth</name>
<value>@/path/to/zk-auth.txt</value>
</property>
<property>
<name>ha.zookeeper.acl</name>
<value>@/path/to/zk-acl.txt</value>
</property>
请注意'@' -- 这说明这些配置不是内联的,而是指向一个硬盘上的文件.

第一个参数等同于在ZK CLI中使用的形式. 例如你会这样做:
digest:hdfs-zkfcs:mypassword
... hdfs-zkfcs是 ZooKeeper的一个唯一的用户名, mypassword 就是密码.
然后,生成一个 ZooKeeper ACL对应这个authentication:
$ java -cp$ZK_HOME/lib/*:$ZK_HOME/zookeeper-3.4.2.jar org.apache.zookeeper.server.auth.DigestAuthenticationProviderhdfs-zkfcs:mypassword
输出:hdfs-zkfcs:mypassword->hdfs-zkfcs:P/OQvnYyU/nF/mGYvB/xurX8dYs=
复制'->' 后面的字符串到zk-acls.txt里面, 并且以"digest:"为前缀. 例如:
digest:hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=:rwcda
为了使这些ACLs生效, 你应该再运行zkfc -formatZK命令.
完成上述工作,我们可以使用ZK CLI检验一下ACLs:
[zk:localhost:2181(CONNECTED) 1] getAcl /hadoop-ha
'digest,'hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=
: cdrwa
确认 automatic failover
一旦设置了automatic failover,我们就应该验证一下。首先定位active状态的NameNode. 这个可以从namenode的web界面看到.找到这个namenode之后,就可以引发这个节点的失败来进行测试了,比如可以使用kill -9 <pid of NN>命令来模仿JVM崩溃,或者可以断掉这台机器的电源,或者拔掉 这个机器的网线。这样之后,几秒钟内,应该会出现新的active的namenode。别的节点发现当前节点失败的时间间隔取决于参数 ha.zookeeper.session-timeout.ms,
默认是5 秒.
如果没成功,那就是配置有问题. 检查zkfc守护线程的日志、NameNode 守护线程的日志来休整。
Automatic Failover 频繁提出的问题

Is it important that I start the ZKFC and NameNode daemons in any particular order?

只有启动了namenode之后,才能启动对应的ZKFC。
No. On any given node you may start the ZKFC before or after itscorresponding NameNode.

What additional monitoring should I put in place?

可以监听一下ZKFC是否一直在运行。有时候ZooKeeper出现错误,而ZKFC不会退出,那它应该被重启。另外,应该监听ZooKeeper quorum中的每一个成员,如果ZooKeeper完蛋了,automatic failover就没作用了。
You should add monitoring on each host that runs a NameNode to ensure thatthe ZKFC remains running. In some types of ZooKeeper failures, for example, theZKFC may unexpectedly exit, and should be restarted to ensure that the systemis ready for
automatic failover.
Additionally, you should monitor each of the servers in the ZooKeeperquorum. If ZooKeeper crashes, then automatic failover will not function.

What happens if ZooKeeper goes down?

如果ZooKeeper真完蛋了,就不会触发automatic failover了。然而,HDFS还是可以正常运行,不会造成任何影响。ZooKeeper重启后,HDFS会自己再去连接。

Can I designate one of my NameNodes as primary/preferred?

现在还不能指定。第一个启动的namenode会成为active的,只能通过改变启动次序达到目的。
No. Currently, this is not supported. Whichever NameNode is started firstwill become active. You may choose to start the cluster in a specific ordersuch that your preferred node starts first.

How can I initiate a manual failover when automatic failover is configured?

即便配置了automatic failover,你还是可以通过使用hdfs haadmin命令来进行手动触发failover。
Even if automatic failover is configured, you may initiate a manualfailover using the same hdfs haadmin command. It will perform a coordinated failover.

如有错误,敬请指明! Any suggestions will be appreciated!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: