Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)

配置 hadoop 高可用集群的原因:如果集群只有一个 NameNode,若NameNode 节点出现故障,那么整个集群都无法使用,也就是存在单点故障的隐患,hadoop 高可用集群能够实现 standby NameNode 自动切换为 active。
HA 的架构,节点个数一般为奇数个,有两个 NameNode,一台为 active 状态,一台为 standby 状态,active NameNode 对外提供服务,standby Namenode 实时同步了 active NameNode 的元数据,当 active NameNode 节点出现故障,standby NameNode 节点可立即切换为active状态并对外提供服务,ResourceManager 同理。所以,在实际生产中一般采用 HA 架构来提高集群的可靠性。

我这里用三台机器来搭建 Hadoop 高可用集群,hadoop 版本3.2.1
集群规划

hostname ip 启动的进程
Master 192.168.150.141 NameNode,DataNode,JournalNode,DFSZKFailoverController,NodeManager,Jps,ResourceManager,QuorumPeerMain
Worker1 192.168.150.142 NameNode,DataNode,JournalNode,DFSZKFailoverController,NodeManager,Jps,ResourceManager,QuorumPeerMain
Worker2 192.168.150.143 DataNode,JournalNode,NodeManager,Jps,QuorumPeerMain

集群可以自己规划,节点最好为奇数,最少为3个节点
以下步骤之前,hadoop,jdk,防火墙等先设置好

一、安装ZooKeeper

先只在一台机器上下载安装并配置好 zookeeper 后,再将配置好的 zookeeper 传给其他节点

1、下载ZooKeeper

Apache ZooKeeper 官网:https://zookeeper.apache.org/releases.html#download
我下载的版本是3.6.1
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第1张图片
点击这个链接开始下载
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第2张图片
下载完成后上传到虚拟机中
也可以直接在虚拟机中用 wget 命令下载

cd ~/software
wget http://archive.apache.org/dist/zookeeper/zookeeper-3.6.1/apache-zookeeper-3.6.1-bin.tar.gz

2、解压ZooKeeper

下载完成后解压到 /usr/local 目录下

sudo tar -zxvf apache-zookeeper-3.6.1-bin.tar.gz -C /usr/local/

重命名 apache-zookeeper-3.6.1-bin 为 zookeeper

cd /usr/local
sudo mv apache-zookeeper-3.6.1-bin zookeeper

3、设置环境变量

vim ~/.bashrc

增加

export ZOOKEEPER_HOME=/usr/local/zookeeper

在 PATH 中添加

$ZOOKEEPER_HOME/bin

(注意冒号:隔开)
我的配置如下
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第3张图片
另外两台机器也要配置环境变量,方法如上
使配置生效

source ~/.bashrc

4、配置ZooKeeper

进入 conf 目录

cd /usr/local/zookeeper/conf/

将 zoo_sample.cfg 复制一份并命名为 zoo.cfg

sudo cp zoo_sample.cfg zoo.cfg

修改 zoo.cfg

sudo vi zoo.cfg

修改 dataDir,改为存储数据的路径(要存在),改成

dataDir=/usr/local/zookeeper/data

Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第4张图片
接着在最后添加

server.1=192.168.150.141:2888:3888
server.2=192.168.150.142:2888:3888
server.3=192.168.150.143:2888:3888

ip改成你自己机器的
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第5张图片
保存退出
刚刚存数据的路径不存在的话记得创建

sudo mkdir /usr/local/zookeeper/data

再在这个 data 目录下创建一个名为 myid 的文件

sudo touch /usr/local/zookeeper/data/myid 

向这个 myid 文件中写入 ID(ID 与前面 server.x 的 x 一致)

sudo vi /usr/local/zookeeper/data/myid

在这里插入图片描述
修改 zookeeper 文件权限

sudo chown -R hadoop:hadoop zookeeper

将配置好的 zookeeper 传给其他节点

sudo scp -r /usr/local/zookeeper 192.168.150.142:/usr/local/
sudo scp -r /usr/local/zookeeper 192.168.150.143:/usr/local/

