HadoopHA搭建

1. HA概述

所谓HA(High Availablity),即高可用7*24小时不中断服务。实现高可用最关键的策略是消除单点故障。Hadoop的HA就是HDFS的HA和YARN的HA。

2. HDFS的HA

HDFS HA功能通过配置多个NameNodes(Active/Standby)实现在集群中对NameNode的热备来解决上述问题。如果出现故障,如机器崩溃或机器需要升级维护,这时可通过此种方式将NameNode很快的切换到另外一台机器。

2.1 HDFS HA核心问题

  1. 怎么保证多个namenode的数据一致?
  • Fsimage: 让一台 nn 生成数据,让其他机器nn同步
  • Edits: 需要引进新的模块JournalNode来保证edtis的文件的数据一致性
  1. 在HA架构中并不存在Secondarynamenode,那么定期合并fsimage和edtis的活谁来干?
    由standby状态的nn来干
  2. 如果nn真的发生了问题,怎么让其他的nn上位干活?
    第一次namenode谁先启动就是active, 其他就是standby, 出现问题时自动故障转移。

2.2 自动故障转移集群规划

node01 node02 node03
NameNode NameNode
JournalNode JournalNode JournalNode
DataNode DataNode DataNode
Zookeeper Zookeeper Zookeeper
ZKFC ZKFC

2.3 HDFS-HA自动故障转移工作机制

HDFS部署实现自动故障转移,需要增加两个新组件:ZooKeeper和ZKFailoverController(ZKFC)。如图所示。ZooKeeper是维护少量协调数据,通知客户端这些数据的改变和监视客户端故障的高可用服务。 alt text

3. 配置HDFS HA集群

3.1 配置core-site.xml

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.4.2/data</value>
    </property>
    <!-- 指定 zkfc 要连接的 zkServer 地址 -->
    <property>
        <name>ha.zookeeper.quorum</name>
        <value>node01:2181,node02:2181,node03:2181</value>
    </property>
</configuration>

3.2 配置hdfs-site.xml

xml
<configuration>
    <!-- NameNode 数据存储目录 -->
    <property>
        <name>dfs.namenode.name.dir</name>
        <value>file://${hadoop.tmp.dir}/name</value>
    </property>
    <!-- DataNode 数据存储目录 -->
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>file://${hadoop.tmp.dir}/data</value>
    </property>
    <!-- JournalNode 数据存储目录 -->
    <property>
        <name>dfs.journalnode.edits.dir</name>
        <value>${hadoop.tmp.dir}/jn</value>
    </property>
    <!-- 完全分布式集群名称 -->
    <property>
        <name>dfs.nameservices</name>
        <value>mycluster</value>
    </property>
    <!-- 集群中 NameNode 节点都有哪些 -->
    <property>
        <name>dfs.ha.namenodes.mycluster</name>
        <value>nn1,nn2,nn3</value>
    </property>
    <!-- NameNode 的 RPC 通信地址 -->
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn1</name>
        <value>node01:8020</value>
    </property>
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn2</name>
        <value>node02:8020</value>
    </property>
    <!-- NameNode 的 http 通信地址 -->
    <property>
        <name>dfs.namenode.http-address.mycluster.nn1</name>
        <value>node01:9870</value>
    </property>
    <property>
        <name>dfs.namenode.http-address.mycluster.nn2</name>
        <value>node02:9870</value>
    </property>
    <!-- 指定 NameNode 元数据在 JournalNode 上的存放位置 -->
    <property>
        <name>dfs.namenode.shared.edits.dir</name>
        <value>qjournal://node01:8485;node02:8485/mycluster</value>
    </property>
    <!-- 访问代理类:client 用于确定哪个 NameNode 为 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.fencing.methods</name>
        <value>
            sshfence
            shell(/bin/true)
        </value>
    </property>
    <!-- 使用隔离机制时需要 ssh 秘钥登录-->
    <property>
        <name>dfs.ha.fencing.ssh.private-key-files</name>
        <value>/home/jack/.ssh/id_rsa</value>
    </property>
    <!-- 启用 nn 故障自动转移 -->
    <property>
        <name>dfs.ha.automatic-failover.enabled</name>
        <value>true</value>
    </property>
    <!-- 指定HDFS副本数量 -->
    <property>
		<name>dfs.replication</name>
		<value>2</value>
	</property>
</configuration>

然后分发配置好的hadoop环境到其他节点。

4. 启动HDFS HA集群

  1. 配置环境变量
sh
## 在三个节点上分别执行
vim /etc/profile.d/my_env.sh
## 添加如下内容
#JAVA_HOME
export JAVA_HOME=/opt/module/jdk-17.0.16
export PATH=$PATH:$JAVA_HOME/bin
#HADOOP_HOME
export HADOOP_HOME=/opt/module/hadoop-3.4.2
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin
  1. 启动Zookeeper以后,然后再初始化HA在Zookeeper中状态:
sh
## 在node01上执行
hdfs zkfc -formatZK
  1. 启动journalnode服务
sh
## 在三个节点上分别执行
hdfs --daemon start journalnode
  1. 在[nn1]上,对其进行格式化,并启动
sh
## node01上执行
hdfs namenode -format
hdfs --daemon start namenode
  1. 启动[nn1]和[nn2]
sh
## node02上执行
hdfs namenode -bootstrapStandby
  1. 在所有节点上,启动datanode
sh
hdfs --daemon start datanode

