使用QJM的高可用HDFS

译者按:因项目中数据存储需要用到HBase,老大下达任务后就屁颠屁颠去网上搜集各种Hadoop+HBase的安装教程,安装单实例时还好,步骤比较简单,但进行到分布式安装时发现网络找的教程都不完整,很多步骤都是没经过验证的,碰到各种BUG,结果硬是花了一个星期,最后对照官方文档才搭建好一个完全分布式的Hadoop+HBase架构。感觉最靠谱的还是官方文档,但由于是英文,读起来有些费力,便一怒之下再花两天时间翻译下来。感觉磨刀不误砍柴工,希望对自己以后有所帮助,也希望对需要搭建高可用HDFS的朋友有所帮助。

原文:http://hadoop.apache.org/docs/r2.7.3/hadoop-project-dist/hadoop-hdfs/HDFSHighAvailabilityWithQJM.html

目的

这个指南提供了一个 HDFS 高可用(HA)特征的概览,和如何使用Quorum Journal Manager (QJM) 特征来配置和管理 HA HDFS 集群。

这个文档假定读者对 HDFS 集群中的通用组件和节点类型有一个整体理解。请参考 HDFS 架构指南来获详细信息。

注意:使用 Quorum Journal Manager 或者传统共享存储

这个指南讨论如何使用 Quorum Journal Manager (QJM) 共享 Active 和 Standby NameNodes 节点间的编辑日志来配置和使用 HDFS HA。关于如何使用 NFS 共享存储替代 QJM 配置 HDFS HA的信息,请见:this alternative guide

背景

在 Hadoop 2.0.0 之前,NameNode 节点是 HDFS 集群中的单点故障(SPOF)。每个集群有一个单一 NameNode 节点,如果那台机器或进程不可用,整个集群都不可用,直至 NameNode 节点重启或者在另一台机器上启动。

这从两个主要方面影响了 HDFS 集群的整体可用性:

  • 在如机器死机这一意外事件的情况下,集群变得不可用,直至操作员重启 NameNode 节点。
  • 如 NameNode 机器的软件或硬件升级这种计划性维修事件,会导致集群停机窗口。

HDFS 高可用解决了如上问题,通过提供在同一集群中以热备份的 主/被 配置运行两个冗余 NameNode 的选项。这允许在机器司机的情况下快速故障转移到新的 NameNode,或者出于计划维护目的的,由管理员发起的优雅故障转移。

架构

一个经典的 HA 集群中,两个独立的机器配置成 NameNode 节点。在任一时刻,恰好一个 NameNode 节点是 Active 状态,另一个是 Standby 状态。Active NameNode 响应集群中的所有客户端操作,而 Standby 仅作为一个从节点,维护所有状态,在需要时快速故障转移。

为了让 Standby 节点的状态与 Active 节点的状态保持同步,所有与一组独立守护进程通信的节点称为 “JournalNodes”(JNs)。当 Active 节点执行的任何命名空间的改变,它会持久化记录一条改动日志到大多数 JNs 。Standby 节点能够从 JNs 中读取改动信息,并且不断监控改动日志的改动信息。由于 Standby 节点理解改动信息,它应用这些信息到自己的命名空间。发生故障转移时,Standby 会保证它自己在晋升为 Active 状态之前从 JournalNodes 上读取了所有的改动信息。这保证故障转移之前,命名空间状态是完全同步的。

为了提供快速故障转移,Standby 节点必须有最新的关于集群中 blocks 位置的信息。为了实现这,DataNodes 配置了所有 NameNodes 的位置,并发送 block 位置信息和心跳给所有 NameNodes。

一个 HA 集群中的正确操作是至关重要的,一个时刻只有一个 NameNode 是 Active 状态。否则,命名空间状态会在这两个之间迅速分离,面临数据丢失和其它错误结果的风险。为了确保这一属性并防止所谓的 “脑裂情景” ,JournalNodes 将永远只允许一个时刻只有一个 NameNode 提供写入。在故障切换期间,成为 Active 的 NameNode 将简单地从 JournalNode 接管写入的角色,这将有效防止其它 NameNode 继续处于 Active 状态,允许新的 Active 节点安全地进行故障切换。

