HADOOP HA + HBASE HA + YARN HA 搭

本文讲解HADOOP HA + HBASE HA + YARN HA 搭建原理和过程。 其实HA版本和非HA版本的前期准备工作基本一致,可以参考文章hadoop2.8.5安装采坑指南(非HA), hbase1.3.3安装采坑指南(非HA)

机器列表

进程 ip-1 ip-2 ip-3 ip-4 ip-5
Zookeeper NO NO YES YES YES
JouranlNode NO NO YES YES YES
NameNode YES YES NO NO NO
ZookeeperFailoverController YES YES NO NO NO
DataNode NO NO YES YES YES
ResourceManager YES YES NO NO NO
NodeManager NO NO YES YES YES
Hbase Master YES YES NO NO NO
Hbase RegionServer NO NO YES YES YES


附一张原理图
hadoop ha 原理图

前期准备

linux 内核参数调整

见文章hadoop2.8.5安装采坑指南(非HA)

机器磁盘挂载和安装用户

见文章hadoop2.8.5安装采坑指南(非HA)

hostname配置

见文章hadoop2.8.5安装采坑指南(非HA)

配置host

见文章hadoop2.8.5安装采坑指南(非HA)

禁掉防火墙

见文章hadoop2.8.5安装采坑指南(非HA)

关闭selinux

见文章hadoop2.8.5安装采坑指南(非HA)

ssh免密

方法见文章hadoop2.8.5安装采坑指南(非HA)
保证ip-1 和 ip-2,ip-3, ip-4, ip-5免密。
保证ip-2 和 ip-1,ip-3, ip-4, ip-5免密。

确保端口可以互相访问

见文章hadoop2.8.5安装采坑指南(非HA)

JDK和环境变量

见文章hadoop2.8.5安装采坑指南(非HA)

ZK安装

下载zk

下面命令分别在 ip-3, ip-4, ip-5机器上执行:


    mkdir -p /opt/zookeeper/data
    mkdir -p /opt/zookeeper/log

    cd /opt/app/

    wget http://mirrors.shu.edu.cn/apache/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz

    tar -zxvf zookeeper-3.4.13.tar.gz

    cd zookeeper-3.4.13.tar.gz
    cp zoo_sample.cfg zoo.cfg


然后

    vi zoo.cfg

    dataDir=/opt/zookeeper/data
    dataLogDir=/opt/zookeeper/log

    maxClientCnxns=0
    tickTime=2000
    initLimit=10
    syncLimit=5

    server.1=ip-3:2888:3888
    server.2=ip-4:2888:3888
    server.3=ip-5:2888:3888


然后

    # 在ip-3机器上 
    echo  1 > /opt/zookeeper/data/myid

    # 在ip-4机器上 
    echo  2 > /opt/zookeeper/data/myid

    # 在ip-5机器上 
    echo  3 > /opt/zookeeper/data/myid

Hadoop HA 安装

下载hadoop-2.8.5安装包

下载地址见文章hadoop2.8.5安装采坑指南(非HA)
hadoop安装包下载完成以后可能因为native lib问题导致用不了snappy压缩算法。所以最好自己重新编译一下,具体方法见;hbase支持snappy, lz4, bizp2,lzo,zs

hadoop 环境变量

见文章hadoop2.8.5安装采坑指南(非HA)

配置文件

如下的所有配置未见保证拷贝到集群所有机器上。
core-site.xml 最少配置

  • 跟非HA版本相比我们要改的地方是: fs.defaultFS 的值不用谢具体的ip了,要写一个类似于域名一样的东西,这里我们命名为self-nameservice。 这个值后面游泳。
  • 第二个要改的东西是 ha.zookeeper.quorum
    <configuration>
       <property> 
         <name>fs.defaultFS</name> <!--NameNode 的URI-->
         <value>hdfs://self-nameservice/</value> 
       </property> 
       <property> 
         <name>hadoop.tmp.dir</name> <!--hadoop临时文件的存放目录-->
         <value>/data/hadoop/temp</value> 
       </property> 
         <property>
             <name>ha.zookeeper.quorum</name>
             <value>ip-3:2181,ip-4:2181,ip-5:2181/hadoop</value>
         </property>
    </configuration>

