目录
HA高可用搭建
资料链接
链接:https://pan.baidu.com/s/1ytGL3cLGQxGltl5bHrSBQQ
提取码:yikm
前提
- 基础配置:修改主机名、主机映射、时区修改、时间同步、定时任务、免密访问;
- JDK安装:环境变量;
- Zookeeper部署:环境变量、配置文件zoo.cfg、myid;
以上全部配置完毕!并且zookeeper已开启!
HA基础配置
1、将hadoop安装包解压到指定路径/usr/hadoop(安装包存放于/usr/package/)
操作环境: master、slave1、slave2
mkdir -p /usr/hadoop
tar -zxvf /usr/package/hadoop-2.7.3.tar.gz -C /usr/hadoop/
2、配置Hadoop环境变量,注意生效($HADOOP_HOME)
操作环境: master、slave1、slave2
vim /etc/profile
在其中加入以下内容
#hadoop
export HADOOP_HOME=/usr/hadoop/hadoop-2.7.3
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
生效环境变量
source /etc/profile
创建存储文件夹
mkdir -p /usr/hadoop/hadoop-2.7.3/hdfs #存放namenode和datanode的数据
mkdir -p /usr/hadoop/hadoop-2.7.3/tmp #存放临时文件
hadoop-env.sh
配置hadoop运行环境JAVA_HOME
操作环境: master、slave1、slave2
cd /usr/hadoop/hadoop-2.7.3/etc/hadoop/
vim hadoop-env.sh
在28行加入:
export JAVA_HOME=/usr/java/jdk1.8.0_171
core-site.xml
操作环境: master、slave1、slave2
编辑core-site.xml
vim core-site.xml
添加以下内容:
<configuration>
<property>
<!-- hdfs 地址,ha中是连接到nameservice -->
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
<property>
<!-- -->
<name>hadoop.tmp.dir</name>
<value>/usr/hadoop/hadoop-2.7.3/tmp</value>
</property>
<!-- 指定zookeeper地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>master:2181,slave1:2181,slave2:2181</value>
</property>
<!-- hadoop链接zookeeper的超时时长设置 -->
<property>
<name>ha.zookeeper.session-timeout.ms</name>
<value>30000</value>
<description>ms</description>
</property>
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>
<property>
<name>hadoop.proxyuser.root.groups</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.root.hosts</name>
<value>*</value>
</property>
</configuration>
hdfs-site.xml
操作环境: slave1、master、slave2
编辑hdfs-site.xml
vim hdfs-site.xml
添加以下内容:
<configuration>
<property>
<!-- 为namenode集群定义一个services name -->
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<property>
<!-- nameservice 包含哪些namenode,为各个namenode起名 -->
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
<property>
<!-- 名为nn1的namenode 的rpc地址和端口号,rpc用来和datanode通讯 -->
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>master:9000</value>
</property>
<property>
<!-- 名为nn2的namenode 的rpc地址和端口号,rpc用来和datanode通讯 -->
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>slave1:9000</value>
</property>
<property>
<!--名为nn1的namenode 的http地址和端口号,web客户端 -->
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>master:50070</value>
</property>
<property>
<!--名为nn2的namenode 的http地址和端口号,web客户端 -->
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>slave1:50070</value>
</property>
<property>
<!-- namenode间用于共享编辑日志的journal节点列表 -->
<!-- 指定NameNode的edits元数据的共享存储位置。也就是JournalNode列表
该url的配置格式:qjournal://host1:port1;host2:port2;host3:port3/journalId
journalId推荐使用nameservice,默认端口号是:8485 -->
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://master:8485;slave1:8485;slave2:8485/mycluster</value>
</property>
<property>
<!-- journalnode 上用于存放edits日志的目录 -->
<name>dfs.journalnode.edits.dir</name>
<value>/usr/hadoop/hadoop-2.7.3/tmp/jn</value>
</property>
<property>
<!-- 客户端连接可用状态的NameNode所用的代理类 -->
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
<!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行 -->
<name>dfs.ha.fencing.methods</name>
<value>
sshfence
</value>
<value>
shell(/bin/true)
</value>
</property>
<!-- 使用sshfence隔离机制时需要ssh免登陆 -->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>
<!-- journalnode集群之间通信的超时时间 -->
<property>
<name>dfs.qjournal.start-segment.timeout.ms</name>
<value>60000</value>
</property>
<!-- 指定副本数 -->
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<!--namenode路径-->
<property>
<name>dfs.namenode.name.dir</name>
<value>/usr/hadoop/hadoop-2.7.3/hdfs/nn</value>
</property>
<!--datanode路径-->
<property>
<name>dfs.datanode.data.dir</name>
<value>/usr/hadoop/hadoop-2.7.3/hdfs/dn</value>
</property>
<!-- 开启NameNode失败自动切换 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- 启用webhdfs -->
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
<!-- 配置sshfence隔离机制超时时间 -->
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>
<property>
<name>ha.failover-controller.cli-check.rpc-timeout.ms</name>
<value>60000</value>
</property>
</configuration>
yarn-env.sh
设置YARN运行环境JAVA_HOME参数
操作环境: master、slave1、slave2
编辑yarn-env.sh
vim yarn-env.sh
插入以下内容:
export JAVA_HOME=/usr/java/jdk1.8.0_171
yarn-site.xml
操作环境: master、slave1、slave2
编辑yarn-site.xml
vim yarn-site.xml
插入以下内容:
<configuration>
<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>106800</value>
</property>
<property>
<!-- 启用resourcemanager的ha功能 -->
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<property>
<!-- 为resourcemanage ha 集群起个id -->
<name>yarn.resourcemanager.cluster-id</name>
<value>yarn-cluster</value>
</property>
<property>
<!-- 指定resourcemanger ha 有哪些节点名 -->
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<property>
<!-- 指定第一个节点的所在机器 -->
<name>yarn.resourcemanager.hostname.rm1</name>
<value>master</value>
</property>
<property>
<!-- 指定第二个节点所在机器 -->
<name>yarn.resourcemanager.hostname.rm2</name>
<value>slave1</value>
</property>
<property>
<!-- 指定resourcemanger ha 所用的zookeeper 节点 -->
<name>yarn.resourcemanager.zk-address</name>
<value>master:2181,slave1:2181,slave2:2181</value>
</property>
<property>
<!-- -->
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
</configuration>
mapred-site.xml
操作环境: master、slave1、slave2
mv mapred-site.xml.template mapred-site.xml
vim mapred-site.xml
插入以下内容:
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
节点文件设置
操作环境: master、slave1、slave2
vim slaves
修改为:
master
slave1
slave2
启动
cd /usr/hadoop/hadoop-2.7.3/
在master[nn1]上,启动所有的journalnode:
在master[nn1]上,对其进行格式化:
bin/hdfs namenode -format
在master[nn1]上,初始化HA在zookeeper中状态:
bin/hdfs zkfc -formatZK
在master[nn1]上,启动namenode:
sbin/hadoop-daemon.sh start namenode
在slave1[nn2]上,同步master元数据信息:
bin/hdfs namenode -bootstrapStandby
在slave1[nn2]上,启动namenode:
sbin/hadoop-daemon.sh start namenode
在master[nn1]上,启动所有datanode:
sbin/hadoop-daemons.sh start datanode
在各个namenode节点上(master[nn1],slave1[nn2])启动DFSZK Failover Controller(先在哪台机器启动,哪个机器的namenode就是active namenode):
sbin/hadoop-daemon.sh start zkfc
到此为止集群启动完毕
查看
在web中输入查看:
记得在windows中hosts中做ip地址映射!
master:50070
slave1:50070
查看[nn1]是否为active
bin/hdfs haadmin -getServiceState nn1
bin/hdfs haadmin -getServiceState nn2
启动yarn
在master上执行:
sbin/start-yarn.sh
在slave1上执行:
sbin/yarn-daemon.sh start resourcemanager
在master上,查看服务状态:
bin/yarn rmadmin -getServiceState rm1
bin/yarn rmadmin -getServiceState rm2
在web中输入查看:
master:8088
输入slave1:8088会自动跳转:
测试
终止namenode进程(在active节点上):
kill -9 进程号
成功
关闭进程
在master上:
sbin/stop-dfs.sh
sbin/stop-yarn.sh
在slave1上:
sbin/yarn-daemon.sh stop resourcemanager
在三台机器上:
zkServer.sh stop
完毕
基本原理
1、namenode高可用
我们知道namenode是整个hdfs的核心,如果namenode挂了,那么整个hdfs文件系统也不能提供服务,所以hadoop对hdfs提供了高可用的方案,即Hadoop HA,hdfs的高可用提供了两种方案,一种是基于QJM(Quorum Journal Manager)的,一种是基于NFS的,我们用的一般都是基于QJM的,所以这里也是讲基于QJM的高可用,高可用用来解决NameNode单点故障的问题。解决的方法是在HDFS集群中设置多个NameNode节点。那么提供多个namenode必定存在新的问题:
1、如何保证NameNode内存中元数据数据一致,并保证编辑日志文件的安全性。
2、多个NameNode如何协作
3、客户端如何能正确地访问到可用的那个NameNode。
4、怎么保证任意时刻只能有一个NameNode处于对外服务状态
针对如上问题,hadoop提供了如下解决方案:
对于保证NameNode元数据的一致性和编辑日志的安全性,采用Zookeeper来存储编辑日志文件。
两个NameNode一个是Active状态的,一个是Standby状态的,一个时间点只能有一个Active状态的 。
NameNode提供服务,两个NameNode上存储的元数据是实时同步的,当Active的NameNode出现问题时,通过Zookeeper实时切换到Standby的NameNode上,并将Standby改为Active状态。
客户端通过连接一个Zookeeper的代理来确定当时哪个NameNode处于服务状态。
我们看一下hdfs高可用的架构图:如下图所示:
HDFS HA架构中有两台NameNode节点,一台是处于活动状态(Active)为客户端提供服务,另外一台处于热备份状态(Standby)。
DataNode会将心跳信息和Block汇报信息同时发给两台NameNode,DataNode只接受Active NameNode发来的文件读写操作指令。为了使备用节点保持其状态与Active节点同步,两个节点都与一组称为“JournalNodes”(JN)的单独守护进程通信。当Active节点执行任何名称空间修改时,它会将修改记录持久地记录到大多数这些JN中。待机节点能够从JN读取编辑,并且不断观察它们对编辑日志的更改。当备用节点看到编辑时,它会将它们应用到自己的命名空间。如果发生故障转移,Standby将确保在将自身升级为Active状态之前已从JournalNodes读取所有编辑内容。这可确保在发生故障转移之前完全同步命名空间状态。注意:必须至少有3个JournalNode守护进程,因为编辑日志修改必须写入大多数JN。这将允许系统容忍单个机器的故障。您也可以运行3个以上的JournalNodes,但为了实际增加系统可以容忍的失败次数,您应该运行奇数个JN(即3,5,7等)。请注意:当使用N JournalNodes运行时,系统最多可以容忍(N-1)/ 2个故障并继续正常运行。
Zookeeper来保证在Active NameNode失效时及时将Standby NameNode修改为Active状态。
故障检测 - 集群中的每个NameNode计算机都在ZooKeeper中维护一个持久会话。如果计算机崩溃,ZooKeeper会话将过期,通知其他NameNode应该触发故障转移。Active NameNode选举 - ZooKeeper提供了一种简单的机制,可以将节点专门选为活动节点。如果当前活动的NameNode崩溃,则另一个节点可能在ZooKeeper中采用特殊的独占锁,指示它应该成为下一个活动的。
ZKFailoverController(ZKFC)是一个新组件,它是一个ZooKeeper客户端,它还监视和管理NameNode的状态。运行NameNode的每台机器也运行ZKFC,ZKFC负责:
1、运行状况监视 : ZKFC定期使用运行状况检查命令对其本地NameNode进行ping操作。只要NameNode及时响应健康状态,ZKFC就认为该节点是健康的。如果节点已崩溃,冻结或以其他方式进入不健康状态,则运行状况监视器会将其标记为运行状况不佳。
2、ZooKeeper会话管理 :当本地NameNode运行正常时,ZKFC在ZooKeeper中保持会话打开。如果本地NameNode处于活动状态,它还拥有一个特殊的“锁定”znode。此锁使用ZooKeeper对“短暂”节点的支持; 如果会话过期,将自动删除锁定节点
3、基于ZooKeeper的选举 :如果本地NameNode是健康的,并且ZKFC发现没有其他节点当前持有锁znode,它将自己尝试获取锁。如果成功,那么它“赢得了选举”,并负责运行故障转移以使其本地NameNode处于活动状态。故障转移过程类似于上述手动故障转移:首先,必要时对先前的活动进行隔离,然后本地NameNode转换为活动状态。
元数据文件有两个文件:fsimage和edits,备份元数据就是备份这两个文件。JournalNode用来实时从Active NameNode上拷贝edits文件,JournalNode有三台也是为了实现高可用。
Standby NameNode不对外提供元数据的访问,它从Active NameNode上拷贝fsimage文件,从JournalNode上拷贝edits文件,然后负责合并fsimage和edits文件,相当于SecondaryNameNode的作用。最终目的是保证Standby NameNode上的元数据信息和Active NameNode上的元数据信息一致,以实现热备份。
2、resourcemanager高可用
首先我们来看一下官方提供的架构图:如图所示:
ResourceManager HA通过主动/备用架构实现 - 在任何时间点,其中一个RM处于活动状态,并且一个或多个RM处于待机模式,等待活动RM出现故障或者宕机时机。转换为活动的触发器来自管理员(通过CLI)或启用自动故障转移时的集成故障转移控制器。
RM可以选择嵌入基于Zookeeper的ActiveStandbyElector来决定哪个RM应该是Active。当Active关闭或无响应时,另一个RM自动被选为Active,然后接管。请注意,不需要像HDFS那样运行单独的ZKFC守护程序,因为嵌入在RM中的ActiveStandbyElector充当故障检测器和领导者选择器而不是单独的ZKFC守护程序。
当存在多个RM时,客户端和节点使用的配置(yarn-site.xml)应该列出所有RM。客户端,应用程序管理器ApplicationMaster(AM)和节点管理器NodeManager(NM)尝试以循环方式连接到RM,直到它们到达活动RM。如果活动停止,他们将恢复循环轮询,直到他们连接到新的RM