NameNode HA With QJM(使用QJM实现HDFS高可用)

程序猿码码

发布时间:18-04-2706:09

Apache Hadoop 2.9.0

翻译自原文:

http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HDFSHighAvailabilityWithQJM.html

(如果转发,请标明出处)

目的

本指南描述了HDFS HA的特性以及如何使用QJM(Quorum Journal Manager)来配置和管理HA HDFS集群。

文章假设读者已经对HDFS集群的组件和节点类型有一定的了解,请查看HDFS架构手册了解HDFS集群详细信息。

Note:使用QJM或者常规共享存储(Conventional Shared Storage)

本指南描述HDFS HA特性如何通过配置和使用QJM来在Active NameNode和Standby NameNode中间共享edit日志。如果想获得如何配置HDFS HA使用NFS来作为共享存储而不是使用QJM,请查看http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HDFSHighAvailabilityWithNFS.html。

背景

在Hadoop 2.0.0之前,在一个HDFS集群中,NameNode是一个单一的节点,可能引起单点故障问题(SPOF)。一个集群只有一个NameNode,如果机器或者进程不可用,那么整个集群将会不可用直到NameNode重启或者在另外的机器启动NameNode。

这将影响HDFS集群的高可用性,主要体现在2个方面:

1. 一个计划外的事件发生例如机器故障,那么整个集群在运维人员重启NameNode之前都不可用。

2. 计划内的维护事件例如NameNode机器的软件或者硬件升级,将会导致整个集群停工。

HDFS HA特性使用在一个集群中提供2个NameNode来解决上述问题,让Active/Passive NameNode之间进行热备份。这样当一个机器故障或者管理者在系统运维过程中主动友好发起故障时,允许立即切换到一个可用的NameNode。

架构

在一个典型的HA集群中,2个单独的机器被配置为NameNode。任意时间点,一个NameNode是Active状态,另一个是Standy状态。集群中客户端发来的请求都会由Active NameNode来负责,而Standby节点只是一个简单从节点,保存集群中的状态数据来作为故障切换时备用。

为了让Standy 节点和Active节点的状态同步,2个节点都同时和一组单独的称为JournalNodes(JNs)的后台程序进行通信。当Active 节点的任意命名空间被更改时,一条描述本次更改的持久化的日志就会被写入大部分的JNs。Standby节点能够读取JNs的这些edit,周期性的查看edit log的变化,一旦Standby节点查看到edit,就立刻应用到自己的命名空间。当故障发生时,Standby在自己变成Active 状态之间能够保证从JounalNodes 读完所有的edits,这样就能保证命名空间的状态跟故障发生之前完全同步。

为了提供一个快速的故障切换,Standy节点必须包含集群中文件块的最新的位置信息,为了实现这一目的,DataNode会和2个NameNode都配置好,同时向2个NameNode发送心跳和文件块位置信息。

任意时刻一个HA集群中只有一个NameNode是至关重要的,否则命名空间会在2个节点之间快速分割,导致数据丢失或者造成不正确的结果。为了保证这一特性避免发生所谓的“split-brain scenario”,JournalNodes 只允许同一时间只有一个NameNode是写状态。当故障发生主备切换时,即将变成active的NameNode就会很容易接管向JournalNodes 的写权限,同时阻止另一个NameNode继续维持Active状态,这样就能够保证安全的切换到新的Active节点。

硬件资源

为了部署HA集群,你需要提供如下资源:

① NameNode 机器 -- 需要运行Active /Standy NameNode的机器需要各自拥有同等的硬件,2台机器之间硬件完全独立,并且和non-HA集群的机器条件大致等同。

② JournalNode 机器 -- 这些机器将用来运行JournalNode。JournalNode 后台程序是非常轻量级的。所以这些后台程序可以和其他hadoop的后台程序合理的分配到一起,例如NameNodes, the JobTracker, or the YARN ResourceManager。Note:因为edit log需要写入多数派的JNs,所以至少需要3个JournalNode 后端程序,这样就能让系统避免单一机器引发的错误。你也可以运行多于3个JournalNode ,但是为了增加系统可以容忍的错误数目,你可以使用奇数数目的JNs(例如3,5,7等等)。当运行N个JournalNode ,系统最多可容忍 (N - 1) / 2个故障并且不影响工作。

