1、集群规划
1.1、主机配置环境

172.16.0.11 node60
172.16.0.13 node89
172.16.0.8 node145

 

1.2、安装后启动的进程
hadoop高可用集群搭建_hdfs

2、修改host文件
希望三个主机之间都能够使用主机名称的方式相互访问而不是IP,我们需要在hosts中配置其他主机的host。因此我们在主机的/etc/hosts下均进行如下配置:

$ vim /etc/hosts
172.16.0.11 node60
172.16.0.13 node89
172.16.0.8 node145

将配置发送到其他主机,同时在其他主机上均如上配置。

 

$ ping node60
PING node60 (172.16.0.11) 56(84) bytes of data.
64 bytes from node60 (172.16.0.11): icmp_seq=1 ttl=64 time=0.313 ms
64 bytes from node60 (172.16.0.11): icmp_seq=2 ttl=64 time=0.275 ms

$ ping node89
PING node89 (172.16.0.13) 56(84) bytes of data.
64 bytes from instance-2nfzkw5m-1 (172.16.0.13): icmp_seq=1 ttl=64 time=0.038 ms
64 bytes from instance-2nfzkw5m-1 (172.16.0.13): icmp_seq=2 ttl=64 time=0.054 ms

$ ping node145
64 bytes from node145 (172.16.0.8): icmp_seq=1 ttl=64 time=0.288 ms
64 bytes from node145 (172.16.0.8): icmp_seq=2 ttl=64 time=0.278 ms

 

3、添加用户账号
在所有的主机下均建立一个账号admin用来运行hadoop ,并将其添加至sudoers中

#添加用户通过手动输入修改密码
$ useradd admin 
#更改用户 admin 的密码
$ passwd admin

 

设置admin用户具有root权限 修改 /etc/sudoers 文件,找到下面一行,在root下面添加一行,如下所示:

$ visudo
## Allow root to run any commands anywhere
root ALL=(ALL) ALL
admin ALL=(ALL) ALL

修改完毕 :wq! 保存退出,现在可以用admin帐号登录,然后用命令 su - ,切换用户即可获得root权限进行操作。 

4、/opt目录下创建文件夹
4.1、在root用户下创建module、software文件夹

[root@89 ~]# cd /opt/
[root@89 opt]# mkdir module
[root@89 opt]# mkdir software

 

4.2、修改module、software文件夹的所有者

[root@89 opt]# chown admin:admin module
[root@89 opt]# chown admin:admin software

 

4.3、查看module、software文件夹的所有者

[root@89 opt]# ll
drwxr-xr-x 2 admin admin 4096 Mar 8 19:25 module
drwxr-xr-x 2 admin admin 4096 Mar 8 19:25 software

 

5、安装配置jdk1.8
本机root用户已安装配置jdk,admin用户不用重新安装,直接使用即可。

如果未安装可采用如下命令安装:

$ sudo yum install -y java-1.8.0-openjdk*
$ vim /etc/profile(root用户安装) 或 vim /home/admin/.bash_profile(admin用户安装),内容如下:
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/jre/lib/rt.jar
export PATH=$PATH:$JAVA_HOME/bin

 

6、设置SSH免密钥
关于ssh免密码的设置,要求每两台主机之间设置免密码,自己的主机与自己的主机之间也要求设置免密码。 这项操作可以在admin用户下执行,执行完毕公钥在/home/admin/.ssh/id_rsa.pub。

在CentOS下会存在非root用户配置免密不能登陆的问题。

root用户按照正常操作配置SSH无密码登录服务器,一切顺利,但是到非root用户的时候,就会出现各种各样的问题,这里,就统一解决一下这些出现的问题,这里以admin用户作为例子说明。

主机node60,node89,node145都需要执行以下步骤,如果之前做过免密,后来改密码了,最好把原来的.ssh目录删掉:

$ rm -rf /home/admin/.ssh (三台都需要删掉,删掉以后在执行以下语句)
$ ssh-keygen -t rsa
$ cat /home/admin/.ssh/id_rsa.pub >> /home/admin/.ssh/authorized_keys
$ chmod 700 /home/admin/ 
$ chmod 700 /home/admin/.ssh 
$ chmod 644 /home/admin/.ssh/authorized_keys 
$ chmod 600 /home/admin/.ssh/id_rsa

如上命令在主机node60,node89,node145上执行成功,下面就来配置这三台主机的免密设置。