传送完成后,需要在这些机器上修改 myid 文件,改成机器对应的 id
Worker1

sudo vi /usr/local/zookeeper/data/myid 

在这里插入图片描述
Worker2

sudo vi /usr/local/zookeeper/data/myid 

在这里插入图片描述

二、配置Hadoop高可用集群

hadoop 没安装好的先将 hadoop 安装好再开始以下步骤

1、NameNode高可用

我的 hadoop 配置文件在 /usr/local/hadoop/etc/hadoop 目录下

cd /usr/local/hadoop/etc/hadoop

(1)修改 core-site.xml

vim core-site.xml

我的配置如下

<configuration>
        <property>
                <name>fs.defaultFS</name>
                <value>hdfs://myNameService1</value>
        </property>
        <property>
                <name>hadoop.tmp.dir</name>
                <value>file:/usr/local/hadoop/tmp</value>
                <description>Abase for other temporary directories.</description>
        </property>

        <!-- 指定zookeeper地址 -->
        <property>
                <name>ha.zookeeper.quorum</name>
                <value>Master:2181,Worker1:2181,Worker2:2181</value>
        </property>

</configuration>

上面指定 zookeeper 地址中的 Master,Worker1,Worker2 换成你自己机器的主机名(要先配置好主机名与 IP 的映射)或者 ip
(2)修改 hdfs-site.xml

vim hdfs-site.xml

我的配置如下(主要配置项的作用已在注释中说明)

<configuration>

        <!--指定hdfs的nameservice为myNameService1,需要和core-site.xml中的保持一致 -->
        <property>
                <name>dfs.nameservices</name>
                <value>myNameService1</value>
        </property>

        <!-- myNameService1下面有两个NameNode,分别是nn1,nn2 -->
        <property>
                <name>dfs.ha.namenodes.myNameService1</name>
                <value>nn1,nn2</value>
        </property>

        <!-- nn1的RPC通信地址 -->
        <property>
                <name>dfs.namenode.rpc-address.myNameService1.nn1</name>
                <value>Master:9000</value>
        </property>

        <!-- nn1的http通信地址 -->
        <property>
                <name>dfs.namenode.http-address.myNameService1.nn1</name>
                <value>Master:50070</value>
        </property>

        <!-- nn2的RPC通信地址 -->
        <property>
                <name>dfs.namenode.rpc-address.myNameService1.nn2</name>
                <value>Worker1:9000</value>
        </property>

        <!-- nn2的http通信地址 -->
        <property>
                <name>dfs.namenode.http-address.myNameService1.nn2</name>
                <value>Worker1:50070</value>
        </property>

        <!-- 指定NameNode的元数据在JournalNode上的存放位置 -->
        <property>
                <name>dfs.namenode.shared.edits.dir</name>
                <value>qjournal://Master:8485;Worker1:8485;Worker2:8485/myNameService1</value>
        </property>

        <!-- 指定JournalNode在本地磁盘存放数据的位置 -->
        <property>
                <name>dfs.journalnode.edits.dir</name>
                <value>/usr/local/hadoop/journalData</value>
        </property>

        <!-- 开启NameNode失败自动切换 -->
        <property>
                <name>dfs.ha.automatic-failover.enabled</name>
                <value>true</value>
        </property>

        <!-- 配置失败自动切换实现方式 -->
        <property>
                <name>dfs.client.failover.proxy.provider.myNameService1</name>
                <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
        </property>

        <!-- 配置隔离机制方法,Failover后防止停掉的Namenode启动,造成两个服务,多个机制用换行分割,即每个机制暂用一行-->
        <property>
                <name>dfs.ha.fencing.methods</name>
                <value>
                        sshfence
                        shell(/bin/true)
                </value>
        </property>

        <!-- 使用sshfence隔离机制时需要ssh免登陆,注意换成自己的用户名 -->
        <property>
                <name>dfs.ha.fencing.ssh.private-key-files</name>
                <value>/home/hadoop/.ssh/id_rsa</value>
        </property>

        <!-- 配置sshfence隔离机制超时时间 -->
        <property>
                <name>dfs.ha.fencing.ssh.connect-timeout</name>
                <value>30000</value>
        </property
        
        <property>
                <name>dfs.replication</name>
                <value>2</value>
        </property>
        <property>
                <name>dfs.namenode.name.dir</name>
                <value>file:/usr/local/hadoop/tmp/dfs/name</value>
        </property>
        <property>
                <name>dfs.datanode.data.dir</name>
                <value>file:/usr/local/hadoop/tmp/dfs/data</value>
        </property>
        <property>
                <name>dfs.permissions</name>
                <value>false</value>
        </property>