硬件资源

为了部署一个 HA 集群,你应该准备如下:

  • NameNode 机器 —— 运行 Active 和 Standby NameNodes 的机器彼此应该有同等的硬件配置,在非HA集群也应该用同等的硬件配置。
  • JournalNode 机器 —— 运行 JournalNodes 的机器。JournalNode 的守护进程是相当轻量级的,所以这些守护进程可以合理地与机器上其它 Hadoop 守护进程并行运行,如 NameNodes, JobTracker 或者 YARN ResourceManager。 注意 :至少必须有3个 JournalNode 守护进程,因为改动日志中的变动必须写入大多数的 JNs。这允许系统能容忍单个机器故障。你可能也需要运行超过3个 JournalNode,但是为了提高系统可以容忍故障的数量,你应该运行奇数个 JNs(如:3、5、7等等)。注意,当运行 N 个 JournalNodes,系统可以容忍最多 (n-1)/2 个故障并继续正常运行。

注意,在一个 HA 集群,Standby NameNode 也执行命名空间状态的checkpoints,因此一个 HA 集群不是必须运行 Secondary NameNode, CheckpointNode 或者 BackupNode。实际上,这样做会出现错误。这也允许我们通过重用之前专用于Secondary NameNode 的硬件资源,重新将一个非 HA HDFS 集群配置成 HA 。

部署

配置概述

类似于联合配置,HA 配置是向后兼容的,而且允许现有的单个 NameNode 配置在不发生改变的情况下正常工作。新的配置设计成集群中的所有节点可能有相同配置,不需要为基于节点类型的不同机器部署不同配置文件。

像 HDFS 联盟,HA 集群重用 nameservice ID 来标识一个单独的 HDFS 实例,但可能实际上由多个 HA NameNodes 组成。另外,HA 中加入一个新的抽象概念称为 NameNode ID。集群中每个不同 NameNode 有一个不同的 NameNode ID 来区分它。为支持所有 NameNode 的单个配置文件,相关配置参数以 nameservice ID 或 NameNode ID 作为后缀。

配置详情

为配置 HA NameNode,你必须给你的 hdfs-site.xml 配置文件添加几个配置选项。