a、配置node60免密设置
把主机node89,node145对应的/home/admin/.ssh/id_rsa.pub内容拷贝到/home/admin/.ssh/authorized_keys(该文件在node60主机上)

b、配置node89免密设置
把主机node60,node145对应的/home/admin/.ssh/id_rsa.pub内容拷贝到/home/admin/.ssh/authorized_keys(该文件在node89主机上)

c、配置node145免密设置
把主机node60,node89对应的/home/admin/.ssh/id_rsa.pub内容拷贝到/home/admin/.ssh/authorized_keys(该文件在node145主机上)

d、验证免密是否设置成功

[admin@60 ~]$ ssh node89
Last login: Sun Mar 8 20:52:20 2020 from 172.16.0.11
[admin@89 ~]$ exit
logout
Connection to node89 closed.

[admin@60 ~]$ ssh node145
Last login: Sun Mar 8 20:52:26 2020 from 172.16.0.11
[admin@145 ~]$ exit
logout
Connection to node145 closed.

[admin@60 ~]$ ssh node60
Last login: Sun Mar 8 20:52:16 2020 from 172.16.0.11
[admin@60 ~]$ exit
logout
Connection to node60 closed.

 

到此,主机之间设置免密完成。

6、安装Zookeeper
安装详解参考:
ZooKeeper集群搭建
ZooKeeper安装与配置
CentOS7.5搭建Zookeeper集群与命令行操作

7、安装hadoop集群
7.1、下载hadoop安装包
http://archive.apache.org/dist/hadoop/core/
http://archive.apache.org/dist/hadoop/core/hadoop-2.7.6/hadoop-2.7.6.tar.gz

hadoop-2.7.6.tar.gz下载后存到/opt/software/

7.2、解压安装Hadoop
解压 hadoop-2.7.6到/opt/module/目录下

$ tar zxvf hadoop-2.7.6.tar.gz -C /opt/module/

 

7.2 配置Hadoop集群
配置文件都在/opt/module/hadoop-2.7.6/etc/hadoop/下

7.2.1 修改hadoop-env.sh, mapred-env.sh ,yarn-env.sh 的JAVA环境变量

export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk 

注:export JAVA_HOME=${JAVA_HOME} 采用变量方式,会导致 hadoop-daemons.sh start datanode 执行失败

7.2.2 修改 core-site.xml
$ vim core-site.xml

<configuration>
    <!-- 把两个NameNode的地址组装成一个集群mycluster -->
    <property>
       <name>fs.defaultFS</name>
       <value>hdfs://mycluster</value>
    </property>
    <!-- 指定hadoop运行时产生文件的存储目录 -->
    <property>
      <name>hadoop.tmp.dir</name>
      <value>/opt/module/hadoop-2.7.6/data/ha/tmp</value>
    </property>
    <!-- 指定ZKFC故障自动切换转移 -->
    <property>
         <name>ha.zookeeper.quorum</name>
         <!-- <value>node60:2181,node89:2181,node145:2181</value> -->
         <value>node145:2181</value>
    </property>
    <!--修改core-site.xml中的ipc参数,防止出现连接journalnode服务ConnectException-->
    <property>
        <name>ipc.client.connect.max.retries</name>
        <value>100</value>
        <description>Indicates the number of retries a client will make to establish a server connection.</description>
    </property>
</configuration>

 

7.2.3 修改hdfs-site.xml
$ vim hdfs-site.xml

<configuration>
    <!-- 设置dfs副本数,默认3个 -->
    <property>
    <name>dfs.replication</name>
    <value>2</value>
    </property>
    <!-- 完全分布式集群名称 -->
    <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>node60:8020</value>
    </property>
    <!-- nn2的RPC通信地址 -->
    <property>
       <name>dfs.namenode.rpc-address.mycluster.nn2</name>
       <value>node89:8020</value>
    </property>
    <!-- nn1的http通信地址 -->
    <property>
       <name>dfs.namenode.http-address.mycluster.nn1</name>
       <value>node60:50070</value>
    </property>
    <!-- nn2的http通信地址 -->
    <property>
        <name>dfs.namenode.http-address.mycluster.nn2</name>
        <value>node89:50070</value>
    </property>
    <!-- 指定NameNode元数据在JournalNode上的存放位置 -->
    <property>
        <name>dfs.namenode.shared.edits.dir</name>
        <value>qjournal://node60:8485;node89:8485;node145: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>/home/admin/.ssh/id_rsa</value>
    </property>
    <!-- 声明journalnode服务器存储目录-->
    <property>
       <name>dfs.journalnode.edits.dir</name>
       <value>/opt/module/hadoop-2.7.6/data/ha/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>
    <!-- 配置自动故障转移-->
    <property>
       <name>dfs.ha.automatic-failover.enabled</name>
       <value>true</value>
    </property> 
