一、部署前准备
写在前头:搭建hadoop+hbase需要考虑版本兼容情况,这个去官网上看,本文选用的是hadoop-3.1.1和hbase-2.1.1版本(官网是“not test”,最终搭建成功),jdk选用的1.8(开始选用的1.6,安装有问题)。
集群环境的搭建,有几个是必要的:ssh免密钥,服务器时钟同步。
hadoop的搭建还需要升级glibc的版本,2.12的版本会导致命令不可用,需升级至2.14版本。
- 准备三台服务器及软件包
所需软件包版本:
jdk-8u181-linux-x64.tar.gz
glibc-2.14.tar.gz
zookeeper-3.4.13.tar.gz
hadoop-3.1.1.tar.gz
hbase-2.1.1-bin.tar.gz
ip分别为:192.168.120.60
192.168.120.62
192.168.120.63
配置网络(3台):
[root@node1 ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE=Ethernet
ONBOOT=yes
NM_CONTROLLED=yes
BOOTPROTO=none
IPADDR=192.168.120.60
NETMASK=255.255.255.0
GATEWAY=192.168.120.254
DNS1=218.2.135.1
DEFROUTE=yes
[root@node1 ~]# service network restart
-
关闭防火墙和selinux安全协议(3台)
[root@hadoop-master ~]# service iptables stop
[root@hadoop-master ~]# chkconfig iptables off
[root@hadoop-master ~]# vi /etc/sysconfig/selinux
将SELINUX=enforcing 改为 SELINUX=disabled
[root@hadoop-master ~]# setenforce 0 -
修改hosts文件(3台)
我们希望三个主机之间都能够使用主机名称的方式相互访问而不是IP,我们需要在hosts中配置其他主机的host。因此我们在主机的/etc/hosts下均进行如下配置(追加):
[root@hadoop-master ~]# vi /etc/hosts
192.168.120.60 node1
192.168.120.62 node2
192.168.120.63 node3
测试:
[root@hadoop-master ~]# ping node1
[root@hadoop-master ~]# ping node2
[root@hadoop-master ~]# ping node3
- 修改hostname(3台)
#node1
[root@hadoop-master ~]# vi /etc/hosts
NETWORKING=yes
HOSTNAME=node1
[root@hadoop-master ~]# service network restart
[root@hadoop-master ~]# hostname node1
#node2
[root@hadoop-slave1 ~]# vi /etc/hosts
NETWORKING=yes
HOSTNAME=node2
[root@hadoop-slave1 ~]# service network restart
[root@hadoop-slave1 ~]# hostname node2
#node3
[root@hadoop-slave2 ~]# vi /etc/hosts
NETWORKING=yes
HOSTNAME=node3
[root@hadoop-slave2 ~]# service network restart
[root@hadoop-slave2 ~]# hostname node3
- 添加hadoop用户及组(3台)
在所有的主机下均建立一个账号hadoop用来运行hadoop ,并将其添加至sudoers中。
[root@node1 ~]# useradd hadoop
[root@node1 ~]# passwd hadoop
[root@node1 ~]# usermod -a -G hadoop hadoop
设置hadoop用户具有root权限 修改 /etc/sudoers 文件,找到下面一行,在root下面添加一行,如下所示:
[root@node1 ~]# vi /etc/sudoers
## Allow root to run any commands anywhere
root ALL=(ALL) ALL
hadoop ALL=(ALL) ALL
修改完毕 :wq! 保存退出,现在可以用hadoop帐号登录,然后用命令 su - ,切换用户即可获得root权限进行操作。
-
创建文件夹及赋权
1)在root用户下创建module、software文件夹
[root@node1 ~]# mkdir /opt/module
[root@node1 ~]# mkdir /opt/software
2)修改module、software文件夹的所有者
[root@node1 ~]# chown hadoop:hadoop /opt/module
[root@node1 ~]# chown hadoop:hadoop /opt/software
3)查看module、software文件夹的所有者
[root@node1 ~]# ll /opt/
drwxr-xr-x. 2 hadoop hadoop 4096 Oct 9 15:37 module
drwxr-xr-x. 2 hadoop hadoop 4096 Oct 9 15:38 software -
安装配置jdk1.8
hadoop2.6版本及以前适用jdk1.6,之后的版本必须要jdk1.8。
#查询是否安装java软件
[root@node1 ~]# rpm -qa | grep java
#如果jdk版本低于1.8,卸载之(没安装则不需此操作)
[root@node1 ~]# rpm -e –nodeps 软件包名
1)上传jdk1.8到 /opt/software下,解压并配置java环境变量
[root@node1 ~]# cd /opt/software
[root@node1 software]# tar -xzvf jdk-8u181-linux-x64.tar.gz -C /opt/module/
[root@node1 software]# cd …/module/
[root@node1 module]# mv jdk1.8.0_181/ jdk1.8
[root@node1 module]# vi /etc/profile
加入如下内容:
export JAVA_HOME=/opt/module/jdk1.8
export PATH=
P
A
T
H
:
PATH:
PATH:JAVA_HOME/bin:$JAVA_HOME/sbin
[root@node1 module]# source /etc/profile
[root@node1 module]# java -version
java version “1.8.0_181”
Java™ SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot™ 64-Bit Server VM (build 25.181-b13, mixed mode)
2)向另外2个节点复制jdk
[root@node1 module]# scp -r /opt/module/jdk1.8 root@node2:pwd
[root@node1 module]# scp -r /opt/module/jdk1.8 root@node3:pwd
3)在node2、node3节点上修改文件夹属主
[root@node2 ~]# chown hadoop:hadoop /opt/module/
[root@node3 ~]# chown hadoop:hadoop /opt/module/
4)在node2、node3上都重新编译一下/etc/profile
[root@node2 ~]# vi /etc/profile
[root@node3 ~]# vi /etc/profile
加入如下内容:
export JAVA_HOME=/opt/module/jdk1.8
export PATH=
P
A
T
H
:
PATH:
PATH:JAVA_HOME/bin:$JAVA_HOME/sbin
[root@node2 ~]# source /etc/profile
[root@node3 ~]# source /etc/profile
测试 java -version
8. 升级glibc至2.14(3台,如已是2.14则不需此步骤)
glibc系统默认安装2.12,如果低于2.14,hadoop安装完成后,hdfs命令启动会报错。
首先查看glibc版本
[root@node1 build]# ll /lib64/libc.so.6
lrwxrwxrwx 1 root root 12 Oct 16 13:56 /lib64/libc.so.6 -> libc-2.12.so
#将glibc-2.14.tar.gz上传至服务器并开始安装
[root@node1 ~]# cd /opt/software/
[root@node1 software]# tar -xzvf glibc-2.14.tar.gz -C /home/
[root@node1 software]# cd /home/glibc-2.14/
[root@node1 glibc-2.14]# mkdir build
[root@node1 glibc-2.14]# cd build
#以下yum命令可忽略,但如果缺少gcc套件,configure命令可能执行报错
[root@node1 build]# yum install gcc
[root@node1 build]# …/configure --prefix=/usr/local/glibc-2.14
[root@node1 build]# make
[root@node1 build]# make install
[root@node1 build]# find / -name “ld.so.conf”
[root@node1 build]# cp /etc/ld.so.conf /usr/local/glibc-2.14/etc/
[root@node1 build]# make install
[root@node1 build]# vi /etc/sysconfig/i18n
#添加如下
LC_ALL=C
export LC_ALL
[root@node1 build]# source /etc/sysconfig/i18n
##[root@node1 build]# make localedata/install-locales
#[root@node1 build]# vi /etc/profile
#加入此变量
#export LD_LIBRARY_PATH=/usr/local/glibc-2.14/lib
#[root@node1 build]# source /etc/profile
[root@node1 build]# ln -snf /usr/local/glibc-2.14/lib/libc-2.14.so /lib64/libc.so.6
#查看升级是否成功
[root@node1 build]# ll /lib64/libc.so.6
lrwxrwxrwx 1 root root 32 Oct 16 05:26 /lib64/libc.so.6 -> /opt/glibc-2.14/lib/libc-2.14.so
#升级libc.so.6会导致时区设置失效
[root@node1 build]# date
Mon Dec 3 11:05:44 Local time zone must be set–see zic manual page 2018
#时区失效需执行以下操作
[root@node1 build]# ln -sf /etc/localtime /usr/local/glibc-2.14/etc/localtime
#接着,在node2、node3上重复上述步骤
9. 设置ssh免密钥登录(3台)
关于ssh免密码的设置,要求每两台主机之间设置免密码,自己的主机与自己的主机之间也要求设置免密码。 这项操作在hadoop用户下执行,执行完毕公钥在/home/hadoop/.ssh/id_rsa.pub
1)在node1节点设置
[root@node1 build]# su - hadoop
[hadoop@node1 ~]$ ssh-keygen -t rsa
一路回车到底
#第一次ssh要输入密码,以后不用
[hadoop@node1 ~]$ ssh-copy-id node1
[hadoop@node1 ~]$ ssh-copy-id node2
[hadoop@node1 ~]$ ssh-copy-id node3
2)在node2节点设置
#node1与node2为namenode节点要相互免秘钥(HDFS的HA)
[root@node2 ~]# su - hadoop
[hadoop@node2 ~]$ ssh-keygen -t rsa
[hadoop@node2 ~]$ ssh-copy-id node2
[hadoop@node2 ~]$ ssh-copy-id node1
[hadoop@node2 ~]$ ssh-copy-id node3
3)在node3节点设置
#node2与node3为yarn节点要相互免秘钥(YARN的HA)
[root@node3 ~]# su - hadoop
[hadoop@node3 ~]$ ssh-keygen -t rsa
[hadoop@node3 ~]$ ssh-copy-id node3
[hadoop@node3 ~]$ ssh-copy-id node1
[hadoop@node3 ~]$ ssh-copy-id node2
10.时钟同步
#集群需要服务器之间时钟同步
[root@node1 ~]# rpm -qa | grep ntp
#为空表示没有安装ntp
[root@node1 ~]# yum install ntp
[root@node1 ~]# chkconfig ntpd on
[root@node1 ~]# vi /etc/ntp.conf
#添加如下
restrict 192.168.120.0 mask 255.255.255.0 nomodify notrap
server 127.127.1.0 # local clock
server 210.72.145.44 perfer
server 202.112.10.36 # 1.cn.pool.ntp.org
server 59.124.196.83 # 0.asia.pool.ntp.org
#注释掉默认几项,如下
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
[root@node1 ~]# /etc/init.d/ntpd restart
Shutting down ntpd: [FAILED]
Starting ntpd: [ OK ]
[root@node1 ~]# ntpstat
synchronised to local net at stratum 6
time correct to within 7948 ms
polling server every 64 s
#如此表示配置成功
#接下来在node2、node3上安装ntp并同步时钟
#还需加入计划任务(每天凌晨3点)同步,以防一段时间后,时间可能又不再同步
# node2
[root@node2 ~]# yum install ntp
[root@node2 ~]# chkconfig ntpd on
[root@node2 ~]# ntpdate -u 192.168.120.60
[root@node2 ~]# /etc/init.d/ntpd restart
[root@node2 ~]# crontab -e
0 3 * * * /usr/sbin/ntpdate 192.168.120.60
# node3
[root@node3 ~]# yum install ntp
[root@node3 ~]# chkconfig ntpd on
[root@node3 ~]# ntpdate -u 192.168.120.60
[root@node3 ~]# /etc/init.d/ntpd restart
[root@node3 ~]# crontab -e
0 3 * * * /usr/sbin/ntpdate 192.168.120.60
二、安装hadoop集群(完全分布式HA)
-
集群规划
节点名称 NN JJN DN ZKFC ZK RM NM
node1 NameNode JournalNode DataNode ZKFC Zookeeper NodeManager
node2 NameNode JournalNode DataNode ZKFC ZooKeeper ResourceManager NodeManager
node3 JournalNode DataNode ZooKeeper ResourceManager NodeManager -
安装Zookeeper集群
在node1、node2和node3三个节点上部署Zookeeper,三个节点都已安装jdk。
将zookeeper-3.4.13.tar.gz上传至/opt/software/目录下。
1)解压Zookeeper安装包到/opt/module/目录下
[hadoop@node1 ~]$ cd /opt/software/
[hadoop@node1 software]$ tar -xzvf zookeeper-3.4.13.tar.gz -C /opt/module/
2)在/opt/module/zookeeper-3.4.12/这个目录下创建Data
[hadoop@node1 software]$ cd …/module/zookeeper-3.4.13/
[hadoop@node1 zookeeper-3.4.13]$ mkdir Data
3)重命名/opt/module/zookeeper-3.4.13/conf这个目录下的zoo_sample.cfg
[hadoop@node1 zookeeper-3.4.13]$ cd conf/
[hadoop@node1 conf]$ mv zoo_sample.cfg zoo.cfg
4)配置zoo.cfg文件
[hadoop@node1 conf]$ vi zoo.cfg
修改dataDir,添加日志存放目录
dataDir=/opt/module/zookeeper-3.4.13/Data
dataLogDir=/opt/module/zookeeper-3.4.13/logs
末尾增加如下配置
server.1=node1:2888:3888
server.2=node2:2888:3888
server.3=node3:2888:3888
5)集群配置
a. 在/opt/module/zookeeper-3.4.13/Data目录下创建一个myid的文件, 在文件中添加与server对应的编号:如 1
[hadoop@node1 conf]$ cd …/Data/
[hadoop@node1 Data]$ vi myid
b. 拷贝配置好的zookeeper到其他机器上
[hadoop@node1 Data]$ scp -r /opt/module/zookeeper-3.4.13/ hadoop@node2:/opt/module/
[hadoop@node1 Data]$ scp -r /opt/module/zookeeper-3.4.13/ hadoop@node3:/opt/module/
c. 分别修改node2,node3中myid文件中内容为2、3
#node2
[hadoop@node2 ~]$ cd /opt/module/zookeeper-3.4.13/Data/
[hadoop@node2 Data]$ echo 2 > myid
#node3
[hadoop@node3 ~]$ cd /opt/module/zookeeper-3.4.13/Data/
[hadoop@node3 Data]$ echo 3 > myid
6)配置环境变量(3台)
[hadoop@node1 ~]$ sudo vi /etc/profile
将文件中的环境变量修改为:
export JAVA_HOME=/opt/module/jdk1.8
export ZOOKEEPER_HOME=/opt/module/zookeeper-3.4.13
export PATH=
P
A
T
H
:
PATH:
PATH:JAVA_HOME/bin:
J
A
V
A
H
O
M
E
/
s
b
i
n
:
JAVA_HOME/sbin:
JAVAHOME/sbin:ZOOKEEPER_HOME/bin
[hadoop@node1 ~]$ source /etc/profile
7)将zookeeper做成服务并加入开机启动项(3台)
[hadoop@node1 ~]$ cd /etc/rc.d/init.d/
[hadoop @node1 init.d]# sudo vi zookeeper
#!/bin/bash
#chkconfig:2345 20 90
#description:zookeeper
#processname:zookeeper
export JAVA_HOME=/opt/module/jdk1.8
case $1 in
start) su - root /opt/module/zookeeper-3.4.13/bin/zkServer.sh start;;
stop) su - root /opt/module/zookeeper-3.4.13/bin/zkServer.sh stop;;
status) su - root /opt/module/zookeeper-3.4.13/bin/zkServer.sh status;;
restart) su - root /opt/module/zookeeper-3.4.13/bin/zkServer.sh restart;;
*) echo “require start|stop|status|restart” ;;
esac
[hadoop @node1 init.d]# sudo chmod 755 zookeeper
[hadoop @node1 init.d]# sudo chkconfig --add zookeeper
8)启动集群
a.分别启动三台节点上的Zookeeper
#node1
[hadoop@node1 ~]$ sudo service zookeeper start
#node2
[hadoop@node2 ~]$ sudo service zookeeper start
#node3
[hadoop@node3 ~]$ sudo service zookeeper start
b. 查看各节点状态
zoo.cfg配置参数解读
Server.A=B:C:D。
A是一个数字,表示这个是第几号服务器;
B是这个服务器的ip地址;
C是这个服务器与集群中的Leader服务器交换信息的端口;
D是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
集群模式下配置一个文件myid,这个文件在dataDir目录下,这个文件里面有一个数据就是A的值,Zookeeper启动时读取此文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server。
①tickTime=2000:通信心跳数,Zookeeper服务器心跳时间,单位毫秒
Zookeeper使用的基本时间,服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个tickTime时间就会发送一个心跳,时间单位为毫秒。
它用于心跳机制,并且设置最小的session超时时间为两倍心跳时间。(session的最小超时时间是2*tickTime)
②initLimit=10:LF初始通信时限
集群中的follower跟随者服务器(F)与leader领导者服务器(L)之间初始连接时能容忍的最多心跳数(tickTime的数量),用它来限定集群中的Zookeeper服务器连接到Leader的时限。
投票选举新leader的初始化时间
Follower在启动过程中,会从Leader同步所有最新数据,然后确定自己能够对外服务的起始状态。
Leader允许F在initLimit时间内完成这个工作。
③syncLimit=5:LF同步通信时限
集群中Leader与Follower之间的最大响应时间单位,假如响应超过syncLimit * tickTime,Leader认为Follwer死掉,从服务器列表中删除Follwer。
在运行过程中,Leader负责与ZK集群中所有机器进行通信,例如通过一些心跳检测机制,来检测机器的存活状态。
如果L发出心跳包在syncLimit之后,还没有从F那收到响应,那么就认为这个F已经不在线了。
④dataDir:数据文件目录+数据持久化路径
保存内存数据库快照信息的位置,如果没有其他说明,更新的事务日志也保存到数据库。
⑤clientPort=2181:客户端连接端口
- 安装配置Hadoop集群
3.1解压安装Hadoop
下载Hadoop最新的tar.gz包(src.tar.gz是源码包),确认版本是32位还是64位:
[hadoop@node1 ~]$ tar -xzvf /opt/software/hadoop-3.1.1.tar.gz -C /opt/module/
[hadoop@node1 ~]$ file /opt/module/hadoop-3.1.1/lib/native/libhadoop.so.1.0.0
/opt/module/hadoop-3.1.1/lib/native/libhadoop.so.1.0.0: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, not stripped
3.2 配置Hadoop集群
配置文件都在/opt/module/hadoop-3.1.1/etc/hadoop/下
3.2.1 修改hadoop-env.sh,mapred-env.sh,yarn-env.sh 的JAVA环境变量
[hadoop@node1 ~]$ cd /opt/module/hadoop-3.1.1/etc/hadoop/
[hadoop@node1 hadoop]$ vi hadoop-env.sh
export JAVA_HOME=/opt/module/jdk1.8
[hadoop@node1 hadoop]$ vi mapred-env.sh
export JAVA_HOME=/opt/module/jdk1.8
[hadoop@node1 hadoop]$ vi yarn-env.sh
export JAVA_HOME=/opt/module/jdk1.8
3.2.2 修改core-site.xml
[hadoop@node1 hadoop]$ vi 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-3.1.1/data/ha/tmp</value>
</property>
<!-- 指定ZKFC故障自动切换转移 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>node1:2181,node2:2181,node3:2181</value>
</property>
</configuration>
3.2.3 修改hdfs-site.xml
[hadoop@node1 hadoop]$ vi 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>node1:8020</value>
</property>
<!-- nn2的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>node2:8020</value>
</property>
<!-- nn1的http通信地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>node1:50070</value>
</property>
<!-- nn2的http通信地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>node2:50070</value>
</property>
<!-- 指定NameNode元数据在JournalNode上的存放位置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://node1:8485;node2:8485;node3: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/hadoop/.ssh/id_rsa</value>
</property>
<!-- 声明journalnode服务器存储目录-->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/opt/module/hadoop-3.1.1/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>
<!— NN写JN时间,默认20s-->
<property>
<name>dfs.qjournal.write-txns.timeout.ms</name>
<value>60000</value>
</property>
</configuration>
3.2.4 修改mapred-site.xml
[hadoop@node1 hadoop]$ vi mapred-site.xml
<configuration>
<!-- 指定mr框架为yarn方式 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!-- 指定mr历史服务器主机,端口 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>node1:10020</value>
</property>
<!-- 指定mr历史服务器WebUI主机,端口 -->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>node1: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>
3.2.5 修改workers
[hadoop@node1 hadoop]$ vi workers
node1
node2
node3
3.2.6 修改yarn-site.xml
[hadoop@node1 hadoop]$ vi 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>node2</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>node3</value>
</property>
<!--指定zookeeper集群的地址-->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>node1:2181,node2:2181,node3: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>
3.3 拷贝hadoop到其他节点
[hadoop@node1 ~]$ scp -r /opt/module/hadoop-3.1.1/ hadoop@node2:/opt/module/
[hadoop@node1 ~]$ scp -r /opt/module/hadoop-3.1.1/ hadoop@node3:/opt/module/
3.4 配置hadoop环境变量(3台)
[hadoop@node1 ~]$ sudo vi /etc/profile
将文件中的环境变量修改为:
export JAVA_HOME=/opt/module/jdk1.8
export ZOOKEEPER_HOME=/opt/module/zookeeper-3.4.13
export HADOOP_HOME=/opt/module/hadoop-3.1.1
export PATH=
P
A
T
H
:
PATH:
PATH:JAVA_HOME/bin:
J
A
V
A
H
O
M
E
/
s
b
i
n
:
JAVA_HOME/sbin:
JAVAHOME/sbin:ZOOKEEPER_HOME/bin::
H
A
D
O
O
P
H
O
M
E
/
b
i
n
:
HADOOP_HOME/bin:
HADOOPHOME/bin:HADOOP_HOME/sbin
[hadoop@node1 ~]$ source /etc/profile
3.5 启动hadoop集群
3.5.1 初始化zkfc
[hadoop@node1 ~]$ hdfs zkfc -formatZK
3.5.2 启动journalnode服务(3台)
在各个JournalNode节点上,输入以下命令启动journalnode服务(前提zookeeper集群已启动)。
#node1
[hadoop@node1 ~]$ hdfs --daemon start journalnode
WARNING: /opt/module/hadoop-3.1.1/logs does not exist. Creating.
命令成功会生成2个目录:
/opt/module/hadoop-3.1.1/data/ha/jn
/opt/module/hadoop-3.1.1/logs
#node2
[hadoop@node2 ~]$ hdfs --daemon start journalnode
#node3
[hadoop@node3 ~]$ hdfs --daemon start journalnode
3.5.3 格式化namenode并启动(node1、node2)
1)在nn1上,对namenode进行格式化
[hadoop@node1 ~]$ hdfs namenode -format
格式化namenode,此时jn里面会产生集群ID等信息
[hadoop@node1 ~]$ cd /opt/module/hadoop-3.1.1/data/ha/jn/mycluster/current/
[hadoop@node1 current]$ cat VERSION
另外,/opt/module/hadoop-3.1.1/data/ha/tmp也会产生如下信息
[hadoop@node1 current]$ cd …/…/…/tmp/
2)启动nn1上namenode
[hadoop@node1 current]$ hdfs --daemon start namenode
3)在nn2上,同步nn1的元数据信息
[hadoop@node2 ~]$ hdfs namenode -bootstrapStandby
4)启动nn2
[hadoop@node2 ~]$ hdfs --daemon start namenode
3.5.4 启动datanode(nn1上启动即可)
[hadoop@node1 ~]$ hdfs --daemon start datanode
[hadoop@node1 ~]$ jps
6691 DFSZKFailoverController
6149 NameNode
6486 JournalNode
7031 NodeManager
7229 Jps
6254 DataNode
查看web页面http://192.168.120.60:50070/, 此时显示
查看web页面http://192.168.120.62:50070/, 此时显示
至此,hadoop安装验证完毕!
三、hadoop集群开机启动
#将集群启动命令加入开机自启动文件
#只需在node1上配置即可启动所有节点
#然而有时重启后会发生node2、node3的DataNode无法启动,还是需要手动启DN
[hadoop@node1 ~]$ sudo vi /etc/rc.local
su - hadoop -c “start-all.sh start”
四、Hadoop搭建问题总结
- hadoop命令报错(glibc版本问题)
[hadoop@node1 ~]$ hadoop fs -ls /
2018-10-16 11:04:36,139 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform… using builtin-java classes where applicable
2018-10-16 11:04:38,473 INFO retry.RetryInvocationHandler: org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.ipc.StandbyException): Operation category READ is not supported in state standby. Visit https://s.apache.org/sbnn-error
[hadoop@node1 ~]$ cd /opt/module/hadoop-3.1.1/etc/hadoop
[hadoop@node1 hadoop]$ vi log4j.properties
#加入打印调试信息选项
log4j.logger.org.apache.hadoop.util.NativeCodeLoader=DEBUG
加入调试信息后,看到日志输出如下错误:
[root@node1 build]# ll /lib64/libc.so.6
lrwxrwxrwx 1 root root 32 Oct 16 05:26 /lib64/libc.so.6 -> /opt/glibc-2.12/lib/libc-2.14.so
libhadoop.so需要的glibc版本是glibc_2.14
- DataNode无法启动
集群的DataNode无法启动,查看node2上的日志
[hadoop@node2 ~]$ cd /opt/module/hadoop-3.1.1/logs
[hadoop@node2 logs]$ tail -200 hadoop-hadoop-namenode-node2.log
2018-10-22 11:37:28,801 WARN org.apache.hadoop.hdfs.server.namenode.ha.EditLogTailer: Unable to trigger a roll of the active NN
java.util.concurrent.ExecutionException: java.io.IOException: Cannot find any valid remote NN to service request!
node1上stop-dfs.sh后重新启动start-dfs.sh
- 主备NN切换
有时候,hadoop的RM在ZKFC正常工作的情况下,也会出现两个standby,两个standby的问题就在于诸如Hive和Pig这种东西,会直接报一个Operation category READ is not supported in state standby,甚至你看着明明一个是active,一个是standby,也会报这个错误。这时候就必须手动强制切换了,强制切换完以后,别忘了,重新启动ZKFC就好了。这个强制切换的要求就是用户必须没有任何对元数据的操作,这样才能有效的防止脑裂的发生。
[hadoop@node2 ~]$ hadoop-daemon.sh stop zkfc
[hadoop@node2 ~]$ hadoop-daemon.sh start zkfc
五、HBase安装
-
把HBase安装包上传到集群中任一服务器中并解压
[root@node1 ~]# cd /opt/software/
[root@node1 software]# tar -xzvf hbase-2.1.1-bin.tar.gz -C /opt/module/
[root@node1 software]# cd …/module/
[root@node1 module]# chown -R hadoop:hadoop hbase-2.1.1/
[root@node1 data]# mkdir hbase
[root@node1 data]# chown -R hadoop:hadoop hbase -
修改hbase-env.sh配置文件
[root@node1 module]# cd hbase-2.1.1/conf/
[root@node1 conf]# vi hbase-env.sh
# 加入JAVA_HOME
export JAVA_HOME=/opt/module/jdk1.8
# 指定不使用自带的zookeeper
export HBASE_MANAGES_ZK=false -
修改hbase-site.xml配置文件
[root@node1 conf]# vi hbase-site.xml
在这里插入<configuration>
<!-- 指定缓存文件存储的路径 -->
<property>
<name>hbase.tmp.dir</name>
<value>/opt/module/hbase-2.1.1/data</value>
</property>
<!-- 设置HRegionServers共享目录 -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://mycluster:8020/hbase</value>
</property>
<!-- 设置HMaster的rpc端口 -->
<property>
<name>hbase.master.port</name>
<value>16000</value>
</property>
<!-- 设置HMaster的http端口 -->
<property>
<name>hbase.master.info.port</name>
<value>16010</value>
</property>
<!-- 开启分布式模式 -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!--指定zookeeper集群-->
<property>
<name>hbase.zookeeper.quorum</name>
<value>node1:2181,node2:2181,node3:2181</value>
</property>
<!-- 指定ZooKeeper集群端口 -->
<!-- ZooKeeper配置文件zoo.cfg中的clientPort。ZooKeeper提供给客户端连接的端口,默认是2181 -->
<property>
<name>hbase.zookeeper.property.clientPort</name>
<value>2181</value>
</property>
<!--指定Zookeeper数据目录,可以不配置,如果配置需要与ZooKeeper集群上配置相一致 -->
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/opt/module/zookeeper-3.4.13/Data</value>
</property>
<!-- hbase客户端rpc扫描一次获取的行数,默认是2147483647, -->
<property>
<name>hbase.client.scanner.caching</name>
<value>2000</value>
</property>
<!-- HRegion分裂前最大的文件大小(默认1.25G),设置为10G-->
<property>
<name>hbase.hregion.max.filesize</name>
<value>10737418240</value>
</property>
<!-- HRegionServer中最大的region数量 -->
<property>
<name>hbase.regionserver.reginoSplitLimit</name>
<value>2000</value>
</property>
<!-- StoreFile开始合并的阀值 -->
<property>
<name>hbase.hstore.compactionThreshold</name>
<value>6</value>
</property>
<!-- 当某一个region的storefile个数达到该值则block写入,等待compact-->
<property>
<name>hbase.hstore.blockingStoreFiles</name>
<value>14</value>
</property>
<!-- 当MemStore占用内存大小超过hbase.hregion.memstore.flush.size MemStore刷新缓存的大小的4倍,开始中block该HRegion的请求,进行flush释放内存,后台会有服务线程在周期内hbase.server.thread.wakefrequency定时检查-->
<property>
<name>hbase.hregion.memstore.block.multiplier</name>
<value>4</value>
</property>
<!-- service工作的sleep间隔 -->
<property>
<name>hbase.server.thread.wakefrequency</name>
<value>500</value>
</property>
<!--ZK并发连接的限制-->
<property>
<name>hbase.zookeeper.property.maxClientCnxns</name>
<value>300</value>
</property>
<!-- RegionServer进程block进行flush触发条件:该节点上所有region的memstore之和达到upperLimit*heapsize-->
<property>
<name>hbase.regionserver.global.memstore.size</name>
<value>0.4</value>
</property>
<!-- RegionServer进程触发flush的一个条件:该节点上所有region的memstore之和达到lowerLimit*heapsize-->
<property>
<name>hbase.regionserver.global.memstore.size.lower.limit</name>
<value>0.3</value>
</property>
<property>
<name>hfile.block.cache.size</name>
<value>0.4</value>
</property>
<!--HRegionserver处理IO请求的线程数-->
<property>
<name>hbase.regionserver.handler.count</name>
<value>100</value>
</property>
<!-- 客户端最大重试次数 -->
<property>
<name>hbase.client.retries.number</name>
<value>5</value>
</property>
<!-- 客户端重试的休眠时间 -->
<property>
<name>hbase.client.pause</name>
<value>100</value>
</property>
<property>
<name>hbase.wal.provider</name>
<value>filesystem</value>
</property>
</configuration> 代码片
-
创建backup-masters文件,并做修改
[root@node1 conf]# vi backup-masters
# 添加备用hbase-master
node2 -
修改regionservers文件,加入RegionServer节点列表
[root@node1 conf]# vi regionservers
# 默认有一行localhost,删除,否则启动时会报错
node1
node2
node3 -
把hadoop的配置文件core-site.xml和hdfs-site.xml复制到hbase的配置文件目录下
[root@node1 conf]# cp /opt/module/hadoop-3.1.1/etc/hadoop/core-site.xmlpwd
[root@node1 conf]# cp /opt/module/hadoop-3.1.1/etc/hadoop/hdfs-site.xmlpwd
[root@node1 conf]# chown hadoop:hadoop backup-masters core-site.xml hdfs-site.xml -
替换hbase lib下的核心包
hadoop 1.x是core包,2.x分拆成散的jar包,首先删除hbase原有hadoop jar包,避免冲突
[root@node1 conf]# cd …/lib
[root@node1 lib]# rm hadoop-.jar
[root@node1 lib]# find /opt/module/hadoop-3.1.1/share/hadoop/ -name "hadoopjar" | xargs -i cp {} /opt/module/hbase-2.1.1/lib
[root@node1 lib]#chown hadoop:hadoop hadoop-*.jar -
添加HBase环境变量
[root@node1 conf]# vi /etc/profile
export HBASE_HOME=/opt/module/hbase-2.1.1
export PATH= P A T H : PATH: PATH:HBASE_HOME/bin
[root@node1 conf]# source /etc/profile
-
创建目录
[root@node1 conf]# cd …
[root@node1 hbase-2.1.1]# mkdir data logs
[root@node1 hbase-2.1.1]# chown -R hadoop:hadoop data/ logs/
[root@node1 hbase-2.1.1]# cd data/
[root@node1 data]# echo ‘1’ > myid -
拷贝HBase到其他节点
[root@node1 data]# scp -r /opt/module/hbase-2.1.1/ hadoop@node2:/opt/module/
[root@node1 data]# scp -r /opt/module/hbase-2.1.1/ hadoop@node3:/opt/module/
11.在node2、node3上添加HBase环境变量
## 在node2上,执行以下
[root@node2 ~]# vi /etc/profile
export HBASE_HOME=/opt/module/hbase-2.1.1
export PATH=
P
A
T
H
:
PATH:
PATH:HBASE_HOME/bin
[root@node2 ~]# source /etc/profile
## 在node3上,执行以下
[root@node3 ~]# vi /etc/profile
export HBASE_HOME=/opt/module/hbase-2.1.1
export PATH=
P
A
T
H
:
PATH:
PATH:HBASE_HOME/bin
[root@node3 ~]# source /etc/profile
12.在node2、node3上修改pid文件
## 在node2上,执行以下
[root@node2 ~]# cd /opt/module/hbase-2.1.1/data/
[root@node2 data]# echo ‘2’ > myid
## 在node3上,执行以下
[root@node3 ~]# cd /opt/module/hbase-2.1.1/data/
[root@node3 data]# echo ‘3’ > myid
13.启动HBase集群
[hadoop@node1 ~]$ start-hbase.sh
#关闭hbase集群
[hadoop@node1 ~]$ stop-hbase.sh
#关闭HRegionServer
[hadoop@node1 ~]$ hbase-daemon.sh stop regionserver
#关闭单一节点hbase
[hadoop@node1 ~]$ hbase-daemon.sh stop master
14.验证HBase
-
命令行查看状态
[hadoop@node1 ~]$ hbase shell
hbase(main):001:0> status
1 active master, 1 backup masters, 3 servers, 0 dead, 0.6667 average load
Took 1.2309 seconds
15.HBase搭建问题总结
- zk注册信息未清理
安装完成后,jps可以看到HBase的所有信息,包括HMaster、 HRegionServer,但是hbase shell命令status,报如下错误:
hbase(main):001:0> status
ERROR: ZooKeeper available but no active master location found
这是hbase的老问题了,一次启动没成功,后面再次启动的时候留有上一次的痕迹,导致启动不成功,这个问题官方一直没解决,只能靠自己手动解决。
百度都是DNS解析问题,实际上是zk里注册了hbase信息,删掉zk中的hbase注册信息,然后重启zk和hbase即可:
[hadoop@node1 ~]$ zkCli.sh -server 127.0.0.1:2181
[zk: 127.0.0.1:2181(CONNECTED) 0] ls /
[zookeeper, yarn-leader-election, hbase-unsecure, hadoop-ha, hbase, rmstore]
[zk: 127.0.0.1:2181(CONNECTED) 1] rmr /hbase-unsecure
[zk: 127.0.0.1:2181(CONNECTED) 2] rmr /hbase
- hbase参数导致HRegionserver启动后关闭
hbase-hadoop-master-node1.log关键信息如下:
2018-12-18 15:59:34,925 WARN [RpcServer.default.FPBQ.Fifo.handler=28,queue=1,port=16000] master.MasterRpcServices: base.regionserver.wal.AbstractFSWAL.rollWriter(AbstractFSWAL.java:486)
org.apache.hadoop.fs.PathIsNotEmptyDirectoryException: ``/opt/module/hbase-2.1.1/data/hbase/WALs/node2,16020,1545119933365-splitting is non empty’: Directory is not empty
hbase-hadoop-regionserver-node1.log关键信息如下:
2018-12-18 15:59:35,816 ERROR [regionserver/node1:16020] regionserver.HRegionServer: ***** ABORTING region server node1,16020,1545119950897: Unhandled: Found interface org.apache.hadoop.hdfs.protocol.HdfsFileStatus, but class was expected *****
java.lang.IncompatibleClassChangeError: Found interface org.apache.hadoop.hdfs.protocol.HdfsFileStatus, but class was expected
2018-12-18 15:59:35,819 ERROR [regionserver/node1:16020] regionserver.HRegionServer: RegionServer abort: loaded coprocessors are: []
首先,确保各配置文件中,各文件路径的属主权限等都是正确的;再确保服务器时钟同步;如果上述均没有问题,在配置文件中明确指定FSHLog,例如,filesystem。
<property>
<name>hbase.wal.provider</name>
<value>filesystem</value>
</property>