hadoop3.1.3文档 配置高可用集群(HA)

使用Quorum Journal Manager的高可用HDFS

本文是对hadoop3.1.3英文文档中比较重要的一部分进行了翻译,并加上一部分自己的理解。如果有不对的地方还请多多指教。本文不适合单纯想搭建HA集群的人群阅读。

部署

配置详细信息

配置HA NameNodes之前,你需要添加一些配置到你的hdfs-site.xml配置文件中。

你设置这些配置的顺序是不重要的,但是你选择的 dfs.nameservicesdfs.ha.namenodes.[nameservice ID] 的值将会决定后面的一些关键配置。因此,你应该在设置剩下的配置项之前,先确定这两个值。

  • dfs.nameservices - 这个新的nameservice的逻辑名

为这个nameservice起一个逻辑名,例如“mycluster”,然后将这个逻辑名赋值给这个配置项。逻辑名你可以随便取。它既被用于配置此配置项,也被用作集群中的hdfs绝对路径的权限组件。
注意: 如果你也使用hdfs 联邦,这个配置也应该将其他的nameservice、HA或者其它也包含进来,然后用逗号分隔。

<property>
	<name>dfs.nameservices</name>
	<value>mycluster</value>
</property>
  • dfs.ha.namenodes.[nameservice ID] - nameservice中每个NameNode的唯一标识

配置项的值为逗号分隔的NameNode的id列表。这个值将会被DataNode用来识别集群中的所有NameNode。举个例子,如果你之前使用mycluster来作为nameservice的id,并且你想使用“nn1”、“nn2”和“nn3”作为各个NameNode的id,你可以这样配置:

<property>
	<name>dfs.ha.namenodes.mycluster</name>
	<value>nn1,nn2,nn3</value>
</property>

注意: HA中的NameNode最少要有2个,当然你可以配置更多。建议不要超过5个,最好是3个,因为更多的NameNode意味着更多的通讯开销。

  • dfs.namenode.rpc-address.[nameservice ID].[name node ID] - 每个NameNode的完整的RPC(远程过程调用)地址。

为之前设配置的NameNode进程设置的完整地址和IPC端口。注意这个会有多个分开的配置(上一步设置NameNode ID时,是写在一起并用逗号分隔开的,这里的配置将会分隔开)。例如:

<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>
<property>
	<name>dfs.namenode.rpc-address.mycluster.nn3</name>
	<value>machine3.example.com:8020</value>
</property>

注意: 如果你愿意的话,你可以将“servicerpc-address”设置的类似一些。(废话)

  • dfs.namenode.http-address.[nameservice ID].[name node ID] - 每个NameNode的完整的http地址。

和之前的 rpc-address 一样,为每个NameNode的http服务设置地址。例如:

<property>
	<name>dfs.namenode.http-address.mycluster.nn1</name>
	<value>machine1.example.com:9870</value>
</property>
<property>
	<name>dfs.namenode.http-address.mycluster.nn2</name>
	<value>machine2.example.com:9870</value>
</property>
<property>
	<name>dfs.namenode.http-address.mycluster.nn3</name>
	<value>machine3.example.com:9870</value>
</property>

注意: 如果你开启了hadoop的安全性功能,你也应该为每个NameNode设置和上面类似的https-address配置。

  • dfs.namenode.shared.edits.dir - 用来配置NameNode进行读写操作所在的journalNode组的URI(统一资源标识符)。

这个地方是用来配置提供共享编辑存储功能的JournalNodes的地址。由active状态的NameNode写入,并由standby 状态的NameNode读取。以此来让standby状态的NameNode和active状态的NameNode具有相同文件系统信息。(原文太拗口了,这里是自己的理解,不知道对不对)。虽然你必须指定多个JournalNode地址,你应该只配置这些URI中的一种。 URI的格式应该像这样:qjournal://host1:port1;host2:port2;host3:port3/journalId。Journal ID是为这个namesevice起的一个唯一标识,通过这个唯一标识,可以允许单个jouralNode组为多个联盟的namesystem提供存储。尽管这个不是必须的,但是最好使用nameService的id来做为journal的标识。