</configuration>

 

 

7.2.4 修改mapred-site.xml
$ mv mapred-site.xml.template mapred-site.xml
$ vim mapred-site.xml

<configuration>
  <!-- 指定mr框架为yarn方式 -->
 <property>
  <name>mapreduce.framework.name</name>
  <value>yarn</value>
 </property>
  <!-- 指定mr历史服务器主机,端口 -->
  <property>   
    <name>mapreduce.jobhistory.address</name>   
    <value>node60:10020</value>   
  </property>   
  <!-- 指定mr历史服务器WebUI主机,端口 -->
  <property>   
    <name>mapreduce.jobhistory.webapp.address</name>   
    <value>node60:19888</value>   
  </property>
    <!-- 历史服务器的WEB UI上最多显示20000个历史的作业记录信息 -->    
  <property>
    <name>mapreduce.jobhistory.joblist.cache.size</name>
    <value>20000</value>
  </property>
  <!--配置作业运行日志 --> 
  <property>
    <name>mapreduce.jobhistory.done-dir</name>
    <value>${yarn.app.mapreduce.am.staging-dir}/history/done</value>
  </property>
  <property>
    <name>mapreduce.jobhistory.intermediate-done-dir</name>
    <value>${yarn.app.mapreduce.am.staging-dir}/history/done_intermediate</value>
  </property>
  <property>
    <name>yarn.app.mapreduce.am.staging-dir</name>
    <value>/tmp/hadoop-yarn/staging</value>
  </property>
</configuration>

 

7.2.5 修改 slaves
$ vim slaves

node60
node89
node145

 

7.2.6 修改yarn-site.xml
[admin@node21 hadoop]$ vim yarn-site.xml

<configuration>
 <!-- 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>rmCluster</value>
    </property>
    <property>
        <name>yarn.resourcemanager.ha.rm-ids</name>
        <value>rm1,rm2</value>
    </property>
    <property>
        <name>yarn.resourcemanager.hostname.rm1</name>
        <value>node89</value>
    </property>
    <property>
        <name>yarn.resourcemanager.hostname.rm2</name>
        <value>node145</value>
    </property>
    <!--指定zookeeper集群的地址-->
    <property>
        <name>yarn.resourcemanager.zk-address</name>
        <value>node60:2181,node89:2181,node145: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>
</configuration>

 

 

7.2.7 拷贝hadoop到其他节点

[admin@145 module]# scp -r hadoop-2.7.6/ admin@node60:/opt/module/
[admin@145 module]# scp -r hadoop-2.7.6/ admin@node89:/opt/module/

注:记得切换成admin用户操作

7.2.8 配置Hadoop环境变量

$ sudo vim /etc/profile
末尾追加
export HADOOP_HOME=/opt/module/hadoop-2.7.6
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
编译生效 source /etc/profile

$ echo ${HADOOP_HOME}

 

8、启动集群
8.1、启动journalnode,三台机器都要执行(仅第一次启动hadoop时,需要这一步操作,之后不再需要手动启动journalnode),前提zookeeper集群已启动:

 

$ sudo mkdir -p /opt/module/hadoop-2.7.6/logs
$ sudo chown admin:admin /opt/module/hadoop-2.7.6/logs

$ ssh admin@node60 '/opt/module/hadoop-2.7.6/sbin/stop-all.sh';
$ ssh admin@node89 '/opt/module/hadoop-2.7.6/sbin/stop-all.sh';
$ ssh admin@node145 '/opt/module/hadoop-2.7.6/sbin/stop-all.sh';

$ ssh admin@node60 'rm -rf /opt/module/hadoop-2.7.6/data';
$ ssh admin@node89 'rm -rf /opt/module/hadoop-2.7.6/data';
$ ssh admin@node145 'rm -rf /opt/module/hadoop-2.7.6/data';