不要使用hadoop_helper或者start-dfs.sh脚本,因为start-dfs.sh群起脚本默认的启动顺序是先启动NN,再启动DN,然后再启动JN,而处于Standby状态的NameNode启动时会连接JournalNode,JN由于还没有启动起来,NN就会报错。查看NameNode日志报错如下:

sh
2020-08-17 10:11:40,658 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: hadoop102/192.168.6.102:8485. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
2020-08-17 10:11:40,659 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: hadoop102/192.168.6.102:8485. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
2020-08-17 10:11:40,659 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: hadoop103/192.168.6.103:8485. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
2020-08-17 10:11:41,660 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: hadoop102/192.168.6.102:8485. Already tried 1 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
2020-08-17 10:11:41,660 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: hadoop102/192.168.6.102:8485. Already tried 1 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
  1. 如果发现没有DFSZKFailoverController进程, 需要单独启动:
sh
hdfs --daemon start zkfc

5. 测试HDFS HA集群

5.1 查看Namenode选举节点内容

连接Zookeeper,查看ActiveStandbyElectorLock节点信息:
alt text 可以看到当前是node02为主节点。

5.2 访问查看HDFS的webUI

node01节点的HDFS的webUI:
alt text node02节点的HDFS的webUI:
alt text 然后杀掉node02的namenode:

sh
[jack@node02 hadoop-3.4.2]$ jps
1136 DataNode
1058 NameNode
1000 JournalNode
906 QuorumPeerMain
1566 DFSZKFailoverController
[jack@node02 hadoop-3.4.2]$ kill -9 1058

会发现namnode发生自主切换: alt text

6. YARN HA机制

在Hadoop2.4之后,通过以主动/备用ResourceManager对的形式添加冗余,以消除RM的单点故障。 alt text

7. 配置YARN HA集群

7.1 集群规划

node01 node02 node03
ResourceManager ResourceManager
NodeManager NodeManager NodeManager
Zookeeper Zookeeper Zookeeper
ZKFC ZKFC

7.2 核心问题

  1. 如果当前active rm挂了,其他rm怎么将其他standby rm上位
    核心原理跟hdfs一样,利用了zk的临时节点
  2. 当前rm上有很多的计算程序在等待运行,其他rm怎么将这些程序接手过来接着跑
    rm会将当前的所有计算程序的状态存储在zk中,其他rm上位后会去读取,然后接着跑

7.3 具体配置

yarn-site.xml配置如下:

xml
<configuration>
    <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>cluster-yarn1</value>
    </property>
    <!--指定 resourcemanager 的逻辑列表-->
    <property>
        <name>yarn.resourcemanager.ha.rm-ids</name>
        <value>rm1,rm2</value>
    </property>
    <!-- ========== rm1 的配置 ========== -->
    <!-- 指定 rm1 的主机名 -->
    <property>
        <name>yarn.resourcemanager.hostname.rm1</name>
        <value>node02</value>
    </property>
    <!-- 指定 rm1 的 web 端地址 -->
    <property>
        <name>yarn.resourcemanager.webapp.address.rm1</name>
        <value>node02:8088</value>
    </property>
    <!-- 指定 rm1 的内部通信地址 -->
    <property>
        <name>yarn.resourcemanager.address.rm1</name>
        <value>node02:8032</value>
    </property>
    <!-- 指定 AM 向 rm1 申请资源的地址 -->
    <property>
        <name>yarn.resourcemanager.scheduler.address.rm1</name>
        <value>node02:8030</value>
    </property>
    <!-- 指定供 NM 连接的地址 -->
    <property>
        <name>yarn.resourcemanager.resource-tracker.address.rm1</name>
        <value>node02:8031</value>
    </property>
    <!-- ========== rm2 的配置 ========== -->
    <!-- 指定 rm2 的主机名 -->
    <property>
        <name>yarn.resourcemanager.hostname.rm2</name>
        <value>node03</value>
    </property>
    <property>
        <name>yarn.resourcemanager.webapp.address.rm2</name>
        <value>node03:8088</value>
    </property>
    <property>
        <name>yarn.resourcemanager.address.rm2</name>
        <value>node03:8032</value>
    </property>
    <property>
        <name>yarn.resourcemanager.scheduler.address.rm2</name>
        <value>node03:8030</value>
    </property>
    <property>
        <name>yarn.resourcemanager.resource-tracker.address.rm2</name>
        <value>node03:8031</value>
    </property>
    <!-- 指定 zookeeper 集群的地址 -->
    <property>
        <name>yarn.resourcemanager.zk-address</name>
        <value>node01:2181,node02:2181,node03: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>
    <!-- 环境变量的继承 -->
    <property>
        <name>yarn.nodemanager.env-whitelist</name>
        <value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME</value>
    </property>
    <!--日志聚集功能-->
    <property>
        <name>yarn.log-aggregation-enable</name>
        <value>true</value>
    </property>
    <!--日志保留时间设置7天-->
    <property>
        <name>yarn.log-aggregation.retain-seconds</name>
        <value>604800</value>
    </property>
</configuration>

分发配置文件到其他节点上。

8. 启动YARN HA

  1. 在node02或者node03中执行:
sh
start-yarn.sh
  1. 查看服务状态
sh
[jack@node02 hadoop-3.4.2]$ yarn rmadmin -getServiceState rm1
standby
[jack@node02 hadoop-3.4.2]$ yarn rmadmin -getServiceState rm2
active
  1. 访问http://node02:8088/cluster ,会发现页面自动跳转到http://node03:8088/cluster: alt text
  2. 查看zk: alt text

评论