例如,如果这个集群的JournalNode运行在 机器“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类的名字,这个java类会被DFS客户端用来判断哪个NameNode当前是active状态,因此就能知道哪个NameNode当前在处理客户端的请求(active状态的当然是在处理客户端的请求)。Hadoop目前使用的两个实现类,一个是 ConfiguredFailoverProxyProvider,一个是 RequestHedgingProxyProvider(这个实现类,在第一次调用时,会同时调用所有的NameNode来判断出哪个是active状态的,然后随后的请求,都会调用这个active状态的NameNode,直到发生了故障转移)。你可以使用这两个中的一个来配置,除非你自定义了一个proxy provider。例如:

<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的脚本或者java类的集合

为了系统的正确性,需要确保任何一个给定的时间点只有一个处于active状态的NameNode。重要的是,当使用Quorum Journal Manager时,永远只允许一个NameNode写入JournalNode,所以即使发生了脑裂情况也不会损坏文件系统的元数据。 但是,当发生了故障切换时,之前的active状态的NameNode仍然有可能接收客户端的读取请求,这时NameNode的数据可能已经过时了,直到NameNode当尝试写入JournalNode时关闭,这种风险才会消失。因此,即使使用了Quorum Journal Manager,也是有必要配置一些隔离的方法。但是,为了提高在隔离机制失败的情况下系统的可用性,建议配置一个绝对会成功的隔离方法放在列表最后,作为最后的一道防线。注意如果你不想使用隔离方法,你还是必须得为本设置项配置一些东西,比如"shell(/bin/true)"。

隔离方法需要被配置成一个回车符分隔的列表,在故障切换时,会按顺序尝试执行列表中的方法,直到其中一个提示隔离成功。Hadoop中有两种方法可供使用:shellsshfence。有关实现自定义隔离方法的信息,可以看org.apache.hadoop.ha.NodeFencer 类。


sshfence - 通过SSH远程到active状态的NameNode,并干掉进程。
这个sshfence选项通过ssh远程到目标节点,然后使用fuser命令来干掉监听服务的TCP端口的进程。为了这个隔离选项起作用,必须要能免密远程到目标节点。因此,同样必须得配置dfs.ha.fencing.ssh.private-key-files 选项。这个选项是一个通过分号分隔的SSH私钥文件集合。例如:

<!-- 如果使用sshfence,需要确保安装了psmisc -->
<!-- 这里配置了两个隔离方法,最后一个是确保隔离成功的临时写法 -->
<!-- 如果只写了sshfence,那么如果active的服务器挂掉之后,是没办法故障转移的,因为sshfence连不上active的服务器,隔离方法通不过,故障转移就执行不了 -->
<property>
	<name>dfs.ha.fencing.methods</name>
	<value>
		sshfence
		shell(/bin/true)
	</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
shell 隔离方法运行一个任意的shell命令。可以配置成下面的样子:

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

‘(’ 和 ‘)’之间的字符串会直接在bash shell中执行,并且字符串中不能包含右括号。

shell命令将会在一个包含所有的当前Hadoop配置的环境中运行,并且Hadoop配置的关键字中的所有的‘.’将会被替换成下划线。被使用的Hadoop配置,已经将所有的指定NameNode的配置变成了它们的通用形式 - 比如,dfs_namenode_rpc-address 会包含目标节点的RPC地址,即使之前的配置里面可能会写成dfs.namenode.rpc-address.mycluster.nn1

此外,下面这些和被隔离的目标节点相关的变量也是可以使用的:

变量名描述
$target_host被隔离的节点的主机名
$target_port被隔离的节点的IPC端口
$target_address上面两个变量的合体,主机:端口
$target_nameserviceid被隔离的NameNode的NameService的ID
$target_namenodeid被隔离的NameNode的ID

这些环境变量也可以在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,那么就会被认为成功隔离。如果返回了其他退出代码,那隔离就会失败,并尝试执行下一个隔离方法。

注意: 这个隔离方法没有设置任何超时。如果有必要的话,需要自己在shell脚本中设置(例如建立一个子shell,在超过一定时间后,kill掉父shell)。


  • fs.defaultFS - 当未指定路径时,Hadoop FS客户端会使用本配置项的值作为默认的路径(前缀)。

你可以使用之前配置的HA逻辑URI作为Hadoop客户端的默认路径,当然也可以不使用,随便。如果你之前使用“mycluster”作为nameservice的ID,那么“mycluster”就是你的所有HDFS路径的授权部分的值(不太明白这句话的意思)。可以在你的core-site.xml文件中做如下配置:

<property>
	<name>fs.defaultFS</name>
	<value>hdfs://mycluster</value>
</property>
  • dfs.journalnode.edits.dir - JournalNode后台进程储存自身状态的路径

这是一个JournalNode主机上的绝对路径,用来储存被JNs使用的编辑和其他本地状态数据。你只能为这个配置设置一个路径。这些数据的冗余(类似备份)可以通过运行多个分隔开的JournalNode或者把这个路径配置到一个本地连接的独立冗余磁盘阵列中。例如:

<property>
	<name>dfs.journalnode.edits.dir</name>
	<value>/path/to/journal/node/local/data</value>
</property>

部署的详细信息

在必要的设置项都配好了之后,需要先启动JouralNode。在配置了JournalNode的几个机器上,执行 “hdfs --daemon start journalnode”命令,运行JournalNode(这个过程可能需要小等一会儿)。
当所有的journalNode启动成功了之后,必须先同步两个HA的NameNode的磁盘元数据。

  • 如果你的HDFS集群是新建的,你第一步应该在任意一个NameNode上,运行格式化命令 (hdfs namenode -initializeSharedEdits)。

  • 如果你之前就已经格式化NameNode了,或者正在将一个未启用HA的集群转换成启用HA集群,你应该复制NameNode元数据目录的内容复制到其他的未格式化NameNode中,然后在未格式化的NameNode上,执行“hdfs namenode -bootstrapStandby” 命令。运行这个命令也能确保JouralNodes( 由dfs.namenode.shared.edits.dir配置 )包含足够的编辑事务来启动所有的NameNode。

  • 如果你正在将一个没有HA的NameNode转换成HA,你应该运行“hdfs namenode -initializeSharedEdits”命令,这将从本地NameNode的edits目录获取edits数据来初始化JournalNode们。

至此,你可以像平常启动一个NameNode一样,启动所有的HA NameNode。

你可以分别访问一下为每个NameNode配置的HTTP地址。你应该就会发现,页面上地址的旁边就是NameNode的HA状态,(不是“standby”就是“active”)。不管什么时候启动HA NameNode,它最初都是standby状态。

管理命令

现在你的HA NameNode已经配好了,并且运行起来了,你可以使用一些命令来管理你的HA HDFS集群了。你需要熟悉"hfds haadmin"命令的所有子命令。当你直接运行这个命令的时候,会得到以下的提示信息:

Usage: haadmin
    [-transitionToActive <serviceId>]
    [-transitionToStandby <serviceId>]
    [-failover [--forcefence] [--forceactive] <serviceId> <serviceId>]
    [-getServiceState <serviceId>]
    [-getAllServiceState]
    [-checkHealth <serviceId>]
    [-help <command>]

下面这个指南描述了这些子命令的高级用法。有关每个子命令的详细使用方法,你可以运行"hdfs haadmin -help <command>"。

  • transitionToActivetransitionToStandby - 将指定NameNode的状态转变成active或者standby。

这两个命令分别会将给定的NameNode转变成active或者standby状态。并且这两个命令不会执行隔离方法,因此很少会用到。相反的,更建议使用"hdfs haadmin -failover"子命令。

  • failover - 在两个NameNode之间启动故障转移。

这个子命令会启动故障转移,由第二个NameNode来接替第一个NameNode。如果第一个NameNode是standby状态,这个命令只是简单的讲第二个NameNode的状态转换为Active,并且不会抛出任何错误。如果第一个NameNode处于Active状态,首先将会尝试将这个NameNode转换为standby状态,如果转换失败,隔离方法(在dfs.ha.fencing.methods中配置的)将会按顺序执行,直到其中一个成功。如果没有成功的,那第二个NameNode将不会被转变成active状态。只有第一个NameNode成功转换为standby状态后,第二个NameNode才会被转换 成active状态。

  • getServiceState - 判断给定的NameNode的状态是active或者standby

通过连接到给定的NameNode来判断其当前状态,并向STDOUT(标准输出)打印“standby”或者“active”。这个子命令通常在计时程序或者监控脚本使用,它们会根据NameNode当前的active或者standby状态作出不同的操作。

  • getAllServiceState - 返回所有NameNode的状态