你设置这些配置的顺序并不重要,但是你为 dfs.nameservicesdfs.ha.namenodes.[nameservice ID] 选择的值会决定下面这些关键点。因此,你应该在设置其它配置选项之前决定这些值。

  • dfs.nameservices - 新 nameservice 的逻辑名称

    为这个 nameservice 选择一个逻辑名称,比如 “mycluster” ,并用这个名称作为配置项的值。你选择的名称可以是任意的。它即用于配置,也作为集群中绝对 HDFS 路径的权威组件。

    注意 :如果你也使用联合 HDFS,这个配置设置也应该包含其它 nameservices 的列表,HA 或者其它,以逗号隔开的列表。

    <property>
    <name>dfs.nameservices</name>
    <value>mycluster</value>
    </property>

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

    配置一列以逗号隔开的NameNode ID,这将用于DataNode区分集群中的所有NameNodes。比如,如果你之前使用”mycluster”作为nameservice ID,并且你想使用”nn1”和”nn2”作为NameNodes的个体ID,你应该配置如下:

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

    注意:目前,每个nameservice最多只允许配置两个NameNode。

  • dfs.namenode.rpc-address.[nameservice ID].[name node ID] - 每个NameNode监听的完整的 RPC 地址

    为之前配置的每个NameNode ID,配置NameNode进程的完整地址和RPC端口。注意这是两个独立的配置选项。例如:

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

    注意:如果你需要也可能要配置”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:8020</value>
    </property>

    <property>
    <name>dfs.namenode.http-address.mycluster.nn2</name>
    <value>machine2.example.com:8020</value>
    </property>

    注意:如果你启用Hadoop的安全特性,你也应该类似地为每个NameNode配置 https-address

  • dfs.namenode.shared.edits.dir - 识别 NameNode 读写改动日志的 JNs 组的URI

    这是一个支持共享改动日志存储的JournalNodes地址配置,由Active NameNode写,由Standby NameNode节点读,使之与Active NameNode对整个文件系统做的改动保持同步。虽然你必须指定一些JournalNode地址,你应该只用配置这些URIs中的一个。这URI应该是 qjournal://host1:port1;host2:port2;host3:port3/journalId 的格式。Journal ID是nameservice的唯一标识,它允许单个JournalNode集合为多联合名称系统提供存储。虽然不是必须,但用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类名称,用于DFS客户端决定哪个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的一列脚本或Java类

    系统的正确性需要在任何时间只有NameNode节点处于Active状态。重要的是,当使用Quorum Journal Manager,只有一个NameNode被允许写入JournalNodes,所以没有在脑裂情景腐蚀文件系统元数据的可能性。然而,在故障切换发生时,仍有可能之前的Active NameNode能服务客户端的读请求,这会过期,直至NameNode向JournalNode写时停止了。由于这个原因,即使在使用Quorum Journal Manager时也需要配置一些防护方法。然而,为提高系统在防护机制失败时间中的可用性,配置一个防护方法是明智的,这个方法保证列表中的最后一个防护服方法返回成功。注意如果你选择使用没有实际防护的方法,你仍然需要为这项设置配置一些东西,比如”shell(/bin/true)”。故障切换期间使用的防护方法配置成carriage-return-separated列表,它会按顺序执行直至明确有一个防护方法成功。Hadoop中有两个方法:shellsshfence。获取实现自己自定义防护方法的资料,查看 org.apache.hadoop.ha.NodeFencer 类。


    sshfence - SSH连接到Active NameNode并终止进程

    sshfence选项SSHes到目标节点并用 fuser 终止监听服务TCP端口的进程。为了这个防护选项起作用,必须允许SSH无密码连接到目标节点。因此,我们也必须配置 dfs.ha.fencing.ssh.private-key-files 选项,它是一个逗号分隔的SSH私钥文件列表。比如:

    <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配置一个timeout,单位毫秒,在防护方法被认识失败之后。这可以按如下配置:

    <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环境变量的环境,用 ‘_’ 字符代替配置选项中的任何 ‘.’ 字符。这些已经在NameNode特性配置里存在的配置提升为它们的通用格式——例如 dfs_namenode_rpc-address 将包含目标节点的RPC地址,即使这个配置可能指定的变量为 dfs.namenode.rpc-address.ns1.nn1

    另外,如下变量指的被防护目标节点仍然可用:

    $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,这个防护断定是成功的。如果它返回其它任何退出码,防护是不成功的,列表中的下一个防护方法会去执行。

    注意:防护方法没有实现任何超时。如果需要超时机制,它们需要自己在shell脚本中实现(例如通过派生子shell在几秒钟内杀死它的父进程)

  • fs.defaultFS - 默认路径前缀,当为空时用于Hadoop文件系统客户端

    根据需要,你可能现在要用新的启用了HA的逻辑URI为Hadoop客户端配置默认路径。如果你之前用”mycluster”作为nameservice ID,这将是你所有HDFS路径的权威部分。这可能这样配置,在你的 core-site.xml 文件中:

    <property>
    <name>fs.defaultFS</name>
    <value>hdfs://mycluster</value>
    </property>

  • dfs.journalnode.edits.dir - JournalNode守护进程存储本地状态的路径

    这是JournalNode机器上的绝对路径,JNs使用的改动日志和其它本地状态将会被存储。为这个配置你可能仅用一个路径。通过运行多个独立JournalNode可以提供这些信息的冗余,或者通过配置这个目录在本地挂载的RAID array(磁盘阵列)上。例如:

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

部署详情