</configuration>

2、Yarn高可用

(1)修改 mapred-site.xml

vim mapred-site.xml 

我的配置如下

<configuration>

        <!-- 指定mr框架为yarn方式 -->
        <property>
                <name>mapreduce.framework.name</name>
                <value>yarn</value>
        </property>

        <!-- 配置 MapReduce JobHistory Server 地址 ,默认端口10020 -->
        <property>
                <name>mapreduce.jobhistory.address</name>
                <value>Master:10020</value>
        </property>

        <!-- 配置 MapReduce JobHistory Server web ui 地址, 默认端口19888 -->
        <property>
                <name>mapreduce.jobhistory.webapp.address</name>
                <value>Master:19888</value>
        </property>

        <property>
                <name>mapreduce.application.classpath</name>
                <value>/usr/local/hadoop/share/hadoop/mapreduce/*,/usr/local/hadoop/share/hadoop/mapreduce/lib/*</value>
        </property>

</configuration>

(2)修改 yarn-site.xml

vim yarn-site.xml

我的配置如下(主要配置项的作用已在注释中说明)

<configuration>

<!-- Site specific YARN configuration properties -->

        <!-- 开启RM高可用 -->
        <property>
                <name>yarn.resourcemanager.ha.enabled</name>
                <value>true</value>
        </property>

        <!-- 指定RM的cluster id -->
        <property>
                <name>yarn.resourcemanager.cluster-id</name>
                <value>yrc</value>
        </property>

        <!-- 指定RM的名字 -->
        <property>
                <name>yarn.resourcemanager.ha.rm-ids</name>
                <value>rm1,rm2</value>
        </property>

        <!-- 分别指定RM的地址 -->
        <property>
                <name>yarn.resourcemanager.hostname.rm1</name>
                <value>Master</value>
        </property>

        <property>
                <name>yarn.resourcemanager.hostname.rm2</name>
                <value>Worker1</value>
        </property>
        
		<!-- RM对外暴露的web http地址,用户可通过该地址在浏览器中查看集群信息 -->
        <property>
                <name>yarn.resourcemanager.webapp.address.rm1</name>
                <value>Master:8088</value>
        </property>

        <property>
                <name>yarn.resourcemanager.webapp.address.rm2</name>
                <value>Worker1:8088</value>
        </property>
        
        <!-- 指定zookeeper集群地址 -->
        <property>
                <name>yarn.resourcemanager.zk-address</name>
                <value>Master:2181,Worker1:2181</value>
        </property>

        <property>
                <name>yarn.nodemanager.aux-services</name>
                <value>mapreduce_shuffle</value>
        </property>

        <property>
                <name>yarn.application.classpath</name>
                <value>/usr/local/hadoop/etc/hadoop:/usr/local/hadoop/share/hadoop/common/lib/*:/usr/local/hadoop/share/hadoop/common/*:/usr/local/hadoop/share/hadoop/hdfs:/usr/local/hadoop/share/hadoop/hdfs/lib/*:/usr/local/hadoop/share/hadoop/hdfs/*:/usr/local/hadoop/share/hadoop/mapreduce/lib/*:/usr/local/hadoop/share/hadoop/mapreduce/*:/usr/local/hadoop/share/hadoop/yarn:/usr/local/hadoop/share/hadoop/yarn/lib/*:/usr/local/hadoop/share/hadoop/yarn/*</value>
        </property>

</configuration>

3、修改workers文件

vim /usr/local/hadoop/etc/hadoop/workers

里面写上你的 datanode 节点名称,我这里三台机都启动 datanode
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第6张图片

4、配置ssh免密码登陆

这里就不详细说明了,网上有很多教程

5、在其他机器上配置

上面三个步骤完成后,可以直接用 scp 命令将配置好的 hadoop 分发到其他机器上,我的机器已经有了之前的 hadoop,这里只修改了几个配置文件,因此我只需把这些配置文件覆盖到另外两台机器即可(若其他机器没有安装 hadoop,那就将整个 hadoop 文件传输过去)

cd /usr/local/hadoop/etc/hadoop 

传到 Worker1

sudo scp core-site.xml Worker1:/usr/local/hadoop/etc/hadoop 
sudo scp hdfs-site.xml Worker1:/usr/local/hadoop/etc/hadoop
sudo scp mapred-site.xml Worker1:/usr/local/hadoop/etc/hadoop 
sudo scp yarn-site.xml Worker1:/usr/local/hadoop/etc/hadoop 
sudo scp workers Worker1:/usr/local/hadoop/etc/hadoop

传到 Worker2

sudo scp core-site.xml Worker2:/usr/local/hadoop/etc/hadoop 
sudo scp hdfs-site.xml Worker2:/usr/local/hadoop/etc/hadoop
sudo scp mapred-site.xml Worker2:/usr/local/hadoop/etc/hadoop 
sudo scp yarn-site.xml Worker2:/usr/local/hadoop/etc/hadoop 
sudo scp workers Worker2:/usr/local/hadoop/etc/hadoop

三、初始化并启动集群

第一次系统启动,需要初始化,严格按照以下步骤
1、启动 zookeeper 集群
分别在三台机器上执行如下命令

zkServer.sh start

在这里插入图片描述
查看状态

zkServer.sh status

三台机中一台 leader,两台 follower
Master
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第7张图片
Worker1
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第8张图片
Worker2
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第9张图片
2、启动journalnode
分别在三台机器上执行

hadoop-daemon.sh start journalnode

然后用 jps 命令查看,可以发现三台机器都多了 JournalNode 进程
Master
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第10张图片
Worker1
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第11张图片
Worker2
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第12张图片
3、格式化 hdfs
第一次启动需要格式化,后面启动不再需要
格式化会根据 core-site.xml 中的 hadoop.tmp.dir 配置生成一个目录,如果之前有格式化过,那么先删除所有节点的该目录,比如我这里配置的是 /usr/local/hadoop/tmp,我之前有格式化过,那么我需要先删除所有结点的该目录
在三个节点上执行

rm -rf /usr/local/hadoop/tmp/

接着开始格式化,在 Master 上执行

hdfs namenode -format

这里只需要在一个 namenode 节点上执行,另一个 namenode 同步数据就好(如果两个你都格式化了那就错了)
成功的话可以看到 successfully formatted
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第13张图片
同步数据
将 /usr/local/hadoop/tmp/ 传输到 Worker1 节点上

sudo scp -r /usr/local/hadoop/tmp Worker1:/usr/local/hadoop/

Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第14张图片
4、格式化 zookeeper
同样,第一次启动需要格式化,后面启动不再需要
在 Master 上执行即可

hdfs zkfc -formatZK

Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第15张图片
5、启动 HDFS
在 Master 上执行

start-dfs.sh

6、启动 YARN
在 Master 上执行

start-yarn.sh

因为我这里 namenode 和 resourcemanager 在同一台机器上,因此启动 hdfs 和 yarn 也可以用一条命令 start-all.sh 来启动,但是建议分成两步启动,如果 namenode 和 resourcemanager 分开了就要分别在不同的机器上启动

四、测试集群

启动完成后浏览器访问下面的地址(ip 换成你自己的)
http://192.168.150.141:50070/
可以看到这个 namenode 处于 active 状态
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第16张图片
http://192.168.150.142:50070/
这个 namenode 处于 standby 状态
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第17张图片
此时访问 Master:8088 页面和 Worker1:8088 页面,Worker1:8088 页面会自动跳转到 Master:8088 的web页面
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第18张图片
测试集群的高可用性
用 kill 命令强制结束正处于 active 的 namenode
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第19张图片

kill -9 2493

刷新刚刚处于 standby 状态的 namenode 的50070页面,可以看到该节点变成 active 了
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第20张图片
也可以用 hadoop jar 命令运行自带的 jar 包来测试,在运行过程中用 kill -9 namenode的进程号 来强制杀死 active 的namenode,如果仍然能正常运行且结果正确,说明你的 hadoop 高可用集群搭建成功!

五、集群启动和关闭顺序

1、启动集群

三台机器先启动 zookeeper 集群

zkServer.sh start

master 机器上先启动 hdfs 再启动 yarn

start-dfs.sh 
start-yarn.sh 

以上两句可以用 start-all.sh 一并启动,但是最好分步启动
需要的话可以启动 history 服务

mr-jobhistory-daemon.sh start historyserver

2、关闭集群

master 机器上先停止 yarn 再停止 hdfs

stop-yarn.sh
stop-dfs.sh

stop-all.sh

三台机器关闭 zookeeper 集群

zkServer.sh stop

六、遇到的错误

运行自带的计算 pi 值程序时出错
Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用)_第21张图片
在 yarn 的管理界面上查看运行日志发现如下错误

2020-05-14 12:01:15,049 ERROR [Listener at 0.0.0.0/37114] org.apache.hadoop.mapreduce.v2.app.MRAppMaster: Error starting MRAppMaster
org.apache.hadoop.yarn.exceptions.YarnRuntimeException: java.lang.NullPointerException
	at org.apache.hadoop.mapreduce.v2.app.rm.RMCommunicator.register(RMCommunicator.java:178)
	at org.apache.hadoop.mapreduce.v2.app.rm.RMCommunicator.serviceStart(RMCommunicator.java:122)
	at org.apache.hadoop.mapreduce.v2.app.rm.RMContainerAllocator.serviceStart(RMContainerAllocator.java:280)
	at org.apache.hadoop.service.AbstractService.start(AbstractService.java:194)
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster$ContainerAllocatorRouter.serviceStart(MRAppMaster.java:979)
	at org.apache.hadoop.service.AbstractService.start(AbstractService.java:194)
	at org.apache.hadoop.service.CompositeService.serviceStart(CompositeService.java:121)
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.serviceStart(MRAppMaster.java:1293)
	at org.apache.hadoop.service.AbstractService.start(AbstractService.java:194)
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster$6.run(MRAppMaster.java:1761)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:422)
	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1730)
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.initAndStartAppMaster(MRAppMaster.java:1757)
	at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.main(MRAppMaster.java:1691)
Caused by: java.lang.NullPointerException
	at org.apache.hadoop.mapreduce.v2.app.client.MRClientService.getHttpPort(MRClientService.java:177)
	at org.apache.hadoop.mapreduce.v2.app.rm.RMCommunicator.register(RMCommunicator.java:159)
	... 14 more
2020-05-14 12:01:15,059 INFO [Listener at 0.0.0.0/37114] org.apache.hadoop.util.ExitUtil: Exiting with status 1: org.apache.hadoop.yarn.exceptions.YarnRuntimeException: java.lang.NullPointerException

原因:大概是 MRClientService 的 WebApp 创建过程出错,导致 WebApp 对象为 null,后边调用了 WebApp 的 getHttpPort() 方法,导致空指针

解决方法:一种是修改源码重新编译生成 class 文件(比较麻烦),简单的方法就是直接在 yarn-site.xml 文件中添加

<property> 
    <name>yarn.resourcemanager.webapp.address.rm1</name>  
    <value>Master:8088</value> 
</property>  

<property> 
    <name>yarn.resourcemanager.webapp.address.rm2</name>  
    <value>Worker1:8088</value> 
</property>

Master 和 Worker1 换成你自己的 ResourceManager 节点
加上后正常运行!

你可能感兴趣的:(Hadoop3.2.1 HA 高可用集群的搭建(基于Zookeeper,NameNode高可用+Yarn高可用))