连接到配置的NameNode,判断他们当前的状态,并在STDOUT中打印“standby”或者“active”。

  • checkHealth - 检查给定的NameNode是否正常

连接到给定的NameNode,检查它是否正常。NameNode是可以为自己做一些诊断的,包括检查内部的服务是否按预期运行。如果正常的话,这个命令将会返回0,如果不正常返回非0的值。

注意: checkHealth命令当前还未完全实现,除非给定的NameNode已经完全关闭了,否则目前的话会一直返回成功。

负载均衡设置

如果你是基于负载均衡来运行一组NameNode,并且想让负载均衡指向处于active状态的NameNode,你可以使用/isActive 的http请求作为健康探测器。
如果NameNode是active状态的,访问http:\\NAMENODE_HOSTNAME/isActive将会返回200状态码,否则返回405状态码。

In-Progress编辑日志跟踪

(下面一段仅供参考,我不太理解,所以翻译出来的很可能不对)

在默认的配置下,standby状态的NameNode只会应用已经完成的编辑日志块中的编辑。如果希望能有一个standby状态的NameNode,它具有最新的命名空间的信息,那么可以通过开启In-Progress编辑块跟踪来实现。这个配置将会尝试从JournalNode中的内存缓存中获取编辑,可以将事务应用到standby状态的NameNode之前的延迟时间减少到毫秒级别。如果某个编辑无法从缓存中获取,那么standby状态的NameNode仍然可以重新去获取,但是延迟时间将会更长。相关的配置如下:

  • dfs.ha.tail-edits.in-progress - 是否启用in-progress编辑日志跟踪。这个同样也会启用JournalNode的内存编辑缓存。默认是关闭的。

  • dfs.journalnode.edit-cache-size.bytes - journalNode上的编辑的内存缓存大小。在一般的环境中,编辑会占用大概200字节的空间,因此,举个例子,1MB(1048576字节)可以保存大概5000个事务。建议监控journalNode 的 RpcRequestCacheMissAmountNumMisses 和RpcRequestCacheMissAmountAvgTxns,它们分别统计了无法从缓存获取编辑的请求次数,和让请求成功需要在缓存中添加的额外的事务数量。举个例子,如果一个请求尝试获取 事务ID从10开始的编辑,但是缓存中最老的数据是在事务ID为20的数据中,那么会在平均数中加10。(这段tm的没怎么看懂)

这个功能一般和Standby/Observer Read功能一起使用。在使用这个功能时,可以从非active状态的NameNode读取请求;因此跟踪in-progress编辑,给这些非active状态的NameNode提供了一个使用更加新的数据来处理请求的能力。

可以从Apache JIRA ticket HDFS-12943获取本功能的更多信息。

(上面一段仅供参考,我不太理解,所以翻译出来的很可能不对)

自动故障转移

介绍

前面的部分介绍了怎么去配置手动的故障转移。在那种模式下,系统不会自动触发故障转移,即使active状态的nameNode已经挂掉了。这一部分将会描述如何配置和部署自动故障转移。

组件

自动故障转移功能需要添加两个新的组件:zookeeper quorum,ZKFailoverController(简称ZKFC)。

apache zookeeper 是一个高可用服务,用于维护小数量级的协调数据,数据变化时通知各个客户端,并且监控客户端是否挂掉。自动HDFS故障转移主要依赖zookeeper来做以下几件事:

  • 故障检测 - 集群中的每个NameNode机器,都在zookeeper中维护一个持久的会话。如果机器挂了,这台机器上的zookeeper会话就会终止,然后提醒其他的NameNode可以触发故障转移了。

  • 选举active状态的NameNode(选举机制) - zookeeper提供一个简单的机制,可以选择唯一的一个节点,作为active的NameNode。如果当前的active状态的NameNode挂掉了,另外一个节点会在zookeeper中加上一个特殊的排他锁,以标识它会成为下一个active节点。