设置了所有必须的配置选项之后,你必须启动JournalNode守护进程,在它们会运行的一套机器上。这可以通过运行命令 “hadoop-daemon.sh start journalnode” 并等待守护进程在每台相关的机器上启动来完成。

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

  • 如果是设置一个全新的HDFS集群,你应该首先运行格式化命令(hdfs namenode -format)在其中一个NameNode上。
  • 如果已经格式化了NameNode,正转换一个非HA集群至HA可用,你现在应该复制NameNode元数据目录内容到另外一个,未格式化的NameNode通过在未格式化的NameNode上运行命令 “hdfs namenode -bootstrapStandby” 。运行这个命令将也确保JournalNodes(通过 dfs.namenode.shared.edits.dir 配置的)包含最后的编辑事务以启动所有的NameNodes
  • 如果你正转换一个非 HA NameNode 至 HA,你应该运行命令 “hdfs namenode -initializeSharedEdits”,它会从本地NameNode编辑目录初始化JournalNodes的编辑数据。

这时候你可能以你通常启动NameNode的方式启动了你所有的HA NameNode。

你可以通过浏览它们配置的HTTP地址来分别访问每个NameNode的Web页面。你应该注意到在配置的地址旁边的是NameNode的HA状态(”Standby”或”Active”)。每当一个HA NameNode启动,它初始是Standby状态。

管理命令

现在你的HA NameNode配置好并启动了,你可以访问一些额外的命令去管理你的HA HDFS集群。特别的,你应该自己熟悉 “hdfs command” 命令下的所有子命令。不带任何参数地运行这个命令会显示如下使用信息:

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

这个指南描述了每个自命令的高级用法。获取每个子命令的特殊用法信息,你可以运行 “hdfs haadmin -help <command>”

  • transitionToActivetransitionToStandby 转换指定NameNode至Active或Standby状态

    这些子命令使指定的NameNode转换成Active或Standby状态。这些命令不会试图执行任何防护,因此很少使用。反而,人们可能都偏向使用 “hdfs haadmin -failover” 子命令。

  • failover - 在两个NameNodes之间发起故障转移。

    此命令导致首先提供的NameNode至第二的故障转移。如果第一个NameNode处于Standby状态,此命令简单地将第二个状态转换为活动状态,没有错误。如果第一个NameNode是Active状态,会试图温和地将它转换为Standby状态。如果这失败了,防护方法(通过 dfs.ha.fencing.methods 配置的)会被有序执行,直至有一个成功。只有在这个过程之后,第二个NameNode才会被转换为Active状态。如果没有防护方法成功,第二个NameNode不会被转换为Active状态,并返回一个错误。

  • getServiceState - 确定指定的NameNode是Active或Standby状态

    连接到当前的NameNode来确定它当前的状态,恰当地打印”standby”或”active”至STDOUT。这个子命令可以被定时任务或监控脚本使用,这些脚本需要根据NameNode当前是Active或Standby状态来进行不同的操作。

  • checkHealth - 检查指定NameNode的运行状况

    连接到提供的NameNode来检查它的运行状况。NameNode有能力在自己身上做一些诊断,包括检查内部服务是否按照预期运行。如果NameNode运转正常,那么这个命令会返回0,否则非0。可以使用此命令进行监控。

    注意:这还没有实现,并且目前将始终返回成功,除非给定的NameNode完全关闭。

自动故障切换

介绍

上面的章节介绍了如何手动进行故障切换。在那个模式下,系统不会自动触发Active至Standby Namenode的故障切换,及时如果Active节点失败了。这一章节描述如何配置和部署自动故障切换。

组件

自动故障切换给HDFS部署增加了两个新组件:一个Zookeeper仲裁,和ZKFailoverController程序(缩写为ZKFC)。

Apache Zookeeper是一个维护少量调度数据,通知客户端数据变化和监控客户端是否故障的高可用服务。自动HDFS故障切换的实现依赖于Zookeeper进行以下操作:

  • 故障检测 - 集群中的每一个NameNode机器在Zookeeper中维护一个持久会话。如果机器崩溃,Zookeeper会话会超时,通知另外一个NameNode故障切换应该被触发。

  • Active NameNode选举 - Zookeeper提供了一个简单机制来唯一选择一个节点作为Active。如果当前Active NameNode崩溃,另外一个节点会在Zookeeper上获取一个特殊排它锁来表明它应该成为下一个Active。

