hadoop2.7.5+zookeeper3.4.8 HA高可用集群搭建

  • Post author:
  • Post category:其他


环境介绍


系统:CentOS-7-x86_64-DVD-1611.iso 最小化安装


hadoop版本:2.7.5


zookeeper版本:3.4.8


集群介绍


两台namenode


三台datanode

主机名 ip地址 安装的软件 jps进程
master 192.168.89.128 Jdk/hadoop/zookeeper

Namenode/zkfc/resourcemanager/

JobHistoryServer/JournalNode/quorumPeerMain

master1 192.168.89.129 Jdk/hadoop/zookeeper

Namenode/zkfc/resourcemanager/

JobHistoryServer/JournalNode/quorumPeerMain

slave1 192.168.89.130 Jkd/hadoop/zookeeper

Datanode/journalnode/nodemanager/

quorumPeerMain

slave2 192.168.89.131 Jkd/hadoop/zookeeper

Datanode/journalnode/nodemanager/

quorumPeerMain

slave3 192.168.89.132 Jkd/hadoop/zookeeper

Datanode/journalnode/nodemanager/

quorumPeerMain

集群搭建

由于原来搭建的非HA集群只有master、slave1和slave2三台机器,因此需要克隆一台master和一台slave。

原来的非HA集群搭建博文连接:

https://blog.csdn.net/ASN_forever/article/details/80701003

克隆slave和master


①修改主机名

克隆slave1得到slave3,首先需要修改主机名,将slave1修改成slave3


②修改ip和mac地址

克隆后的机器是ping不了的,无法上网。首先查看一下ip如下

可以看到没有分配ip地址,但是因为每个主机都有唯一的mac地址,因此可以看到这里的mac地址与slave1的不同。

接下来查看ifcfg-ens33文件如下

可以看到克隆的机器的网络配置文件ifcfg-ens33与被克隆的一样,这样的话首先ip地址会冲突,其次mac地址也不对应。因此为了避免网络冲突,需要重新分配一个ip地址,并修改mac地址。

修改之后重启网络服务,发现启动成功,并且ping百度也能够ping通了

添加DataNode


①修改hosts文件

为了实现集群各节点之间的SSH无密码登录,首先应该配置hosts文件,使节点之间能够互相ping通。在hosts文件中添加上slave3及对应的ip,并在集群其他节点做同样的修改。


②生成密钥并修改authorized_keys文件

因为克隆过来的密钥文件是slave1的,因此需要使用命令ssh-keygen -t rsa重新生成密钥,除了标红的地方输入y外,其它一路回车即可

可以看到生成的密钥被保存在id_rsa.pub文件中了,因此需要将其内容复制到authorized_keys文件中。并将此密钥添加到集群其他节点的authorized_keys中。

此时通过ssh 主机名进行无密码登录其他节点时,可能会出现权限过大需要输入密码的问题。

解决办法是将id_rsa文件的权限降低到0600,命令为chmod 0600 /root/.ssh/id_rsa


③修改slaves文件

因为是直接克隆过来的,所有jdk,hadoop等文件也都拷贝过来了。只是需要修改涉及到slave3的地方,这里先修改slaves文件。添加上slave3即可,集群上的每台机器都需要修改。


④启动hadoop集群


启动集群可以看到slave3的NodeManager和DataNode进程被顺利启动,说明节点添加成功

但是此时在50070页面发现只有两个DataNode节点,并且刷新后还可能会变。这是因为克隆的原因,导致slave3的datanodeUuid与slave1的相同,因此集群认为它们是同一个DataNode,所以会随机启动一个。具体解决方法点击

这里

添加NameNode节点

类似于DataNode节点的添加步骤,添加namenode时要克隆master。然后修改ip,mac,hosts,slaves。

配置zookeeper


①修改zoo.cfg

在slave1节点上修改zoo.cfg文件,添加slave3的信息如下。其中2888是leader和follower之间的通信端口,3888是集群投票的端口。

修改zookeeper的日志输出路径

修改zookeeper的日志配置文件


②修改myid文件

修改master、master1、slave1、2、3节点的/root/hadoop/zookeeper/data目录下的myid文件,将其内容依次改为1、2、3、4、5。并将slave1中配置好的zookeeper安装包scp到其他节点。