ZKFailoverController(ZKFC)是一个zookeeper客户端,也是一个用来监控和管理NameNode状态的组件。每一个运行了NameNode的机器也需要运行一个ZKFC,这个ZKFC主要负责:

  • 健康监控 - ZKFC会定期使用一个健康检查命令来ping它本地的Namenode。只要NameNode及时响应一个健康状态,ZKFC就会认为这个节点是正常的。如果节点崩溃了、冻结或者在其他方面处于不健康的状态,那健康监控会标记它为不健康。
  • zookeeper会话管理 - 当本地的NameNode是健康的,ZKFC会保持zookeeper中的session处于开启状态。如果本地NameNode处于active状态,ZKFC也会保持一个特殊的“锁住的”znode(zookeeper中的节点叫znode)。这个锁使用了zookeeper对“临时”节点的支持(zookeeper支持临时节点)。如果session中断了,这个锁定的节点也将会自动移除掉。
  • 基于zookeeper的选举机制 - 如果本地的NameNode是健康的,并且ZKFC发现其他节点当前没有持有锁住的znode,那它自己会尝试获取这个锁。如果它成功获取到了,就“赢得了选举”,然后它就负责运行故障转移来使它本地的NameNode转为active状态。这个故障转移过程和之前的手动故障转移是比较相似的:第一,有必要的话前active节点被隔离,然后本地NameNode准换成active状态。

自动故障转移的跟多细节,可以参考Apache HDFS JIRA上HDFS-2185的附加设计文档。

部署zookeeper

在一个典型的部署中,zookeeper进程被配置在3、4个节点上运行。自从zookeeper对资源的需求变少了之后,是可以将zookeeper节点和HDFS中Namenode和standby节点一起部署在一个硬件上的。很多人选择将第三个zookeeper进程和YARN 资源管理器部署到一个节点上。为了最好的表现和隔离,建议配置zookeeper节点的数据存储路径的时候,将路径设置到和HDFS元数据不同的磁盘驱动器上。

zookeeper的设置已经超出本文的范围了,这里不多赘述。现在假设你已经配置了一个运行在3个或者更多节点上的zookeeper集群,并且已经使用ZK CLI连接集群,验证了这个集群是正常的。

开始之前

在你开始配置自动故障转移之前,你需要把集群关掉。就目前而言,集群运行的时候,是不能将手动故障转移设置为自动故障转移的。

配置自动故障转移

自动故障转移的配置很简单,只要在你的配置里面加两个新的参数就好了。

在你的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上,直接在参数名后面加上nameservice的id就可以了。例如,在一个开启了联邦的集群中,你可以通过设置dfs.ha.automatic-failover.enabled.my-nameservice-id明确的指定联邦中的某一个nameservice来开启自动故障转移。

其实还有其他的一些配置,可以用来控制自动故障转移的行为,但是大多数情况不是必须的。具体请参见xxxxx文档。

在zookeeper中初始化HA状态

在上面两个配置加好之后,下一步就是在zookeeper中初始化一些状态。你可以在任何一个NameNode主机上执行下面的命令:

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

这个命令将会一个zookeeper的节点znode,自动故障转移系统会把数据存在这个节点里面。

手动启动集群

如果你是手动管理集群的,你需要在运行了NameNode的机器上,手动开启zkfc进程。你可以运行下面的命令来开启进程:

[hdfs]$ $HADOOP_HOME/bin/hdfs --daemon start zkfc

安全访问zookeeper

如果你运行的是一个有安全设置的集群,你应该也想确保存储在zookeeper中的数据也是安全的。这可以防止恶意客户端修改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>

请注意 “@”符号,这个符号表示指定的配置不是hdfs中的文件,而是指向磁盘上的文件。认证信息也可以通过CredentialProvider来提供(请看hadoop-common项目中的CredentialProviderAPI向导)。

上面的第一个配置里指向的文件是zookeeper身份认证列表,它的内容格式和ZK CLI一样。例如,你可以这样写:

digest:hdfs-zkfcs:mypassword

其中hdfs-zkfcs是zookeeper的名称,mypassword是密码。

下一步,创建一个和上面的身份认证列表一致的zookeeper ACL(访问控制列表),使用的命令类似下面所示:

$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=

复制output部分,“->”之后的字符串,然后粘贴到zk-acls.txt中,然后加上前缀“digest:”。例如:

diges:hdfs-zkfcs:P/OQvnYyU/nF/mGYvB/xurX8dYs=

为了使这些ACL(访问控制列表)生效,你应该重新运行一下zkfc -formatZK 命令。
在完成了这些事情之后,你可以通过ZK CLI来验证ACL了。

[zk: localhost:2181(CONNECTED) 1] getAcl /hadoop-ha
'digest,'hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=
: cdrwa

验证成功应该就是这个样子的。