ZKFailoverController是一个新的组件,它是一个Zookeeper客户端,也监控和管理NameNode的状态。每一个运行NameNode的机器也运行ZKFC,ZKFC负责如下:

  • 运行状况监控 - ZKFC用一个状况监测命令周期性地 pings 它的本地NameNode。只要NameNode及时响应正常状态,ZKFC就认为这个节点是正常的。如果节点崩溃、挂起或进入其它非正常状态,状态检测器会标记它为非正常。

  • Zookeeper会话管理 - 当本地NameNode运转正常时,ZKFC持有一个在Zookeeper中打开的会话。如果本地NameNode是Active,它也持有一个特殊的”lock” znode。这个锁使用Zookeeper支持的”ephemeral”节点;如果会话超时,这个锁节点会自动删除。

  • 基于Zookeeper的选举 - 如果本地Namenode是正常的,然后ZKFC发现没有其它节点当前持有锁znode,它会自己尝试获取这个锁。如果成功,它“赢得选举”,并负责运行故障转移使它的本地NameNode转换成Active。这个故障切换程序类似于上面手动故障转移描述的:首先,之前的Active在需要时进行防护,然后那个本地NameNode转换成Active状态。

获取自动故障切换设计的更详细内容,参考在Apache HDFS JIRA上附加在HDFS-2185上的设计文档。

部署Zookeeper

在一个经典的部署中,Zookeeper守护进程配置成运行在3个或者5个节点。由于Zookeeper自身只有轻量资源需求,可以将Zookeeper节点放在与HDFS的NameNode和Standby NameNode相同的硬件资源上。许多运营商选择在与YARN ResourceManager相同的节点上部署第三个ZooKeeper进程。建议将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服务的主机-端口对。

与文档中先前描述的参数一样,可以通过用名称服务ID后缀配置键来在每个名称服务的基础上配置这些设置。 例如,在启用了联合的集群中,可以通过设置 dfs.ha.automatic-failover.enabled.my-nameservice-id 来为仅一个名称服务器显式启用自动故障切换。

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

在Zookeeper中初始化HA状态

添加了关键配置后,下一步是在Zookeeper中初始化需要的状态。你可以在其中一台NameNode主机上运行如下命令来做这个。

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

这会在Zookeeper内部创建一个znode,它用于自动故障切换系统存储它的数据。

start-dfs.sh 启动集群

由于在配置中启用了自动故障切换,start-dfs.sh 脚本会在运行任何NameNode的机器上自动开启一个ZKFC守护进程。当ZKFCs启动,它们会自动选择NameNodes中的一个作为Active。

手动启动集群

如果你手动管理集群中的服务,你需要手动在每个运行NameNode的机器上启动 zkfc 守护进程。你可以启动这个守护进程通过运行:

[hdfs]$ $HADOOP_PREFIX/sbin/hadoop-daemon.sh –script $HADOOP_PREFIX/bin/hdfs 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>

请注意这些值中的 ‘@’ 字符 —— 这说明这个配置不是联机的,而是指向磁盘上的一个文件。

第一个配置的文件指定了一列Zookeeper认证,与ZK CLI使用相同的格式。比如,你可能指定一些如下:

digest:hdfs-zkfcs:mypassword

hdfs-zkfcs 是Zookeeper的一个唯一用户名,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:hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=:rwcda

为了这些ACLs生效,你应该回到上面描述的命令 zkfc -formatZK。这要做了后,你可以从ZK CLI验证ACLs如下:

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

验证自动故障切换

一旦自动故障切换设置好了,你应该测试它的功能。要做这,首先定位到Active NameNode。你可以通过访问NameNode网页接口来获取那个节点是Active —— 每个节点在页面的顶部记录它的HA状态。