③启动zookeeper查看状态

完成上述配置后,就可以在所有slave节点上启动zookeeper服务,并查看状态了。


(需要关闭防火墙


,否则启动时会报没有到主机的路由之类的错误)

systemctl disable firewalld.service

配置hadoop

hadoop的一些配置,如环境变量之类的已经在非HA集群中配置好了,因此在将非HA变为HA时,只需要修改一下core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml即可。

在一台机器上进行配置后,用scp传输到集群其他节点(如果接收scp的节点已经有hadoop文件,需要先删除再传输,否则可能会无法覆盖?还不是很确定)

我选择在master节点上配置hadoop


配置core-site.xml


配置hdfs-site.xml

<configuration>
  <!-- 指定hdfs元数据存储的路径 -->
  <property>
    <name>dfs.namenode.name.dir</name>
    <value>/root/hadoop/dfs/name</value>
  </property>
 
  <!-- 指定hdfs数据存储的路径 -->
  <property>
    <name>dfs.datanode.data.dir</name>
    <value>/root/hadoop/dfs/data</value>
  </property>
  
  <!-- 数据备份的个数 -->
  <property>
    <name>dfs.replication</name>
    <value>3</value>
  </property>
 
  <!-- 关闭权限验证 -->
  <property>
    <name>dfs.permissions.enabled</name>
    <value>false</value>
  </property>
  
  <!-- 开启WebHDFS功能(基于REST的接口服务) -->
  <property>
    <name>dfs.webhdfs.enabled</name>
    <value>true</value>
  </property>
  
  <!-- //以下为HDFS HA的配置// -->
  <!-- 指定hdfs的nameservices名称为mycluster -->
  <property>
    <name>dfs.nameservices</name>
    <value>ns1</value>
  </property>
 
  <!-- 指定mycluster的两个namenode的名称分别为nn1,nn2 -->
  <property>
    <name>dfs.ha.namenodes.ns1</name>
    <value>nn1,nn2</value>
  </property>
 
  <!-- 配置nn1,nn2的rpc通信端口 -->
  <property>
    <name>dfs.namenode.rpc-address.ns1.nn1</name>
    <value>master:9000</value>
  </property>
  <property>
    <name>dfs.namenode.rpc-address.ns1.nn2</name>
    <value>master1:9000</value>
  </property>
 
  <!-- 配置nn1,nn2的http通信端口 -->
  <property>
    <name>dfs.namenode.http-address.ns1.nn1</name>
    <value>master:50070</value>
  </property>
  <property>
    <name>dfs.namenode.http-address.ns1.nn2</name>
    <value>master1:50070</value>
  </property>
 
  <!-- 指定namenode元数据存储在journalnode中的路径 -->
  <property>
    <name>dfs.namenode.shared.edits.dir</name>
    <value>qjournal://master:8485;master1:8485;slave1:8485;slave2:8485;slave3:8485/ns1</value>
  </property>
  
  <!-- 指定journalnode日志文件存储的路径 -->
  <property>
    <name>dfs.journalnode.edits.dir</name>
    <value>/opt/hadoop/hadoop-2.7.5/data/journal</value>
  </property>
 
  <!-- 指定HDFS客户端连接active namenode的java类 -->
  <property>
    <name>dfs.client.failover.proxy.provider.ns1</name>
    <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
  </property>
 
  <!-- 配置隔离机制为ssh -->
  <property>
    <name>dfs.ha.fencing.methods</name>
    <value>sshfence</value>
  </property>
 
  <!-- 指定秘钥的位置 -->
  <property>
    <name>dfs.ha.fencing.ssh.private-key-files</name>
    <value>/root/.ssh/id_rsa</value>
  </property>
  
  <!-- 开启自动故障转移 -->
  <property>
    <name>dfs.ha.automatic-failover.enabled</name>
    <value>true</value>
  </property>
</configuration>


配置mapred-site.xml

<configuration>
<property>
    <name>mapreduce.framework.name</name>
    <value>yarn</value>
</property>

<!-- 指定jobhistory server的rpc地址 -->
  <property>
    <name>mapreduce.jobhistory.address</name>
    <value>master:10020</value>
  </property>