$ ssh admin@node60 'cd /opt/module/hadoop-2.7.6/sbin/;sh hadoop-daemon.sh start journalnode;';
$ ssh admin@node89 'cd /opt/module/hadoop-2.7.6/sbin/;sh hadoop-daemon.sh start journalnode;';
$ ssh admin@node145 'cd /opt/module/hadoop-2.7.6/sbin/;sh hadoop-daemon.sh start journalnode;';

 

 

启动Journalnde是为了创建/data/ha/jn,此时jn里面是空的

[admin@60 jn]$ cd /opt/module/hadoop-2.7.6/data/ha/jn
[admin@60 jn]$ ll
total 0

 

查看journalnode服务日志

$ tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/hadoop-admin-journalnode-145.out
$ tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/hadoop-admin-journalnode-145.log


注:hadoop-daemon.sh stop journalnode 关闭JournalNode节点

8.2、在[nn1]上,对namenode进行格式化,并启动:

[admin@node60 ~]$ cd /opt/module/hadoop-2.7.6/bin
[admin@node60 ~]$ hdfs namenode -format

hadoop高可用集群搭建_apache_02

格式化namenode,此时jn里面会产生集群ID等信息
hadoop高可用集群搭建_hdfs_03
注:图片盗用别人的,node21对用我主机的node60

另外,/data/ha/tmp也会产生如下信息
hadoop高可用集群搭建_java_04
注:图片盗用别人的,node21对用我主机的node60

启动nn1上namenode

[admin@60 sbin]$ hadoop-daemon.sh start namenode
starting namenode, logging to /opt/module/hadoop-2.7.6/logs/hadoop-admin-namenode-node21.out

[admin@60 sbin]$ tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/hadoop-admin-namenode-60.out
[admin@60 sbin]$ tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/hadoop-admin-namenode-60.log

 

8.3、在[nn2]上,同步nn1的元数据信息:

[admin@89 bin]$ cd /opt/module/hadoop-2.7.6/bin
[admin@89 ~]$ hdfs namenode -bootstrapStandby

hadoop高可用集群搭建_hdfs_05

8.4、启动[nn2]:

[admin@89 sbin]$ hadoop-daemon.sh start namenode

 

8.5、在[nn1]上,启动所有datanode

[admin@60 sbin]$ hadoop-daemons.sh start datanode

 

8.6、查看web页面此时显示

http://182.*.*.60:50070

hadoop高可用集群搭建_apache_06

 

http://106.*.*.89:50070

 hadoop高可用集群搭建_zookeeper_07

 

8.7、手动切换状态,在各个NameNode节点上启动DFSZK Failover Controller,先在哪台机器启动,哪个机器的NameNode就是Active NameNode

[admin@60 ~]$ hadoop-daemon.sh start zkfc
[admin@89 ~]$ hadoop-daemon.sh start zkfc

 

或者强制手动其中一个节点变为Active

[admin@60 data]$ hdfs haadmin -transitionToActive nn1 --forcemanual

 

Web页面查看

Overview 'node60:8020' (active)

Overview 'node89:8020' (standby)

 

8.8、自动切换状态,需要初始化HA在Zookeeper中状态,先停掉hdfs服务,然后随便找一台zookeeper的安装节点

[admin@60 current]$ hdfs zkfc -formatZK

hadoop高可用集群搭建_hdfs_08

查看,此时会产生一个hadoop-ha的目录

[admin@145 ~]# cd /opt/module/zookeeper-3.4.6/bin
[admin@145 bin]$ ./zkCli.sh
[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper, hadoop-ha]
[zk: localhost:2181(CONNECTED) 1]

 

启动hdfs服务,查看namenode状态

[admin@60 ~]$ ./start-dfs.sh

 

8.9、测试namenode高可用
8.9.1、在node60上kill掉namenode进程,然后通过浏览器查看node89的状态,发现状态变为active,说明高可用测试成功

[admin@60 sbin]$ jps
20441 NameNode
24523 Jps
20172 JournalNode
24430 DFSZKFailoverController
21278 DataNode
[admin@60 sbin]$ kill -9 20441

 

8.9.2、重新启动node60的namenode进程,sh start-dfs.sh,浏览器访问node60,此时node60的状态为standby

[admin@60 sbin]$ hadoop-daemon.sh start journalnode
[admin@60 sbin]$ sh start-dfs.sh

 

至此,hadoop高可用集群搭建完毕。

9、启动yarn
9.1、在node89中执行:

[admin@89 ~]$ cd /opt/module/hadoop-2.7.6/sbin
[admin@89 ~]$ start-yarn.sh

 

9.2、在node145中执行:

[admin@89 ~]$ cd /opt/module/hadoop-2.7.6/sbin
[admin@145 ~]$ yarn-daemon.sh start resourcemanager

 

9.3、查看服务状态

[admin@145 sbin]$ yarn rmadmin -getServiceState rm1
standby
[admin@145 sbin]$ yarn rmadmin -getServiceState rm2
active
[admin@145 sbin]$

  

10、查看启动journalnode日志

ssh admin@node60 'tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/hadoop-admin-journalnode-60.log';
ssh admin@node89 'tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/hadoop-admin-journalnode-89.log';
ssh admin@node145 'tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/hadoop-admin-journalnode-145.log';

ssh admin@node60 'tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/hadoop-admin-namenode-60.log';
ssh admin@node89 'tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/hadoop-admin-namenode-89.log';
ssh admin@node60 'tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/hadoop-admin-zkfc-60.log';
ssh admin@node89 'tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/hadoop-admin-zkfc-89.log';

ssh admin@node60 'tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/yarn-admin-nodemanager-60.log';
ssh admin@node89 'tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/yarn-admin-nodemanager-89.log';
ssh admin@node89 'tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/yarn-admin-resourcemanager-89.log';
ssh admin@node145 'tail -f -n 1000 /opt/module/hadoop-2.7.6/logs/yarn-admin-nodemanager-145.log';

 

 

配置集群常见错误

1、执行yum提示错误:rpmdb: BDB0113 Thread/process 424227/139826856310848 failed
解决方案:https://blog.csdn.net/qq_41688455/article/details/86690143

2、hadoop-daemon.sh start journalnode启动失败
2020-03-09 14:20:03,099 INFO org.apache.hadoop.hdfs.qjournal.server.JournalNode: registered UNIX signal handlers for [TERM, HUP, INT]
2020-03-09 14:20:03,303 ERROR org.apache.hadoop.hdfs.qjournal.server.JournalNode: Failed to start journalnode.
org.apache.hadoop.util.DiskChecker$DiskErrorException: Cannot create directory: /opt/module/hadoop-2.7.6/data/ha/jn
at org.apache.hadoop.util.DiskChecker.checkDir(DiskChecker.java:106)
at org.apache.hadoop.hdfs.qjournal.server.JournalNode.validateAndCreateJournalDir(JournalNode.java:118)
at org.apache.hadoop.hdfs.qjournal.server.JournalNode.start(JournalNode.java:138)
at org.apache.hadoop.hdfs.qjournal.server.JournalNode.run(JournalNode.java:128)
at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70)
at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:84)
at org.apache.hadoop.hdfs.qjournal.server.JournalNode.main(JournalNode.java:299)
2020-03-09 14:20:03,309 INFO org.apache.hadoop.util.ExitUtil: Exiting with status -1
2020-03-09 14:20:03,311 INFO org.apache.hadoop.hdfs.qjournal.server.JournalNode: SHUTDOWN_MSG:

解决方案:
$ sudo chown admin:admin hadoop-2.7.6/

 

3、2020-03-13 17:15:20,059 WARN org.apache.hadoop.hdfs.server.common.Storage: Failed to add storage directory [DISK]file:/opt/module/hadoop-2.7.6/data/ha/tmp/dfs/data/
java.io.IOException: Incompatible clusterIDs in /opt/module/hadoop-2.7.6/data/ha/tmp/dfs/data: namenode clusterID = CID-1e9a7844-9d48-4d66-be81-5ee83e19a482; datanode clusterID = CID-0599cb61-c91b-453f-9821-fa32956b55c0

由于多次格式化命令所致(/opt/module/hadoop-2.7.6/bin/hdfs namenode -format)

解决方法:
停止Hadoop服务,删除/opt/module/hadoop-2.7.6/data下的所有文件,然后重新格式化,再启动就好了.

ssh admin@node60 'rm -rf /opt/module/hadoop-2.7.6/data';
ssh admin@node89 'rm -rf /opt/module/hadoop-2.7.6/data';
ssh admin@node145 'rm -rf /opt/module/hadoop-2.7.6/data';

 


参考文章:
CentOS7.5搭建Hadoop2.7.6完全分布式集群
hadoop高可用集群搭建