许吉友 - 运维

使用 QJM 实现 HDFS 高可用

本指南概述了HDFS高可用性(HA)功能以及如何使用Quorum Journal Manager(QJM)功能配置和管理HA HDFS群集。

本文档假定读者对HDFS群集中的常规组件和节点类型有一般的了解。有关详细信息,请参阅HDFS体系结构指南。

背景

在Hadoop 2.0.0之前,NameNode是HDFS集群中的单点故障(SPOF)。每个群集只有一个NameNode,并且如果该计算机或进程不可用,则整个群集将不可用,直到NameNode重新启动或在单独的计算机上启动。

这从两个方面影响了HDFS群集的总可用性:

HDFS高可用性功能通过提供以下选项来解决上述问题:在具有热备用的主动/被动配置中,可以在同一群集中运行两个(并且自3.0.0起,超过两个)冗余NameNode。这可以在计算机崩溃的情况下快速故障转移到新的NameNode,或者出于计划维护的目的由管理员发起的正常故障转移。

架构

在典型的HA群集中,将两个或更多单独的计算机配置为NameNode。在任何时间点,恰好其中一个NameNode处于Active状态,而其他NameNode处于Standby状态。 Active NameNode负责群集中的所有客户端操作,而Standby则仅充当工作程序,并保持足够的状态以在必要时提供快速故障转移。

为了使备用节点保持其状态与活动节点同步,两个节点都与一组称为“ JournalNodes”(JN)的单独守护程序进行通信。当活动节点执行任何名称空间修改时,它会持久地将修改记录记录到这些JN的大多数中。 Standby节点能够从JN中读取编辑,并一直在监视它们以查看编辑日志的更改。当“备用节点”看到编辑内容时,会将其应用到自己的名称空间。发生故障转移时,备用服务器将确保在将自身提升为活动状态之前,已从JournalNode读取所有编辑内容。这样可确保在发生故障转移之前,名称空间状态已完全同步。

为了提供快速故障转移,备用节点还必须具有有关集群中块位置的最新信息。为了实现这一点,DataNode被配置了所有NameNode的位置,并向所有人发送块位置信息和心跳。

对于HA群集的正确操作至关重要,一次只能有一个NameNode处于活动状态。否则,名称空间状态将在两者之间迅速分散,从而有数据丢失或其他不正确结果的风险。为了确保此属性并防止所谓的“裂脑情况”,JournalNode将仅一次允许单个NameNode成为作者。在故障转移期间,将变为活动状态的NameNode将仅承担写入JournalNodes的角色,这将有效地防止另一个NameNode继续处于活动状态,从而使新的Active节点可以安全地进行故障转移。

硬件资源

为了部署HA群集,您应该准备以下内容:

请注意,在高可用性群集中,备用名称节点也执行名称空间状态的检查点,因此不必在高可用性群集中运行辅助名称节点,检查点节点或备份节点。实际上,这样做将是一个错误。这还允许正在重新配置未启用HA的HDFS群集的用户启用HA,以重用他们先前专用于次要NameNode的硬件。

配置

与联合身份验证配置类似,高可用性配置向后兼容,并允许现有的单个NameNode配置无需更改即可工作。设计新配置后,群集中的所有节点都可以具有相同的配置,而无需根据节点的类型将不同的配置文件部署到不同的机器上。

与HDFS联合身份验证一样,HA群集重用名称服务ID来标识单个HDFS实例,该实例实际上可能包含多个HA NameNode。此外,HA还添加了一个名为NameNode ID的新抽象。群集中的每个不同的NameNode都有一个不同的NameNode ID来区分它。为了支持所有NameNode的单个配置文件,相关的配置参数后缀有nameservice ID和NameNode ID。

要配置HA NameNode,必须将多个配置选项添加到hdfs-site.xml配置文件中。

设置这些配置的顺序并不重要,但是您为dfs.nameservices和dfs.ha.namenodes。[nameservice ID]选择的值将确定后面的密钥。因此,您应该在设置其余配置选项之前决定这些值。

部署

设置完所有必需的配置选项后,必须在将要运行它们的机器集上启动JournalNode守护程序。这可以通过运行命令hdfs --daemon start journalnode并等待该守护程序在每台相关计算机上启动来完成。

一旦启动JournalNode,便必须首先同步两个HA NameNode的磁盘元数据。

此时,您可以像通常启动NameNode一样启动所有HA NameNode。

通过浏览到每个NameNode配置的HTTP地址来分别访问它们。您应注意,配置的地址旁边将是NameNode的HA状态(“待机”或“活动”)。无论何时启动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 <命令>”。

负载均衡