<!-- 指定jobhistory server的http地址 -->
  <property>
    <name>mapreduce.jobhistory.webapp.address</name>
    <value>master:19888</value>
  </property>

<!-- 开启uber模式(针对小作业的优化) -->
  <property>
    <name>mapreduce.job.ubertask.enable</name>
    <value>true</value>
  </property>

<!-- 配置启动uber模式的最大map数 -->
  <property>
    <name>mapreduce.job.ubertask.maxmaps</name>
    <value>9</value>
  </property>
 
  <!-- 配置启动uber模式的最大reduce数 -->
  <property>
    <name>mapreduce.job.ubertask.maxreduces</name>
    <value>3</value>
  </property>
</configuration>


配置yarn-site.xm

<configuration>

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

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

  <!-- 使用了2个resourcemanager,分别指定Resourcemanager的地址 -->
  <property>
    <name>yarn.resourcemanager.ha.rm-ids</name>
    <value>rm1,rm2</value>
  </property>

  <!-- 指定rm1的地址 -->
  <property>
    <name>yarn.resourcemanager.hostname.rm1</name>
    <value>master</value>
  </property>

  <!-- 指定rm2的地址  -->
  <property>
    <name>yarn.resourcemanager.hostname.rm2</name>
    <value>master1</value>
  </property>

  <!-- 指定当前机器master作为rm1 
  <property>
    <name>yarn.resourcemanager.ha.id</name>
    <value>rm1</value>
  </property>
  -->
<!-- 配置YARN的http端口 -->
  <property>
    <name>yarn.resourcemanager.webapp.address.rm1</name>
    <value>master:8088</value>
  </property>	
  <property>
    <name>yarn.resourcemanager.webapp.address.rm2</name>
    <value>master1:8088</value>
  </property>


  <!-- 指定zookeeper集群机器 -->
  <property>
    <name>yarn.resourcemanager.zk-address</name>
    <value>master:2181,master1:2181,slave1:2181,slave2:2181,slave3:2181</value>
  </property>

  <!-- NodeManager上运行的附属服务,需配置成mapreduce_shuffle才可运行MapReduce程序 -->
  <property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
  </property>

  <!-- 配置Web Application Proxy安全代理(防止yarn被攻击) -->
  <property>
    <name>yarn.web-proxy.address</name>
    <value>master1:8888</value>
  </property>

<!-- 开启yarn resourcemanager restart -->
  <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 nodemanager restart -->
  <property>
    <name>yarn.nodemanager.recovery.enabled</name>
    <value>true</value>
  </property>
 
  <!-- 配置nodemanager IPC的通信端口 -->
  <property>
    <name>yarn.nodemanager.address</name>
    <value>0.0.0.0:45454</value>
  </property>



<!-- 启用自动故障转移 -->
  <property>
    <name>yarn.resourcemanager.ha.automatic-failover.enabled</name>
    <value>true</value>
  </property>
</configuration>

配置完成后将hadoop安装包scp到集群其他节点的相应目录

安装psmisc

因为centos采取的是最小化安装,因此没有fuser命令,而配置的fence方法需要用到fuser,因此在两个namenode节点上需要手动安装。(如果不安装,就会出现同时存在两个standby等不能正常进行主备切换的现象)

如果没有fuser命令,再主备切换时会失败。standby节点的zkfc日志会报如下错误:

2020-11-04 07:45:49,556 INFO org.apache.hadoop.ha.SshFenceByTcpPort: Looking for process running on port 9000
2020-11-04 07:45:49,962 WARN org.apache.hadoop.ha.SshFenceByTcpPort: PATH=$PATH:/sbin:/usr/sbin fuser -v -k -n tcp 9000 via ssh: bash: fuser: 未找到命令
2020-11-04 07:45:49,963 INFO org.apache.hadoop.ha.SshFenceByTcpPort: rc: 127
2020-11-04 07:45:49,963 INFO org.apache.hadoop.ha.SshFenceByTcpPort.jsch: Disconnecting from master port 22
2020-11-04 07:45:49,968 WARN org.apache.hadoop.ha.NodeFencer: Fencing method org.apache.hadoop.ha.SshFenceByTcpPort(null) was unsuccessful.
2020-11-04 07:45:49,968 ERROR org.apache.hadoop.ha.NodeFencer: Unable to fence service by any configured method.
2020-11-04 07:45:49,969 WARN org.apache.hadoop.ha.ActiveStandbyElector: Exception handling the winning of election
java.lang.RuntimeException: Unable to fence NameNode at master/192.168.89.128:9000
        at org.apache.hadoop.ha.ZKFailoverController.doFence(ZKFailoverController.java:538)
        at org.apache.hadoop.ha.ZKFailoverController.fenceOldActive(ZKFailoverController.java:510)
        at org.apache.hadoop.ha.ZKFailoverController.access$1100(ZKFailoverController.java:60)