core-site.xml 最少配置
细节:下面的几个配置要根据core-site.xml中配置的fs.defaultFS的值进行适配。

  • dfs.nameservices
  • dfs.ha.namenodes.self-nameservice
  • dfs.namenode.rpc-address.self-nameservice.nn1 dfs.namenode.rpc-address.self-nameservice.nn2
  • dfs.namenode.http-address.self-nameservice.nn1 dfs.namenode.http-address.self-nameservice.nn2
  • dfs.client.failover.proxy.provider.self-nameservice
    上面几个配置项认真检查, 漏一个都会导致HA搭建失败。
<configuration> 
  <property> 
    <!--namenode持久存储名字空间及事务日志的本地文件系统路径-->          
    <name>dfs.namenode.name.dir</name>          
    <value>/data/hadoop/dfs/name</value>            
    <!--目录无需预先创建,会自动创建-->       
  </property>        
  <property> 
    <!--DataNode存放块数据的本地文件系统路径-->          
    <name>dfs.datanode.data.dir</name>          
    <value>/data/hadoop/dfs/data</value>        
  </property>        
  <property> 
    <!--数据需要备份的数量,不能大于集群的机器数量,默认为3-->          
    <name>dfs.replication</name>          
    <value>1</value>       
  </property>  
  <!--hadoop HA 以后不要再开 secondNameNode 否则可能出现问题。
   <property> 
       <name>dfs.namenode.secondary.http-address</name> 
        <value>ip-1:8000</value> 
   </property>  
  -->        
  <property> 
    <!--设置为true,可以在浏览器中IP+port查看-->          
    <name>dfs.webhdfs.enabled</name>          
    <value>true</value>       
  </property>  
  <!--指定hdfs的nameservice为ns1,需要和core-site.xml中的保持一致 -->  
  <property> 
    <name>dfs.nameservices</name>  
    <value>self-nameservice</value> 
  </property>  
  <!-- ns1下面有两个NameNode,分别是nn1,nn2 -->  
  <property> 
    <name>dfs.ha.namenodes.self-nameservice</name>  
    <value>nn1,nn2</value> 
  </property>  
  <!-- nn1的RPC通信地址  访问hdfs的 端口-->  
  <property> 
    <name>dfs.namenode.rpc-address.self-nameservice.nn1</name>  
    <value>ip-1:8001</value> 
  </property>  
  <!-- nn1的http通信地址 -->  
  <property> 
    <name>dfs.namenode.http-address.self-nameservice.nn1</name>  
    <value>ip-1:8002</value> 
  </property>  
  <!-- nn2的RPC通信地址 -->  
  <property> 
    <name>dfs.namenode.rpc-address.self-nameservice.nn2</name>  
    <value>ip-2:8001</value> 
  </property>  
  <!-- nn2的http通信地址 -->  
  <property> 
    <name>dfs.namenode.http-address.self-nameservice.nn2</name>  
    <value>ip-2:8002</value> 
  </property>  
  <!-- 指定NameNode的元数据在JournalNode上的存放位置 -->  
  <property> 
    <name>dfs.namenode.shared.edits.dir</name>  
    <value>qjournal://ip-3:8485;ip-4:8485;ip-5:8485/ns1</value> 
  </property>  
  <!-- 指定JournalNode在本地磁盘存放数据的位置 -->  
  <property> 
    <name>dfs.journalnode.edits.dir</name>  
    <value>/data/journaldata</value> 
  </property>  
  <!-- 开启NameNode失败自动切换 -->  
  <property> 
    <name>dfs.ha.automatic-failover.enabled</name>  
    <value>true</value> 
  </property>  
  <!-- 配置失败自动切换实现方式 -->  
  <property> 
    <name>dfs.client.failover.proxy.provider.self-nameservice</name>  
    <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> 
  </property>  
  <!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行-->  
  <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/admin/.ssh/id_rsa</value> 
  </property>  
  <!-- 配置sshfence隔离机制超时时间 -->  
  <property> 
    <name>dfs.ha.fencing.ssh.connect-timeout</name>  
    <value>30000</value> 
  </property> 