如果您正在负载平衡器(例如Azure或AWS)后面运行一组NameNode,并且希望负载平衡器指向活动的NN,则可以将 /isActive HTTP 端点用作运行状况探测器。如果NN处于活动HA状态,则http://NN_HOSTNAME/isActive将返回200状态代码响应,否则返回405。

进行中的编辑日志拖尾

在默认设置下,Standby NameNode将仅应用已完成的编辑日志段中存在的编辑。如果希望具有一个具有最新名称空间信息的Standby NameNode,则可以启用正在进行的编辑段的尾部处理。此设置将尝试从JournalNode上的内存高速缓存中获取编辑,并且可以将在Standby NameNode上应用事务之前的延迟时间减少到毫秒量级。如果无法从缓存中进行编辑,则备用数据库仍将能够检索它,但是滞后时间将更长。相关配置为:

该功能主要与“待机/观察者读取”功能结合使用。使用此功能,可以从非活动的NameNode服务读取请求;因此,进行中的后期编辑为这些节点提供了为请求提供最新数据的能力。有关此功能的更多信息,请参见Apache JIRA票证HDFS-12943。

自动故障转移

以上各节描述了如何配置手动故障转移。在这种模式下,即使活动节点发生故障,系统也不会自动触发从活动NameNode到备用NameNode的故障转移。本节介绍如何配置和部署自动故障转移。

组件

自动故障转移为HDFS部署添加了两个新组件:ZooKeeper 和 ZKFailoverController进程(缩写为ZKFC)。

Apache ZooKeeper是一项高可用性服务,用于维护少量的协调数据,将数据中的更改通知客户端并监视客户端的故障。 HDFS自动故障转移的实现依赖ZooKeeper进行以下操作:

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

部署 Zookeeper 略。

在开始配置自动故障转移之前,应关闭集群。当前无法在集群运行时从手动故障转移设置过渡到自动故障转移设置。

配置自动故障转移

自动故障转移的配置需要在配置中添加两个新参数。在您的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>

与本文档前面所述的参数一样,可以通过在配置密钥后缀名称服务ID来基于每个名称服务配置这些设置。例如,在启用了联盟的群集中,可以通过设置dfs.ha.automatic-failover.enabled.my-nameservice-id显式地仅对其中一种名称服务启用自动故障转移。

还可以设置其他几个配置参数来控制自动故障转移的行为。但是,对于大多数安装而言,它们不是必需的。有关详细信息,请参阅特定于配置密钥的文档。

在ZooKeeper中初始化HA状态

添加配置密钥后,下一步是在ZooKeeper中初始化所需的状态。您可以通过从其中一个NameNode主机运行以下命令来做到这一点。

$ hdfs zkfc -formatZK

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

使用start-dfs.sh启动集群

由于已在配置中启用了自动故障转移,因此start-dfs.sh脚本现在将在任何运行NameNode的计算机上自动启动ZKFC守护程序。 ZKFC启动时,它们将自动选择一个NameNode激活。

手动启动集群

如果您手动管理群集上的服务,则需要在运行NameNode的每台计算机上手动启动zkfc守护程序。您可以通过运行以下命令启动守护程序:

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

请注意这些值中的“ @”字符-这表明配置不是内联的,而是指向磁盘上的文件。身份验证信息也可以通过CredentialProvider读取(请参阅hadoop-common项目中的CredentialProviderAPI指南)。

第一个配置的文件指定ZooKeeper身份验证列表,格式与ZK CLI使用的格式相同。例如,您可以指定以下内容:

digest:hdfs-zkfcs:mypassword

其中hdfs-zkfcs是ZooKeeper的唯一用户名,而mypassword是用作密码的一些唯一字符串。

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

$ 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:hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=:rwcda

为了使这些ACL生效,您应该按照上述说明重新运行zkfc -formatZK命令。

这样做之后,您可以按照以下步骤从ZK CLI验证ACL:

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

验证自动故障转移

设置自动故障转移后,应测试其操作。为此,首先找到活动的NameNode。您可以通过访问NameNode Web界面来确定哪个节点处于活动状态–每个节点在页面顶部报告其HA状态。

找到活动的NameNode之后,可能会导致该节点发生故障。例如,您可以使用kill -9 <NN的pid>模拟JVM崩溃。或者,您可以重新启动计算机电源或拔出其网络接口以模拟另一种中断。触发您要测试的中断后,另一个NameNode应在几秒钟内自动变为活动状态。检测故障和触发故障转移所需的时间取决于ha.zookeeper.session-timeout.ms的配置,但默认值为5秒。

如果测试不成功,则可能是配置错误。检查zkfc守护程序以及NameNode守护程序的日志,以便进一步诊断问题。