需要注意的是,在一个HA集群中,Standby NameNode一样会执行命名空间的checkpoint操作,因此在HA集群中不需要运行Secondary Namenode,CheckpointNode, 或者 BackupNode,事实上,如果运行这些将会导致错误。这就允许重新配置一个non-HA-enabled HDFS cluster变成HA-enabled 集群时能够继续使用之前 属于Secondary NameNode的硬件资源。

部署

配置概述

和HDFS Federation类似,HA配置是向后兼容的,并且允许已经存在的单一NameNode配置继续工作而不需要修改。新的配置设计成集群中所有节点有同样的配置,这样就不需要为同类型的节点在不同机器上分别部署分发不同的配置文件。

跟HDFS Federation类似,HA集群复用nameservice ID 来标识一个单一的HDFS实例(事实上它可能包含多个HA Namenodes)(注意,这个地方是很多HA集群,因为单点NameNode资源有限,所以整个Hadoop集群机器数量受限,但是,现在的Hadoop已经支持多个HA集群,解决了单个NameNode的问题 -- by 程序猿码码),额外HA增加了一个抽象的ID:NameNode ID ,用来区分集群中不同的NameNode。为了所有的NameNode节点使用统一的配置文件,相关的配置文件参数后面都会添加nameservice ID和NameNode ID的后缀。

配置细节

为了配置HA NameNodes,你必须添加一些配置选项到hdfs-site.xml配置文件。

配置的顺序是不重要的,但是dfs.nameservices 和 dfs.ha.namenodes.[nameservice ID] 的数值将会决定下面的Key,在设置余下的配置选项之前,你必须决定dfs.nameservices 和 dfs.ha.namenodes.[nameservice ID] 的数值。

l dfs.nameservices - 新nameservice的逻辑名字

为当前nameservice选择一个逻辑名字,比如“mycluster”,并且在配置选项中使用这个逻辑名字。这个名字可以任意,它将被用到配置文件中以及集群中HDFS path授权组件中。

Note:如果你使用 HDFS Federation,配置文件中同样需要包含其他的nameservices(他们是使用逗号分隔的列表),例如HA或者其他。

<property>

<name>dfs.nameservices</name>

<value>mycluster</value>

</property>

l dfs.ha.namenodes.[nameservice ID] - nameservice中每个NameNode的唯一标识

配置一个逗号分隔的NameNode IDs列表,这个列表可以方便DataNode来确定集群中的所有NameNodes。例如,你之前使用“mycluster”来作为nameservice ID ,使用“nn1” and “nn2”来作为NameNodes ID,你可以这样配置:

<property>

<name>dfs.ha.namenodes.mycluster</name>

<value>nn1,nn2</value>

</property>

Note:当前,每个nameservice最多可以配置2个NameNode。

l dfs.namenode.rpc-address.[nameservice ID].[name node ID] - 每个NameNode 监听的完全合格的RPC地址。

对于之前配置的两个NameNode ID,请设置NameNode 进程的完整地址和IPC端口。请注意,这将导致两个单独的配置选项。例如:

<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”

l dfs.namenode.http-address.[nameservice ID].[name node ID] -每个NameNode 监听的完全合格的HTTP address

和上面的 rpc-address类似,为2个NameNodes的HTTP servers设置监听的地址,例如:

<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 。

l dfs.namenode.shared.edits.dir -NameNodes读写edits的一组JNs的URI。

这个配置选项用来配置提供共享edits存储的JournalNodes 的地址,Active NameNode来进行写入,Standby NameNode来读取Active NameNode对文件的更改来同步保持内容的更新。这里,你需要指定一系列的JournalNode地址,并且是只能配置一个URI选项,这个URI的格式是这样的: qjournal://*host1:port1*;*host2:port2*;*host3:port3*/*journalId*Journal ID 是namespace内的唯一标识,允许一个单一的JournalNodes 集合为多个federated namesystems提供存储。复用nameservice ID来标识journal 不是必须的,但是仍然是个好主意。(这个地方好晦涩难懂)