验证自动故障转移

自动故障转移设置完成之后,你应该测试一下。为了测试,首先找到active状态的NameNode。你可以通过访问NameNode的web页面来确认哪个NameNode是active状态的,因为页面顶部就显示了每个节点的状态了。

找到active的NameNode之后,你可以让这个节点挂掉。比如,你可以使用kill -9 强制干掉进程,假装是JVM崩溃了。或者,你可以重启机器或者拔掉网线,来模拟其他的异常情况。在你触发了各种异常情况之后,其他的NameNode节点应该在几秒内自动变成active状态。这个检测故障的和触发故障转移的时长取决于zookeeper中 ha.zookeeper.session-timeout.ms的配置,默认情况下是5秒。

如果测试没有成功,那你可能配置错了。检查一下zkfc进程和NameNode进程产生的日志,以进一步确认问题的原因。

自动故障转移的FAQ

  • 我需要按照特定的顺序来启动ZKFC和NameNode进程吗?
    不需要。在任何一个节点上,你可以启动在对应的NameNode之前或者之后启动ZKFC。

  • 我需要添加哪些额外的监控吗?
    你需要在每个运行NameNode的主机添加监控,以确保ZKFC一直在运行。如果zookeeper崩掉了,自动故障转移也就不会生效了。

  • 如果zookeeper挂掉了会怎么样?
    如果zookeeper挂掉了,自动故障转移就不会触发。不过,这不会影响HDFS的运行。等zookeeper重启了,HDFS也会重新连接。

  • 我可以指定其中一个NameNode让它优先变成active状态吗?
    不行,目前这个是不支持的。不管是谁,第一个启动的NameNode就是active状态。你可以先启动你首选的节点。

  • 我如何在配置了自动故障转移的情况下,发起手动故障转移?
    可以的。就算配置了自动故障转移,你也可以执行hdfs haadmin中的命令发起手动故障转移。

启用了HA的HDFS的升级/中止/回滚
当切换HDFS的版本的时候,有些情况下,新版的软件可以直接安装,然后重启集群就可以了。但是有些时候,升级HDFS的版本可能需要修改一些数据。在这种情况下,在安装完新版软件的时候,必须使用HDFS的升级/中止/回滚功能。在HA环境下,这个过程就更复杂了,因为NameNode依赖的磁盘元数据是分布式的,都在成对的两个HA NameNode上,当QJM被用来共享存储的话,元数据也会在JournalNode上。
这部分的文档,描述在HA下使用HDFS的升级/关闭/回滚功能。

部署一个HA升级,必须按下面步骤来操作:

  1. 正常关闭所有的NameNode,然后安装新版软件。
  2. 开启所有的JournalNode。注意,在升级/中止/回滚操作中,关键点是所有的JournalNode都得是运行的。如果在执行升级/中止/回滚的时候,任何一个journalNode关掉了,操作就会失败。
  3. 启动其中一个NameNode,并加上“-upgrade”标识。
  4. 启动的时候,这个NameNode不会和平常一样进入standby状态。而是会立马进入active状态, 执行本地存储路径的升级,也执行分享编辑日志的升级。
  5. 这个阶段,其他的NameNode和已升级过的NameNode之间的数据将不会同步。为了重新同步以及启用HA,你应该加上“-bootstrapStandby”标识来运行其他的NameNode,以便重新引导这个NameNode。用“-upgrade”来启动其他节点是不对的。

注意,在任何时间,如果你想在中止或者回滚更新的过程中,重启NameNode,你可以正常启动NameNode,也就是不添加任何启动标识。

要查看升级的状态,你可以使用“hfds dfsadmin -upgrade query”命令,不过只要需要一个NameNode处于正常运行的状态。这个命令会返回每个NameNode的升级有没有完成。

要回滚一个升级,首先需要关闭所有的NameNode。你应该在安装升级程序的NameNode上运行回滚命令,然后就会回滚本地目录,也会回滚NFS或者JNs上的共享日志。之后,你需要启动这个NameNode,然后通过“-bootstarpStandby”标识来启动其他的NameNode,这样其他的NameNode就能同步回滚之后的文件系统状态了。

(完结,本文肯定有不完全对的地方,后期会不断完善,发现问题的小伙伴可以留下评论提醒我一下啊)


版权声明:本文为JinShuYSM原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。