</configuration>

虽然 JournalNodes可以确保集群中只有一个 Active NameNode 写入 edits,这对保护 edits 一致性很重要,但是在 failover 期间,有可能 Acitive NameNode 仍然存活,Client 可能还与其保持连接提供旧的数据服务,我们可以通过此配置,指定 shell 脚本或者 java 程序,SSH 到 Active NameNode 然后 Kill NameNode 进程。它有两种可选值:

  1. sshfence:SSH登录到 Active NameNode,并 Kill 此进程。首先当前机器能够使用 SSH 登录到远端,前提是已经授权(rsa)。
  2. shell:运行 shell 指令隔离 Active NameNode。

<configuration>
       <property> <!--mapreduce运用了yarn框架,设置name为yarn-->
      <name>mapreduce.framework.name</name>
      <value>yarn</value>
    </property>
    <property> <!--历史服务器,查看Mapreduce作业记录-->
      <name>mapreduce.jobhistory.address</name>
      <value>master:11103</value>
    </property>
    <property>
      <name>mapreduce.jobhistory.webapp.address</name>
      <value>master:11104</value>
    </property>
</configuration>


yarn-site.xml

    <configuration>

        <!-- -->
        <property>
           <name>yarn.resourcemanager.ha.enabled</name>
           <value>true</value>
        </property>
        <property>
           <name>yarn.resourcemanager.cluster-id</name>
           <value>self-yarn</value>
        </property>
        <property>
           <name>yarn.resourcemanager.ha.rm-ids</name>
           <value>rm1,rm2</value>
        </property>
        <property>
           <name>yarn.resourcemanager.hostname.rm1</name>
           <value>wz-hadoop2</value>
        </property>
        <property>
           <name>yarn.resourcemanager.hostname.rm2</name>
           <value>wz-hadoop3</value>
        </property>

        <property>
          <name>yarn.resourcemanager.webapp.address.rm1</name>
          <value>ip-1:8105</value>
        </property>
        <property>
          <name>yarn.resourcemanager.webapp.address.rm2</name>
          <value>ip-2:8105</value>
        </property>

        <property>
          <name>yarn.resourcemanager.admin.address.rm1</name>
          <value>ip-1:8904</value>
        </property>
        <property>
          <name>yarn.resourcemanager.admin.address.rm2</name>
          <value>ip-2:8904</value>
        </property>

        <property>
          <name>yarn.resourcemanager.resource-tracker.address.rm1</name>
          <value>ip-1:8903</value>
        </property>
        <property>
          <name>yarn.resourcemanager.resource-tracker.address.rm2</name>
          <value>ip-2:8903</value>
        </property>

        <property>
          <name>yarn.resourcemanager.scheduler.address.rm1</name>
          <value>ip-1:8902</value>
        </property>
        <property>
          <name>yarn.resourcemanager.scheduler.address.rm2</name>
          <value>ip-2:8902</value>
        </property>

        <property>
          <name>yarn.resourcemanager.address.rm1</name>
          <value>ip-1:8901</value>
        </property>
        <property>
          <name>yarn.resourcemanager.address.rm2</name>
          <value>ip-2:8901</value>
        </property>

        <property>
           <name>yarn.resourcemanager.zk-address</name>
           <value>ip-3:2181,ip-4:2181,ip-5:2181/resourcemanager</value>
        </property>
        <property>
           <name>yarn.nodemanager.aux-services</name>
           <value>mapreduce_shuffle</value>
        </property>
        <property>
                <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
                <value>org.apache.hadoop.mapred.ShuffleHandler</value>
        </property>
    </configuration>

启动前额外操作


经过上面配置以后, 先不要着急启动hadoop集群和yarn集群。我们还需要在zookeeper上创建两个目录。原因是因为上面配置文件中两处:

# core-site.xml

<property>
      <name>ha.zookeeper.quorum</name>
      <value>ip-3:2181,ip-4:2181,ip-5:2181/hadoop</value>
</property>

# yran-site.xml
<property>
        <name>yarn.resourcemanager.zk-address</name>
        <value>ip-3:2181,ip-4:2181,ip-5:2181/resourcemanager</value>
</property>


如上所示, hadoop的HA需要在zookeeper上创建 /hadoop 目录, yarn HA需要在zookeeper上创建 resourcemanager这个目录。否则集群HA会启动失败。

# 用zkCli链接上zookeeper 然后执行
create /hadoop ""
create /resourcemanager ""
#根据上面配置创建如下几个目录
# 在 ip-3 ip-4 ip-5执行
mkdir -p /data/journaldata 
# 在所有机器执行
mkdir -p /data/hadoop/dfs/name
mkdir -p /data/hadoop/dfs/data
mkdir -p /data/hadoop/temp

启动

启动zk
bin/zkServer.sh start
bin/zkServer.sh status
ZKFC初始目录
###确保执行下面命令前, zk创建/hadoop 目录
hdfs zkfc -formatZK
启动JournalNode
#在 ip-3ip-4ip-5机器上执行如下命令
sbin/hadoop-daemon.sh start journalnode
启动NameNode
#在 ip-1上 执行如下命令。 格式化HDFS #在wz-hadoop2上执行命令:
 hdfs namenode -format

# 在 ip-1上执行如下命令:
 sbin/hadoop-daemon.sh start namenode

# 在HA的另外一台机器(ip-2)上执行如下命令
hdfs namenode -bootstrapStandby
sbin/hadoop-daemon.sh start namenode


# 目前HA的两台 都是 standby状态
# 切换一台为active状态
hdfs haadmin -transitionToActive -forcemanual nn1

#  查看状态
hdfs haadmin -getServiceState nn1

# Active 状态的NameNode 执行如下命令
sbin/start-dfs.sh

注意上面的命令仅限第一次启动cluster的时候使用,命令比较繁琐,只要HA级群启动成功以后, 后续启停HA 集群只用如下命令即可。

#关闭HA集群
sbin/stop-dfs.sh
#启动HA集群
sbin/start-dfs.sh
Yarn 启动
# 在 ip-1上启动
sbin/start-yarn.sh
# HA的另外一台机器(ip-2)上执行如下命令
sbin/yarn-daemon.sh start resourcemanager
#查看状态
yarn rmadmin -getServiceState rm2

# 此时发现两台 ResourceManager都是standby状态,执行下面命令,指定一台为active
yarn rmadmin -transitionToActive  --forcemanual  rm1

验证是否HA成功

验证Hadoop HA是否成功

#查看目前两个namenode的状态
hdfs haadmin -getServiceState nn1
active
hdfs haadmin -getServiceState nn2
standby
# ip-1上执行下面命令 上传文件
hadoop fs -put text.txt /
# kill -9 ip-1 的namenode
# 在ip-2 上执行下面命令
hadoop fs -ls /
# 同时查看 
hdfs haadmin -getServiceState nn2
active

验证YARN HA是否成功

#查看状态
yarn rmadmin -getServiceState rm1
actie
yarn rmadmin -getServiceState rm2
standby
# 访问页面
http://ip-1:8105/cluster/scheduler
# 访问 http://ip-2:8105/cluster/scheduler 发现自动跳转到 http://ip-1:8105/cluster/scheduler
# ip-1上执行 kill -9  杀死active的 ResourceManager。
yarn rmadmin -getServiceState rm2
active

HBASE HA 搭建

Hadoop HA搭建好了以后,hbase ha搭建非常简单。 hbase HA的配置文件跟非HA配置文件一模一样详情见: hbase1.3.3安装采坑指南(非HA)

修改配置文件

根据hadoop HA的 ha nameservice配置如下

# 修改hbase-site.xml
<property> 
   <name>hbase.rootdir</name> <!-- hbase存放数据目录 -->
   <value>hdfs://self-nameservice/hbase-data/hbase/hbase_db</value>