例如,如果当前集群的JournalNodes 运行在机器“node1.example.com”, “node2.example.com”, and “node3.example.com”,并且nameservice ID were “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>

l dfs.client.failover.proxy.provider.[nameservice ID] -HDFS客户端与Active NameNode交互使用的Java class。

配置 HDFS客户端使用的Java class,这个Java class能够判断哪个NameNode当前是Active,也就是哪个NameNode当前可以提供服务。目前两种实现方式是ConfiguredFailoverProxyProvider 和RequestHedgingProxyProvider(第一次呼叫,同时唤起所有namenode来决定哪个active,后面的请求中,一直访问active namenode直到故障切换)。你如果不使用惯例的proxy,你可以选择上面2种方式之一。例如:

<property>

<name>dfs.client.failover.proxy.provider.mycluster</name>

<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>

</property>

l dfs.ha.fencing.methods -在failover期间用来隔离Active Namenode的脚本或者java class

任意时刻系统中只有一个NameNode处于Active状态是非常令人满意的,也是非常正确的。重要的是,当使用QJM时,只有一个NameNode被允许写入JournalNodes,这样就避免了split-brain scenario情况下文件系统元数据的切分损坏。但是,当主备切换时也有可能发生这种情况:先前Active NameNode正在为客户端提供读服务,直到这个NameNode尝试写入JournalNodes时才能shut down,那么读取的那部分数据可能不是最新的数据。如果使用QJM,那么这种情况下就需要配置一些fence的方法。即使fence机制也可能是失败的,但是它确实提高了系统的高可用性,注:如果没有实际的fence方法,仍然必须配置此设置的东西,例如“shell(/ bin / true)”。

故障切换期间使用的隔离方法配置为回车分隔列表,在故障切换过程中,在arriage-return-separated列表中的fence方法将被依次尝试使用,直到一个fence方法成功。Hadoop提供了两种方法:ssh和sshfence。如果需要自己实现fence,需要参考org.apache.hadoop.ha.NodeFencer class。

sshfence - ssh 登录到 Active NameNode并且杀死进程

SSH使用sshfence 选项登录到目标节点,并且使用fuser 杀死监听在TCP端口上的进程。为了fence 选项起作用,必须能够ssh无密码登录到目标机器中,所以必须配置dfs.ha.fencing.ssh.private-key-files(一个逗号分隔的SSH private key 文件),例如:

<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超时时间,超过了规定的时间,fence方法就会认为执行失败,可以参考如下配置:

<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 --- 执行任意的脚本来隔离Active NameNode。

Shell 隔离方法必须是一个单独的shell 命令,可以如下配置:

<property>

<name>dfs.ha.fencing.methods</name>

<value>shell(/path/to/my/script.sh arg1 arg2 ...)</value>

</property>

括号中间的字符串会被直接传递给bash shell,并且不能包含任意右括号。

Shell命令可以在包含当前Hadoop配置变量的环境下运行,在配置文件变量中使用‘_’ 代替‘.’ 。所使用的配置选项已经将任何特定于NameNode的配置升级到其通用形式 -- 例如 dfs_namenode_rpc-address 是目标节点的RPC地址,变量定义成了这个样子 dfs.namenode.rpc-address.ns1.nn1。

下面是需要fance的目标节点相关变量,这些变量也是可用的:

$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

环境变量也可以在shell命令行中被替换掉,例如:

<property>

<name>dfs.ha.fencing.methods</name>

<value>shell(/path/to/my/script.sh --nameservice=$target_nameserviceid $target_host:$target_port)</value>

</property>

如果shell命令返回0,那么说明隔离执行成功,如果返回其他的exit code,那么就是没有执行成功,这样会继续尝试执行列表中的下一个隔离方法。

Note:隔离方法并不一定有超时时间间隔。如果超时时间间隔必须设置,那么需要在shell脚本中自己实现(例如fork一个subshell若干秒后来杀掉父进程)。

l fs.defaultFS - Hadoop FS客户端使用的默认目录前缀