启动集群


1. 启动 ZooKeeper 集群


在集群中安装 ZooKeeper 的主机上启动 ZooKeeper 服务。此集群全部安装了zookeeper,因此需要全部执行一遍以下命令。

zkServer.sh start


2. 格式化 ZooKeeper 集群


在任意的 namenode 上都可以执行,笔者选择了 master主机执行格式化命令

hdfs zkfc -formatZK


3. 启动 JournalNode 集群


在集群所有节点上执行以下命令

hadoop-daemon.sh start journalnode

//3.0版本的命令
//hdfs --daemon start journalnode


4. 格式化集群的 NameNode

在 master的主机上执行以下命令,以格式化 namenode:

hdfs namenode -format


这里很有可能会报错,尤其是之前如果格式化失败了,再次格式化的时候,需要保证之前格式化时创建的目录和文件已经删除干净。比如下面的报错:

Cannot lock storage /xxx. The directory is already locked.

这个报错就是上一次格式化失败了,但hadoop在/tmp下已经创建了一些文件,并锁住了,导致再次格式化时失败。解决办法就是删除/tmp下hadoop创建的文件。(有一些pid默认也是创建在这里,可以不删)


5. 启动刚格式化的 NameNode


刚在 master上格式化了 namenode ,故就在 master上执行

hadoop-daemon.sh start namenode

//3.0版本的命令
//hdfs --daemon start namenode


6. 同步 NameNode1 元数据到 NameNode2 上


复制你 NameNode 上的元数据目录到另一个 NameNode,也就是此处的 master 复制元数据到 master1上。在 master1上执行以下命令:

hdfs namenode -bootstrapStandby


7. 启动 NameNode2


master1主机拷贝了元数据之后,就接着启动 namenode 进程了,执行

hadoop-daemon.sh start namenode

//3.0版本的命令
//hdfs --daemon start namenode


8. 启动集群中所有的DataNode

在 master上执行

hadoop-daemons.sh start datanode

//3.0版本的命令
//hdfs --daemon start datanode


9. 在 RM1 启动 YARN

在 master 的主机上执行以下命令:

start-yarn.sh


10. 在 RM2 单独启动 YARN

虽然上一步启动了 YARN ,但是在 master1上是没有相应的 ResourceManager 进程,故需要在 master1主机上单独启动:

yarn-daemon.sh start resourcemanager


11. 启动 ZKFC

在 master和 master1 的主机上分别执行如下命令(这个进程是负责监测namenode状态进行重新选举的,因此两个namenode必须启动这个进程):

hadoop-daemon.sh start zkfc

//3.0版本的命令
//hdfs --daemon start zkfc


12. 开启历史日志服务

在 master1和 master1的主机上执行

mr-jobhistory-daemon.sh   start historyserver

至此,初次启动完成,更多情况的启动顺序可参考这篇博文

https://blog.csdn.net/u011414200/article/details/50437356

HA测试

为了能够直接在windows本地的浏览器中通过集群的节点名进行访问,需要配置hosts文件。

找到hosts文件后,添加如下内容

在浏览器中分别输入

http://master:50070



http://master1:50070

发现master是active,master1是standby。那么手动kill掉master的namenode进程,重新查看master1是否变为active。发现几秒内即变为了active。

再通过命令hadoop-daemon.sh start namenode重新启动master的namenode,发现其状态变为standby。这说明hdfs的高可用基本实现。

参考文章:

https://blog.csdn.net/carl810224/article/details/52160418#commentsedit


https://www.ibm.com/developerworks/cn/opensource/os-cn-hadoop-name-node/



版权声明:本文为ASN_forever原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。