sujins 2020-06-10
HA
(High Available
)即高可用(7*24小时不中断服务),实现高可用最关键的策略就是消除单点故障。HA
严格地来说应该分成各个组件的HA
机制,HDFS
的HA
和YARN
的HA
。
Hadoop2.0
之前,在HDFS
集群中NameNode
存在单点故障(SPOF
)。NameNode
主要在以下两个方面影响HDFS
集群:
NameNode
机器发生意外,如宕机,集群将无法使用,直到管理员重启NameNode
机器需要升级,包括软件、硬件升级,此时集群也将无法使用HDFS HA
功能通过配置Active/Standby
两个NameNodes
实现在集群中对NameNode
的热备来解决上述问题。如果出现故障,如机器崩溃或机器需要升级维护,这时可通过此种方式将NameNode
很快的切换到另外一台机器。
通过双NameNode
消除单点故障
Edit
日志只有Active
状态的NameNode
节点才可以做写操作,两个NameNode
都可以读取Edits
。共享的Edits
放在一个共享存储中管理(qjournal
和NFS
两个主流实现)zkfailover
常驻在每一个NameNode
所在的节点,每一个zkfailover
负责监控自己所在NameNode
节点,利用ZooKeeper
进行状态标识,当需要进行状态切换时,由zkfailover
来负责切换,切换时需要防止brain split
现象的发生。NameNode
之间能够ssh
无密码登录Fence
),即同一时刻仅仅有一个NameNode
对外提供服务使用命令hdfs haadmin failover
手动进行故障转移,在该模式下,即使现役NameNode
已经失效,系统也不会自动从现役NameNode
转移到待机NameNode
,下面学习如何配置部署HA
自动进行故障转移。
自动故障转移为HDFS
部署增加了两个新组件:ZooKeeper
和ZKFailoverController
(ZKFC
)进程。
如图所示:ZooKeeper
是维护少量协调数据,通知客户端这些数据的改变和监视客户端故障的高可用服务。HA
的自动故障转移依赖于ZooKeeper
的以下功能:
①故障检测 :集群中的每个NameNode
在ZooKeeper
中维护了一个持久会话,如果机器崩溃,ZooKeeper
中的会话将终止,ZooKeeper
通知另一个DataNode
需要触发故障转移。
②现役NameNode
选择: ZooKeeper
提供了一个简单的机制用于唯一的选择一个节点为Active
状态。如果目前现役NameNode
崩溃,另一个节点可能从ZooKeeper
获得特殊的排外锁以表明它应该称为现役NameNode
。
ZKFC
是自动故障转移的另一个新组件,是ZooKeeper
的客户端,也监视和管理NameNode
的状态。每个运行NameNode
的主机也运行一个ZKFC
进程,ZKFC
负责:
①健康监测:ZKFC
使用一个健康检查命令定期地ping
与之在相同主机的NameNode
,只要该NameNode
及时地回复健康状态,ZKFC
认为该节点是健康的。如果该节点崩溃,冻结或进入不健康状态,健康监测器标识该节点为非健康的。
②ZooKeeper会话管理: 当本地NameNode
是健康的,ZKFC
保持一个在ZooKeeper
中打开的会话。如果本地NameNode
处于Active
状态,ZKFC
也保持一个特殊的znode
锁,该锁使用了ZooKeeper
对短暂节点的支持,如果会话终止,锁节点将自动删除。
③基于ZooKeeper的选择: 如果本地NameNode
是健康的,且ZKFC
发现没有其它的节点当前持有znode
锁,它将为自己获取该锁。如果成功,则它已经赢得了选择,并负责运行故障转移进程以使它的本地NameNode
为Active
。故障转移进程与前面描述的手动故障转移相似,首先如果必要保护之前的现役NameNode
,然后本地NameNode
转换为Active
状态。
ZooKeeper
集群和完全分布运行模式Hadoop
集群的搭建。
JournalNode:两个NameNode
为了数据同步,会通过一组称作JournalNodes
的独立进程进行相互通信。
hadoop100 | hadoop101 | hadoop1042 |
---|---|---|
NameNode | NameNode | |
JournalNode | JournalNode | JournalNode |
DataNode | DataNode | DataNode |
ZooKeeper | ZK | ZK |
ResourceManager | ResourceManager | SecondaryNameNode |
NodeManager | NodeManager | NodeManager |
①拷贝之前的Hadoop
文件到HA
文件夹
[ hadoop-2.7.2]# cp -r hadoop-2.7.2/ /opt/module/HA/
②配置core-site.xml
<!-- 指定HDFS中NameNode的地址 --> <property> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> </property> <!-- 指定Hadoop运行时产生文件的存储目录 --> <property> <name>hadoop.tmp.dir</name> <value>/opt/module/HA/hadoop-2.7.2/data/tmp</value> </property>
③配置hdfs-site.xml
<!-- 完全分布式集群名称 --> <property> <name>dfs.nameservices</name> <value>mycluster</value> </property> <!--指定NameNode节点的名称--> <property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2</value> </property> <!-- nn1的RPC通信地址 --> <property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>hadoop100:9000</value> </property> <!-- nn2的RPC通信地址 --> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>hadoop101:9000</value> </property> <!-- nn1的http通信地址 --> <property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>hadoop100:50070</value> </property> <!-- nn2的http通信地址 --> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>hadoop101:50070</value> </property> <!-- 指定NameNode元数据在JournalNode上的存放位置 --> <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://hadoop100:8485;hadoop101:8485;hadoop102:8485/mycluster</value> </property> <!-- 配置隔离机制,即同一时刻只能有一台服务器对外响应 --> <property> <name>dfs.ha.fencing.methods</name> <value>sshfence</value> </property> <!-- 使用隔离机制时需要ssh无秘钥登录--> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/root/.ssh/id_rsa</value> </property> <!-- 声明journalnode服务器存储目录--> <property> <name>dfs.journalnode.edits.dir</name> <value>/opt/module/HA/hadoop-2.7.2/data/jn</value> </property> <!-- 关闭权限检查--> <property> <name>dfs.permissions.enable</name> <value>false</value> </property> <!-- 访问代理类:client,mycluster,active配置失败自动切换实现方式--> <property> <name>dfs.client.failover.proxy.provider.mycluster</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property>
④分发HA
[ HA]# xsync ./HA/
①在各个节点上启动JournalNode
服务
[ hadoop-2.7.2]# sbin/hadoop-daemon.sh start journalnode
②在nn1
上,对其进行格式化并启动
[ hadoop-2.7.2]# bin/hdfs namenode -format [ hadoop-2.7.2]# sbin/hadoop-daemon.sh start namenode
③在nn2
上,同步nn1
的元数据信息
[ hadoop-2.7.2]# bin/hdfs namenode -bootstrapStandby
④启动nn2
[ hadoop-2.7.2]# sbin/hadoop-daemon.sh start namenod
⑤将nn1
切换为Active
[ hadoop-2.7.2]# bin/hdfs haadmin -transitionToActive nn1
⑥查看是否Active
[ hadoop-2.7.2]# bin/hdfs haadmin -getServiceState nn1
①具体配置
【hdfs-site.xml
】
<!--配置HDFS-HA自动故障转移--> <property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property>
【core-site.xml
】
<property> <name>ha.zookeeper.quorum</name> <value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value> </property>
②关闭所有HDFS
服务
[ hadoop-2.7.2]# sbin/stop-dfs.sh
③启动ZooKeeper
集群
[ hadoop-2.7.2]# bin/zkServer.sh start [ hadoop-2.7.2]# cat zkServer.sh #!/bin/bash if (($#==0)) then exit 1; fi for i in hadoop100 hadoop101 hadoop102 do echo Starting zk in $i ssh $i "source /etc/profile && /opt/module/zookeeper-3.4.10/bin/zkServer.sh $1" > /dev/null done
④初始化HA
在ZooKeeper
中状态
[ hadoop-2.7.2]# bin/hdfs zkfc -formatZK
⑤启动HDFS
服务
[ hadoop-2.7.2]# sbin/start-dfs.sh
⑥验证:杀死NameNode
进程
[ hadoop-2.7.2]# kill -9 2883
杀死nn1
后,此时NamaNode
已经切换为nn2
通过查看ZKFC
的日志,可以发现没有fuser
命令,安装fuser
命令后重启HDFS
后即能完成故障转移
规划集群:
hadoop100 | hadoop101 | hadoop1042 |
---|---|---|
NameNode | NameNode | |
JournalNode | JournalNode | JournalNode |
DataNode | DataNode | DataNode |
ZooKeeper | ZK | ZK |
ResourceManager | ResourceManager | SecondaryNameNode |
NodeManager | NodeManager | NodeManager |
具体配置:
①配置【yarn-site.xml
】
<!-- Reducer获取数据的方式 --> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <!--启用resourcemanager ha--> <property> <name>yarn.resourcemanager.ha.enabled</name> <value>true</value> </property> <!--声明两台resourcemanager的地址--> <property> <name>yarn.resourcemanager.cluster-id</name> <value>cluster-yarn1</value> </property> <property> <name>yarn.resourcemanager.ha.rm-ids</name> <value>rm1,rm2</value> </property> <property> <name>yarn.resourcemanager.hostname.rm1</name> <value>hadoop100</value> </property> <property> <name>yarn.resourcemanager.hostname.rm2</name> <value>hadoop101</value> </property> <!--指定zookeeper集群的地址--> <property> <name>yarn.resourcemanager.zk-address</name> <value>hadoop100:2181,hadoop101:2181,hadoop102:2181</value> </property> <!--启用自动恢复--> <property> <name>yarn.resourcemanager.recovery.enabled</name> <value>true</value> </property> <!--指定resourcemanager的状态信息存储在zookeeper集群--> <property> <name>yarn.resourcemanager.store.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value> </property>
②同步更新其他节点的配置信息
③启动YARN
[ hadoop-2.7.2]# sbin/start-yarn.sh [ hadoop-2.7.2]# sbin/yarn-daemon.sh start resourcemanager [ hadoop-2.7.2]# bin/yarn rmadmin -getServiceState rm1 active [ hadoop-2.7.2]# bin/yarn rmadmin -getServiceState rm2 standby