</property> 
      
# 在hbase-1.3.3/conf 目录中
echo ip-2 > backup-masters

启动


sh bin/start-hbase.sh

然后打开hbase web。 查看 Backup Masters 发现多了 ip-2这个机器。

坑1


19/03/22 16:37:28 FATAL ha.ZKFailoverController: The failover controller encounters runtime error: java.lang.RuntimeException: java.io.IOException: Couldn't create /hadoop-ha 19/03/22 16:37:28 FATAL tools.DFSZKFailoverController: Got a fatal error, exiting now java.io.IOException: Couldn't create /hadoop-ha


原因是没有提前在zookeeper上创建 /hadoop 目录。
因为 core-site.xml配置中我们指定了zk的目录。

    <property>
          <name>ha.zookeeper.quorum</name>
          <value>ip-3:2181,ip-4:2181,ip-5:2181/hadoop</value>
    </property>

坑2

2019-03-26 10:19:37,131 FATAL org.apache.hadoop.yarn.server.resourcemanager.ResourceManager: Error starting ResourceManager org.apache.hadoop.service.ServiceStateException: java.io.IOException: Couldn't create /yarn-leader-election


原因没有提前在zookeeper上创建 /resourcemanager 目录

    因为我们在yarn-site.xml中配置了目录
    <property>
            <name>yarn.resourcemanager.zk-address</name>
            <value>ip-3:2181,ip-4:2181,ip-5:2181/resourcemanager</value>
    </property>

坑3

执行 hadoop fs -ls /
-ls: java.net.UnknownHostException: self-nameservice

原因:

# 一定不要忘了这个配置 也要配置成 self-nameservice
    <property>
          <name>dfs.client.failover.proxy.provider.xxx</name>
          <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
      </property>

坑4

2019-03-22 15:53:11,958 INFO org.apache.hadoop.hdfs.server.common.Storage: Formatting journal Storage Directory /tmp/hadoop/dfs/journalnode/ns1 with nsid: 55943428 2019-03-22 15:53:11,963 INFO org.apache.hadoop.hdfs.server.common.Storage: Lock on /tmp/hadoop/dfs/journalnode/ns1/in_use.lock acquired by nodename 30640@wz-hadoop1 2019-03-22 15:56:36,242 ERROR org.apache.hadoop.hdfs.qjournal.server.JournalNode: RECEIVED SIGNAL 15: SIGTERM

可以删除所有node的 /tmp/hadoop/dfs/journalnode/ns1/in_use.lock 再启动集群

坑5

2019-03-22 16:43:05,093 WARN org.apache.hadoop.hdfs.server.namenode.FSNamesystem: Encountered exception loading fsimage java.io.IOException: NameNode is not formatted. at org.apache.hadoop.hdfs.server.namenode.FSImage.recoverTransitionRead(FSImage.java:230)

> 如果集群第一次启动的话可以参照如下两种解决方法

  1. 忘记指定格式化的话,那么按照本文上面命令先格式化。
  2. 如果在启动第二台namenode的时候报的错误的话,那么记住执行 hdfs namenode -bootstrapStandby 在执行 sbin/hadoop-daemon.sh start namenode

    如果是 namenode restart以后发生的。
    从HA的另外一台namenode的 data/hadoop/dfs/name/current/ 中copy到 这台机器上。然后在 运行启动命令就好了

坑6

172.16.217.85:8485: [[1,2], [3,4], [5,6], [7,8], [9,10], [11,12], [13,14], [15,15], [16,16], [17,24], [25,26], [27,27]] 2 exceptions thrown: 172.16.217.199:8485: Journal Storage Directory /data/journaldata/ns1 not formatted

坑7

java.io.IOException: There appears to be a gap in the edit log. We expected txid 5, but got txid 16. at org.apache.hadoop.hdfs.server.namenode.MetaRecoveryContext.editLogLoaderPrompt(MetaRecoveryContext.java:94)

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
慷慨打赏