你可以为Hadoop 客户端使用新的 HA-enabled 逻辑的URI提供默认的目录前缀,这是一个可选项。如果你之前使用了“mycluster” 作为nameservice ID,那么这将作为你的HDFS 目录授权认证的一部分。可以在你的 core-site.xml 中这样进行配置:

<property>

<name>fs.defaultFS</name>

<value>hdfs://mycluster</value>

</property>

l dfs.journalnode.edits.dir - JournalNode 后端程序存储本地状态的目录

这是一个JournalNode 机器上的绝对目录,这个目录下存放着JNs使用的edits和一些本地状态。这个选项只能配置一个单一的目录。实现这些数据的冗余可以运行多个JournalNodes,也可以配置目录到一个locally-attached RAID array。例如:

<property>

<name>dfs.journalnode.edits.dir</name>

<value>/path/to/journal/node/local/data</value>

</property>

部署细节

在必要的配置选项设置好以后,你必须启动JournalNode所在机器上的后端程序。启动后端程序可以通过运行命令行“hadoop-daemon.sh start journalnode”来实施,同时等待后端程序在每个相关机器上启动。

一旦JournalNodes 成功启动,必须首先同步2个HA NameNode磁盘上的元数据。

l 如果是建立一个新的HDFS集群,则应在其中一个NameNode上运行format命令(hdfs namenode -format

l 如果已经format了NameNode,或者正在将一个non-HA-enabled集群转变成一个 HA-enabled集群,那么你需要将一个NameNode元数据目录拷贝到另一个NameNode。然后在unformatted NameNode上执行命令“hdfs namenode -bootstrapStandby”。运行这个命令必须保证JournalNodes (as configured by dfs.namenode.shared.edits.dir) 包含足够多的edits来启动2个NameNode。

l 如果正在将一个non-HA NameNode转变成HA NameNode,可以运行命令 “hdfs namenode -initializeSharedEdits”,这个命令将会使用本地的 NameNode edits 目录中的edits 数据初始化JournalNodes 。

这时,就可以像平时启动一个NameNode一样启动2个 HA NameNodes。

可以通过配置的HTTP 地址来分别访问每个NameNode的网页来获得NameNode的相关信息。你需要注意的是,配置的地址旁边将是NameNode的HA状态(“standby”或“active”)。每当HA NameNode 启动时,它最初都处于Standby 状态。

管理员命令

当HA NameNodes 已经配置好并启动了,我们就可以通过额外的命令来管理HA HDFS集群。具体来说,我们应该熟悉“hdfs haadmin”命令的所有子命令。在没有任何参数的情况下运行此命令将显示使用的相关信息:

Usage: haadmin

[-transitionToActive <serviceId>]

[-transitionToStandby <serviceId>]

[-failover [--forcefence] [--forceactive] <serviceId> <serviceId>]

[-getServiceState <serviceId>]

[-getAllServiceState]

[-checkHealth <serviceId>]

[-help <command>]

本指南介绍这些子命令的高级用法。对于每个子命令的特定使用信息,可以执行 “hdfs haadmin -help <command>”来进行查看。

l transitionToActive and transitionToStandby -将指定NameNode的状态装换成Active或者Standby。

这些子命令分别导致给定NameNode转换到Active或Standby状态。这些命令不会尝试执行任何隔离,因此很少使用。相反,大家总是喜欢使用“hdfs haadmin -failover”子命令。

l failover - 启动2个NameNode之间的故障切换

此子命令导致从第一个提供的NameNode故障切换到第二个的NameNode。如果第一个NameNode处于Standby 状态,此命令将简单地将第二个转换为Active 状态,整个过程并不会出错。如果第一个NameNode处于Active 状态,将尝试将其优雅的转换为Standby 状态。如果失败,将按顺序尝试隔离方法(由 dfs.ha.fencing.methods配置)直到一个方法能够执行成功。只有在此过程之后,第二个NameNode才会转换为Active 状态。如果没有隔离方法执行成功,则第二个NameNode将不会转换为Active 状态,并返回错误。

l getServiceState -确定指定的NameNode的状态是Active 还是Standby

连接到指定的NameNode以确定其当前状态,将“Standby”或“Active ”状态打印到标准输出。需要根据NameNode当前处于Active 状态还是Standby状态来执行不同的操作的cron作业或监控脚本可能会使用此子命令。

l getAllServiceState -返回所有NameNode的状态

连接到已配置的所有NameNode来确定当前状态,将“standby” or “active”适当打印到标准输出STDOUT。

l checkHealth - 检测给定NameNode的运行状况

连接到提供的NameNode以检查其运行状况。NameNode能够对自身执行某些诊断,包括检查内部服务是否按预期运行。如果NameNode运行正常,此命令将返回0,否则返回非零值。可以使用此命令来对NameNode运行状态进行监控。

Note:当前这个功能还没有实现,除非给定的NameNode完全挂了,否则目前始终返回成功。

自动故障迁移

介绍

以上各节介绍了如何配置手动故障切换。在该模式下,即使active节点发生故障,系统也不会自动触发从active NameNode到standy NameNode的故障切换。本节介绍如何配置和部署自动故障切换。

组件

自动故障切换需要在HDFS部署中增加2个新的组件:一个ZooKeeper quorum和ZKFailoverController 进程(缩写为ZKFC)。

Apache ZooKeeper是一个高可用的服务,ZooKeeper维护少量的协调数据,通知客户端数据更改以及监控客户端故障。自动HDFS故障切换依赖ZooKeeper来完成如下任务:

l 故障检测 - 集群中的每个NameNode机器都和ZooKeeper维持一个长连接。如果机器故障,ZooKeeper的会话(session)就会过期,通知其他NameNode应触发故障切换。

l Active NameNode选择 - ZooKeeper提供了一种简单的机制来专门选择一个NameNode作为Active NameNode。如果当前Active的NameNode崩溃,另一个NameNode可能在ZooKeeper中获得一个特殊的独占锁,指示它应该成为下一个Active的NameNode。

KFailoverController ( ZKFC )是一个新的组件,它是一个ZooKeeper客户端,也监视和管理NameNode的状态。运行NameNode的每台计算机也运行一个ZKFC,并且ZKFC负责:

① 运行状况监控- ZKFC定期ping本地NameNode,使用运行状况检查命令进行查验。只要NameNode是健康状态并及时响应,ZKFC就会认为NameNode正在正常运行。如果节点已崩溃、冻结或以其他方式进入不正常状态,运行状况监控器将其标记为不正常。

② ZooKeeper 会话管理 - 当本地NameNode健康运行,ZKFC会和ZooKeeper保持一个打开的会话。如果本地NameNode处于Active 状态,则它还持有特殊的“锁”znode。此锁使用ZooKeeper对“ephemeral”节点的支持;如果会话过期,将自动删除锁定节点。(这部分最好结合看下ZooKeeper相关介绍)

③ 基于ZooKeeper的选择-如果本地NameNode运行正常,并且ZKFC发现当前没有其他节点持有znode的锁,则它将自己尝试获取锁。如果成功,它将“赢得选举”,并负责运行故障切换以使其本地NameNode处于Active状态。故障切换过程类似于上述手动故障切换:首先,如有必要,前一个Active NameNode将被隔离,然后本地NameNode将转换到Active状态。

如果想了解更多的自动故障切换的详情,请查看 Apache HDFS JIRA上的HDFS-2185相关的设计文档。

部署ZooKeeper

在一个典型的部署中,ZooKeeper后端程序部署到三个或五个节点上运行。由于ZooKeeper本身具有较轻的资源需求,因此可以将ZooKeeper节点与HDFS Active NameNode和Standby NameNode配置在同一硬件上。许多运维人员选择在与YARN ResourceManager相同的节点上部署第三个ZooKeeper进程。建议将Zookeeper的数据存放在和HDFS元数据不同的磁盘上,以获得最佳性能和隔离。

Zookeeper的设置超出了本文档的范围。我们假设您已经设置了一个在三个或更多节点上运行的ZooKeeper集群,并且已经通过使用ZK CLI连接验证了集群正常运行。

开始之前

在配置自动部署之前,必须关闭整个集群。目前在集群正常运行的情况下,还不能从手动故障切换转换成自动故障切换。

配置自动故障切换

自动故障切换需要增加2个新的变量:

在 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 service服务的集群的主机名和端口号。

与本文档前面描述的参数一样,这些设置可以通过在配置key后加上nameservice ID的后缀来为每个nameservice 进行配置。例如,在启用federation 了的集群中,您只需要设置dfs.ha.automatic-failover.enabled.my-nameservice-id. 来实现nameservices 的自动故障切换的设置。

还有几个其他配置参数可以设置为控制自动故障切换;但是,它们对于大多数安装不是必需的。有关详细信息,请参阅 configuration key的特定文档。

在ZooKeeper中初始化HA状态

添加完配置变量后,下一步就是在ZooKeeper中初始化所需的状态。可以通过从其中一个NameNode主机运行以下命令来执行此操作。

[hdfs]$ $HADOOP_PREFIX/bin/hdfs zkfc -formatZK

这将在ZooKeeper中创建一个znode,自动故障切换系统将在其中存储数据。

运行start-dfs.sh来启动集群

由于配置中已启用自动故障切换,因此 start-dfs.sh 脚本现在将在任何运行NameNode的计算机上自动启动ZKFC后端程序。当ZKFCs启动时,它们将自动选择一个NameNode成为active节点。

手动启动集群

如果是手动管理集群,那么需要手动启动每台NameNode上的zkfc后端程序,可以使用下面的命令行

[hdfs]$ $HADOOP_PREFIX/sbin/hadoop-daemon.sh --script $HADOOP_PREFIX/bin/hdfs start zkfc

secure (安全)访问ZooKeeper

如果正在运行的是一个secure集群,则可能需要确保在ZooKeeper中的信息也是secure的。这样可防止恶意客户端修改ZooKeeper中的元数据,也能防止恶意客户端触发故障切换。

为了保证ZooKeeper中的信息安全,首先需要在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>

请注意这些值中的 ‘@’字符-这指定配置不是内联(inline)的,而是指向磁盘上的文件.

上面的配置文件指定了一系列ZooKeeper 的身份验证的列表,其格式与ZK CLI使用的格式相同。例如,您可以向下面这样指定:

digest:hdfs-zkfcs:mypassword

在ZooKeeper中hdfs-zkfcs是唯一的username ,mypassword 是一些唯一被作为密码使用的字符串。

接下来,使用如下命令生成与此身份验证相对应的ZooKeeper ACL :

[hdfs]$ java -cp $ZK_HOME/lib/*:$ZK_HOME/zookeeper-3.4.2.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider hdfs-zkfcs:mypassword

output: hdfs-zkfcs:mypassword->hdfs-zkfcs:P/OQvnYyU/nF/mGYvB/xurX8dYs=

拷贝输出中‘->’ 后面的字符串,并复制到 zk-acls.txt文件,开头以“digest:”的字符串(这个地方应该是将字符串拷贝到开头digest:的字符串后面 -- by 程序猿码码),例如:

digest:hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=:rwcda

为了让这些ACL生效,还需要重新运行上面描述的zkfc -formatZK 命令。

这些做完后,你就可以像如下一样通过ZK CLI验证ACLs:

[zk: localhost:2181(CONNECTED) 1] getAcl /hadoop-ha

'digest,'hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=

: cdrwa

验证自动故障切换

设置好并启动后,应测试其操作。为此,先找到Active NameNode。可以通过NameNode web接口来判断哪个NameNode处于Active状态---每个节点在页面顶部报告其HA状态。

找到 active NameNode后,我们可以手动制造一些故障。例如,可以使用kill -9 <pid of NN>来模拟JVM崩溃,或者可以重启机器或者拔下网络接口来模拟不同类型的中断,这些动作触发我们需要测试的中断场景后,另一个NameNode应在几秒钟内自动变成Active状态。检测到故障到触发故障自动切换之间所需的时间间隔取决于配置文件中的 ha.zookeeper.session-timeout.ms,默认是5秒。

如果测试没有成功,有可能是配置出了问题,需要检查zkfc后端程序和NameNode的后端程序的日志来判断问题所在。

自动故障切换FAQ:

① 以特定顺序启动ZKFC和NameNode后端程序是否重要?

No,在任何给定节点上,都可以在相应NameNode之前或之后启动ZKFC。

② 是否需要额外的监控?

需要在每个NameNode 增加监控来监控ZKFC是否运行。在一些类型的ZooKeeper 错误中,比如ZKFC 可能意外退出,这种情况就需要重启ZKFC,为随时可能进行的故障切换做好准备。

另外, 需要监控ZooKeeper quorum中的每个服务器,如果ZooKeeper 崩溃,那么自动故障切换将没办法进行。

③ 如果ZooKeeper 崩溃,将会怎么样?

如果ZooKeeper 集群崩溃,将不会再触发自动故障切换。但是HDFS将会继续运行,并且不会受到任何影响。当ZooKeeper 重启以后,HDFS将会重新连接到ZooKeeper,也不会受到任何影响。

④ 能否在NameNodes 之间指定优先级?

No,目前是不支持的。第一个启动的NameNode 将会是active状态,我们只能人为的控制NameNode 启动的顺序来做到“优先级”。

⑤ 已经设置了自动故障切换的情况下,如何手动切换?

虽然设置了自动故障切换,但是仍然可以使用 hdfs haadmin命令来手动故障切换。hdfs haadmin会进行协调的故障切换。

HA情况下HDFS 的 Upgrade/Finalization/Rollback

在HDFS版本之间切换时,有时只需要安装较新的软件,然后重启集群即可。但是,有时候升级正在运行的HDFS版本可能需要更改磁盘上的数据,这种情况下,在安装完新软件后必须使用HDFS Upgrade/Finalize/Rollback 工具。在HA环境中,这个过程就变得更加复杂,因为根据定义,NN依赖的磁盘元数据是分布式的,可以分布在2个HA NN机器中,也可以基于QJM实现的共享edits存储的数据放在了JournalNodes上。本文档部分介绍在HA设置中使用HDFS Upgrade/Finalize/Rollback工具的过程:

HA升级:为了完成HA update,需要进行如下操作:

1. 正常关闭所有NN,并且安装最新的软件。

2. 启动所有的JN。请注意,在执行 upgrade, rollback, or finalization 操作时,所有JN必须正在运行。如果在运行upgrade/ rollback/finalization操作时任何JN失败都会导致upgrade/ rollback/finalization操作失败。

3. 使用'-upgrade' flag启动其中一个NN。

4. 启动时,这个NN不会像HA通常那样进入standby状态,相反,此NN会立即进入active状态,执行其本地存储目录的升级,并执行共享edit日志的升级。

5. 此时,HA中的另一个NN将会与升级后的NN不同步。为了使其恢复同步并再次具有高可用配置,我们应该通过运行的NN的时候增加 '-bootstrapStandby' 选项来re-bootstrap这个NameNode。在启动第二个NN时使用了'-upgrade' 选项是错误的。

请注意,如果要在完成或回滚升级之前随时重新启动NameNodes,则应正常启动NNs,即不使用任何特殊启动参数。

完成HA升级:在NN正在运行并且其中一个是active时,要完成HA upgrade,需要使用`hdfs dfsadmin -finalizeUpgrade' 命令。发生这种情况时,active NN这时将会执行共享日志的最终确定。本地存储目录下包含之前FS状态的NN(哪个包含就是哪个NN)将会删除自己的本地状态。

回滚:要执行升级的回滚时,首先需要关闭两个NN。操作员应在启动过升级过程的NN上执行回滚命令,这个NN将会在本地目录和(NFS或者JNs上的)共享日志上执行回滚操作。之后,应启动这个NN,操作员需要在另外一个NN上执行 `-bootstrapStandby' 来和这个回滚的NN上达到状态同步。

-------------------------------------全文完---------------------------------------------------

备注:

NN: NameNode的缩写

Daemon: 这里翻译成了后端程序

最近有点累,2天翻译将近8000字实在太累了,为了不影响大家阅读,没有进行拆分,后续会稍微慢点,但是我会一天天坚持下去,谢谢大家。共同学习,共同进步!

返回顶部