一旦你定位到你的Active NameNode,你可以在那个节点上引起一个故障切换。比如,你可以使用 kill -9 <pid of NN> 来模拟一个JVM 崩溃。或者,你可以重新启动机器或者拔掉网络接口来模拟一种不同类型的中断。在触发了你希望测试的中断后,另一个NameNode应该在数秒内自动成为Active。检测到故障并触发故障修复的时间依赖于配置 ha.zookeeper.session-timeout.ms,但默认是5秒。

如果测试不成功,你可能有一个错误配置。检查 zkfc 守护进程和 NameNode 守护进程的日志来进一步解决问题。

自动故障切换 FAQ

  • 我以任何某种顺序启动ZKFC和NameNode守护进程重要吗?
    不重要。在任何给定的节点上,你可以在相应的NameNode之前或之后启动ZKFC。

  • 我需要落实哪些额外监控?
    你应该在每台运行NameNode的主机上添加监控来确保ZKFC仍在运行。在某些类型的Zookeeper故障中,比如,ZKFC可能意外退出,应该重启来保证系统是准备好自动故障切换的。

    另外,你应该监测Zookeeper仲裁中的每一个服务器。如果Zookeeper崩溃,自动故障切换将会不起作用。

  • 如果Zookeeper关闭了会发生什么?
    如果Zookeeper集群崩溃,没有自动故障切换会被触发。然而,HDFS会照常运行不受影响。当Zookeeper重启了,HDFS会重新连接,没有错误。

  • 我可以设计我NameNodes中的一个为主要/优先吗?
    不可以。目前,这不支持,无论哪个先起来的NameNode会成为Active。你可以以一个指定顺序来启动集群,比如先启动你想要的节点。

  • 当配置了自动故障切换我怎样能启动手动故障切换
    及时配置了自动故障切换,你也可以启动手动故障切换,使用相同的 hdfs haadmin 命令。它会执行一个同等的故障切换。

启用HA的HDFS升级/终止/回滚

当在HDFS的版本之间移动时,有时可以简单地安装较新的软件并重新启动集群。 然而,有时,升级您正在运行的HDFS版本可能需要更改磁盘数据。 在这种情况下,必须在安装新软件后使用HDFS升级/完成/回滚工具。 在HA环境中,这个过程变得更加复杂,因为NN依赖的磁盘元数据是定义分布的,在该对的两个HA NN上,以及在使用QJM的情况下的JournalNode 共享编辑存储。 本文档部分介绍在HA设置中使用HDFS升级/完成/回滚功能的过程。

要执行HA升级,操作员必须执行以下操作:

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

  2. 启动所有JN。 请注意,执行升级,回滚或最终化操作时,所有JN都必须正在运行。 如果任何JN在运行任何这些操作时都关闭,操作将失败。

  3. 使用’-upgrade’标志启动其中一个NN。

  4. 开始时,此NN将不会像通常在HA设置中那样进入备用状态。 相反,该NN将立即进入活动状态,执行其本地存储盘的升级,并且还执行共享编辑日志的升级。

  5. 在这一点上,HA对中的另一NN将与升级的NN不同步。 为了使它恢复同步并且再次具有高可用性设置,您应该通过使用’-bootstrapStandby’标志运行NN来重新引导此NameNode。 使用’-upgrade’标志启动第二个NN是一个错误。

请注意,如果在任何时候想要在完成或回滚升级之前重新启动NameNodes,您应该正常启动NN,即没有任何特殊的启动标志。

要完成HA升级,当NN正在运行并且其中一个活动时,操作员将使用 hdfs dfsadmin -finalizeUpgrade 命令。 在发生此时的活动NN将执行共享日志的最终化,并且其本地存储目录包含先前FS状态的NN将删除其本地状态。

要执行升级的回滚,应首先关闭两个NN。 操作员应在NN上运行回滚命令,在那里它们发起升级过程,这将在本地dirs上以及在共享日志(NFS或JN上)上执行回滚。 之后,应该启动此NN,并且操作员应在其他NN上运行 -bootstrapStandby ,以使两个NN与此回滚的文件系统状态同步。

猜你喜欢

转载自blog.csdn.net/u013235478/article/details/54564345