Hadoop HDFS-HA

目录

Hadoop HDFS-HA

HA(High Availablity)

1.高可用:7*24小时不中断服务。
2.实现高可用最关键的策略是消除单点故障(一个节点故障,整个集群不可以使用),HA严格来说应该分成各个组件的HA机制:HDFS的HA和YARN的HA。
3.NameNode主要在以下两个方法影响HDFS集群
NameNode集群发生意外,如宕机,集群将无法使用,直到管理员重启。
NameNode机器需要升级,包括软件、硬件升级,此时集群也将无法使用

HDFS HA 功能通过配置多个NameNodes(1个Active/多个Standby)实现在集群中对NameNode的热备份来解决问题。如果出现故障可以将Standby替换Active。

HDFS-HA 集群搭建

当前HDFS集群的规划

Hadoop HDFS-HA

HA的主要目的是消除NameNode的单点故障,需要将HDFS集群重新规划,这里规划3个。

Hadoop HDFS-HA

HDFS-HA 核心问题

1.如何保证三台NameNode的数据一致

Fsimage:需要一台NameNode作为Active生成数据,其他NameNode作为Standby进行同步
Edits:需要引进新的模块JournaNode来保证edtis的文件数据一致性

2.怎么让只有一台nn是active,其他所有是standly

1.手动分配,指定某一台为active,其余为standly
2.自动分配

3.2nn在ha架构中不允许不存在,那么谁负责定期合并Fsimage和Edits?

由standly的nn

4.如果active的nn发生了问题,怎么让其他的nn变成新的active?
a.手动故障转移
b.自动故障转移:依赖框架

HDFS-HA手动配置

1 环境准备

1.修改IP
2.修改主机名和主机名与IP地址的映射
3.关闭防火墙
4.ssh免密登录
5.安装JDK,配置环境变量等

我之前已经配过了,具体流程可以看下面的博客
https://www.cnblogs.com/rananie/p/14802251.html
https://www.cnblogs.com/rananie/p/14897536.html

2 规划集群

Hadoop HDFS-HA

3 配置HDFS-HA集群

1.在opt目录下创建一个ha文件,103、104同样需要

[ranan@hadoop102 opt]$ sudo mkdir ha
[ranan@hadoop102 opt]$ ll
总用量 0
drwxr-xr-x. 2 root  root   6 1月   5 10:28 ha # 权限属于root用户
drwxr-xr-x. 4 ranan ranan 46 6月  17 2021 module
drwxr-xr-x. 2 ranan ranan 67 7月   8 21:34 software
[ranan@hadoop102 opt]$ sudo chown ranan:ranan ha  # 修改权限
[ranan@hadoop102 opt]$ ll
总用量 0
drwxr-xr-x. 2 ranan ranan  6 1月   5 10:28 ha
drwxr-xr-x. 4 ranan ranan 46 6月  17 2021 module
drwxr-xr-x. 2 ranan ranan 67 7月   8 21:34 software

2.将/opt/module/下的hadoop-3.1.3拷贝到/opt/ha目录下

[ranan@hadoop102 opt]$ cp -r /opt/module/hadoop-3.1.3 /opt/ha/

3.删除/opt/ha/hadoop-3.1.3 下的data和logs文件,删除数据

[ranan@hadoop102 hadoop-3.1.3]$ rm -rf data/ logs/

4.配置/opt/ha/hadoop-3.1.3/etc/hadoop/目录下的core-site.xmlhdfs-site.xml

<!-- core-site.xml -->
<configuration>
  <!-- 指定 NameNode 的地址 -->
<property>
        <name>fs.defaultFS</name>
        <value>hdfs://mycluster</value> <!--不需要单独指定一个节点为NameNode,我们访问的是mycluster,访问代理类来处理访问让访问连接到active节点-->
</property>
   <!-- 指定 hadoop 数据的存储目录 -->
<property>
        <name>hadoop.tmp.dir</name>
        <value>/opt/ha/hadoop-3.1.3/data</value>    
</property>
</configuration>


<!--hdfs-site.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>file://${hadoop.tmp.dir}/jn</value>
</property>

     <!-- 完全分布式集群名称 -->
<property>
        <name>dfs.nameservices</name>
        <value>mycluster</value>  <!--与core-site.xml里面的fs.defaultFS设置一致-->
</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> <!--与上述设置的集群中的namenode一致-->
        <value>hadoop102:8020</value>
</property>
	
<property>
        <name>dfs.namenode.rpc-address.mycluster.nn2</name>
        <value>hadoop103:8020</value>
</property>

<property>
        <name>dfs.namenode.rpc-address.mycluster.nn3</name>
        <value>hadoop104:8020</value>
</property>

     <!--NameNode的http外部通信地址 -->
<property>
        <name>dfs.namenode.http-address.mycluster.nn1</name> <!--与上述设置的集群中的namenode一致-->
        <value>hadoop102:9870</value>
</property>

<property>
        <name>dfs.namenode.http-address.mycluster.nn2</name>
        <value>hadoop103:9870</value>
</property>

<property>
        <name>dfs.namenode.http-address.mycluster.nn3</name>
        <value>hadoop104:9870</value>
</property>

<!-- 指定 NameNode 元数据在 JournalNode 上的存放位置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hadoop102:8485;hadoop103:8485;hadoop104:8485/mycluster</value>
</property>

<!-- 访问代理类: client用于确定哪个NameNode为Active,客户端访问mycluster集群,并不知道哪个节点是active,由代理类帮客户连接到active-->
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>

<!-- 配置隔离机制,即同一时刻只能有一个NameNode对外响应 -->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>

<!-- 使用隔离机制时需要 ssh 无秘钥登录,自动故障转移时用到-->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/ranan/.ssh/id_rsa</value>
</property>

</configuration>

5.分发配置信息

[ranan@hadoop102 opt]$ xsync ha/hadoop-3.1.3

4 启动HDFS-HA集群

1 修改3台节点的环境配置信息,关于hadoop的配置信息,我的在/etc/profile.d/my_env.sh

[ranan@hadoop103 hadoop-3.1.3]$ cd /etc/profile.d
[ranan@hadoop103 profile.d]$ sudo vim my_env.sh 
[ranan@hadoop102 profile.d]$ source /etc/profile  # 会重新加载profile脚本,该脚本里会加载profile.d

Hadoop HDFS-HA

2 在各个JournalNode节点上,启动JournalNode服务

[ranan@hadoop102 hadoop-3.1.3]$  hdfs --daemon start journalnode
[ranan@hadoop103 hadoop-3.1.3]$  hdfs --daemon start journalnode
[ranan@hadoop104 hadoop-3.1.3]$  hdfs --daemon start journalnode
[ranan@hadoop102 hadoop]$ jpsall
=============== hadoop102 ===============
4005 Jps
3933 JournalNode
=============== hadoop103 ===============
3738 Jps
3679 JournalNode
=============== hadoop104 ===============
3699 JournalNode
3757 Jps

3 在启动集群之前,需要格式化namenode,但是现在三台节点都是namenode,我们可以随便选择一个节点格式化,其他节点同步该信息,namenode需要一致

在nn1,对其格式化,并启动

[ranan@hadoop102 hadoop]$ hadfs namenode -farmat
[ranan@hadoop102 hadoop]$  hdfs --daemon start namenode

查看是否启动成功:http://hadoop102:9870/

Hadoop HDFS-HA

在nn2和nn3上,同步nn1的元数据信息

[ranan@hadoop103 hadoop-3.1.3]$ hdfs namenode -bootstrapStandby
[ranan@hadoop104 hadoop-3.1.3]$ hdfs namenode -bootstrapStandby
[ranan@hadoop103 hadoop-3.1.3]$ hdfs --daemon start namenode
[ranan@hadoop104 hadoop-3.1.3]$ hdfs --daemon start namenode

查看是否启动成功:http://hadoop103:9870/,http://hadoop104:9870/
Hadoop HDFS-HA
Hadoop HDFS-HA

4 修改其中一个节点为Active节点
因为这是我们手动配置的,所以所有节点都是standby,我们需要手动的修改其中一个为Active节点

先在所有节点上,启动datanode,将HDFS启动起来

[ranan@hadoop102 hadoop-3.1.3]$ hdfs --daemon start datanode
[ranan@hadoop103 hadoop-3.1.3]$ hdfs --daemon start datanode
[ranan@hadoop104 hadoop-3.1.3]$ hdfs --daemon start datanode
[ranan@hadoop102 hadoop]$ jpsall
=============== hadoop102 ===============
4200 NameNode
4570 DataNode
4747 Jps
3933 JournalNode
=============== hadoop103 ===============
3976 NameNode
4408 Jps
4238 DataNode
3679 JournalNode
=============== hadoop104 ===============
3699 JournalNode
4259 DataNode
3990 NameNode
4427 Jps

将nn1切换为Active

[ranan@hadoop102 hadoop]$ hdfs haadmin -transitionToActive nn1

Hadoop HDFS-HA

5 假设nn1挂掉了

kill nn1

[ranan@hadoop102 hadoop]$ jpsall
=============== hadoop102 ===============
4200 NameNode
4570 DataNode
19355 Jps
3933 JournalNode
=============== hadoop103 ===============
3976 NameNode
18923 Jps
4238 DataNode
3679 JournalNode
=============== hadoop104 ===============
3699 JournalNode
4259 DataNode
3990 NameNode
19033 Jps
[ranan@hadoop102 hadoop]$ kill -kill 4200
[ranan@hadoop102 hadoop]$ jpsall
=============== hadoop102 ===============
4570 DataNode
3933 JournalNode
19422 Jps
=============== hadoop103 ===============
18992 Jps
3976 NameNode
4238 DataNode
3679 JournalNode
=============== hadoop104 ===============
3699 JournalNode
4259 DataNode
3990 NameNode
19103 Jps

假设此时我们把nn2设置为active,报错102拒绝连接

[ranan@hadoop103 hadoop-3.1.3]$ hdfs haadmin -transitionToActive nn2
2022-01-11 10:10:18,292 INFO ipc.Client: Retrying connect to server: hadoop102/192.168.10.102:8020. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=1, sleepTime=1000 MILLISECONDS)
Unexpected error occurred  Call From hadoop103/192.168.10.103 to hadoop102:8020 failed on connection exception: java.net.ConnectException: 拒绝连接; For more details see:  http://wiki.apache.org/hadoop/ConnectionRefused
Usage: haadmin [-ns <nameserviceId>] [-transitionToActive [--forceactive] <serviceId>]

重启nn1,发现nn1变成了standby,现在没有active了,可以重新选取节点成为新的active

[ranan@hadoop102 hadoop]$ hdfs --daemon start namenode

Hadoop HDFS-HA

手动模式下,需要所有namenode启动才可以将某个节点转成Active

Active需要知道其他namenode是存活状态,因为一个集群中只能由一个Active,如果联系不上,不知道该节点是否是active。

HDFS-HA自动模式

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

主要需要解决的问题:当要提升某个节点为Active的时候,如果确定其他节点不是Active

ZooKeeper 是维护少量协调数据,通知客户端这些数据的改变和监视客户端故障的高可用服务
自动故障增加了两个新组件:Zookeeper和ZKFailoverController(ZKFC)进程,该进程监控节点是否挂掉,如果监控到挂点了,再次发送kill命令真正杀死节点,防止出现脑裂。

Hadoop HDFS-HA

HDFS-HA 自动故障转移的集群规划

Hadoop HDFS-HA

配置HDFS-HA 自动故障转移

1 在hdfs-site.xml里面打开自动转移

<!--打开自动转移-->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>

2 在core-site.xml里面添加zookeeper信息

<property>
<name>ha.zookeeper.quorum</name>
<value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value>
</property>

3 分发节点

[ranan@hadoop102 hadoop]$ xsync core-site.xml hdfs-site.xml

4 保持集群关闭状态下,启动Zookeeper集群,再初始化HA在Zookeeper中状态

# 启动zookeep
[ranan@hadoop102 zookeeper-3.4.10]# zkServer.sh start
[ranan@hadoop103 zookeeper-3.4.10]# zkServer.sh start
[ranan@hadoop104 zookeeper-3.4.10]# zkServer.sh start

# 初始化HA在Zookeeper中的状态
[ranan@hadoop102 zookeeper-3.4.10]# hdfs zkfc -formatZK

5 启动集群

[ranan@hadoop102 hadoop]# start-dfs.sh

Hadoop HDFS-HA

6 可以去zkCli.sh客户端查看NameNode节点内容

哪台机器先启动DFSZK Failover Controller,哪个机器的NameNode就是Active NameNode

[ranan@hadoop102 zookeeper]# bin/zkcli.sh

get -s /hadoop-ha/mycluster/ActiveStandbyElectorLock
mycluster nn2 hadoop103  # 这里是hadoop103节点

Hadoop HDFS-HA

7 杀死Hadoop103,观察Active是否转移

Active切换到hadoop102后,如果hadoop103重新启动,hadoop103不再是Active而是Standby

[ranan@hadoop103 zookeeper]# kill -9 4897

# zkcli.sh客户端查看
get -s /hadoop-ha/mycluster/ActiveStandbyElectorLock
mycluster nn1 hadoop102  # 这里切换到了hadoop102了

注意如果写代码上传到比如根目录使用hdfs://mycluster/
在上传过程中会去找active,所以可能在尝试中会连接到standby,有报错但是没关系。

YARN-HA配置

YARN-HA 工作机制

Hadoop HDFS-HA

配置YARN-HA集群

1 集群规划

Hadoop HDFS-HA

2 核心问题
a.如果当前active rm挂了,其他rm怎么上位
核心原理和hdfs一样,利用了zk的临时节点

b.当前rm上有很多的计算程序在等待运行,其他rm怎么将这些程序接手过来继续跑

rm会将当前的所有计算程序的状态存储在zk中,其他rm上位后会去读取,然后接着跑

3 修改yarn-site.xml,修改之后分发yarn-site.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>
<property>
	<name>yarn.resourcemanager.ha.rm-ids</name>
	<value>rm1,rm2,rm3</value>
</property>
<!--rm1的配置-->
<property>
	<name>yarn.resourcemanager.hostname.rm1</name>
	<value>hadoop102</value><!--指定rm1 的主机名-->
</property>
<property>
	<name>yarn.resourcemanager.webapp.address.rm1</name>
	<value>hadoop102:8088</value><!--指定rm1的web端地址-->
</property>	
<property>
	<name>yarn.resourcemanager.address.rm1</name>
	<value>hadoop102:8032</value><!--指定rm1的内部通信地址-->
</property>
<property>
<name>yarn.resourcemanager.scheduler.address.rm1</name>
	<value>hadoop102:8030</value><!--指定AM向rm1申请资源的地址-->
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address.rm1</name>
	<value>hadoop102:8031</value><!--指定供NM连接的地址-->
</property>	
<!--rm2的配置-->
<property>
	<name>yarn.resourcemanager.hostname.rm1</name>
	<value>hadoop103</value><!--指定rm2 的主机名-->
</property>
<property>
	<name>yarn.resourcemanager.webapp.address.rm1</name>
	<value>hadoop103:8088</value><!--指定rm2的web端地址-->
</property>	
<property>
	<name>yarn.resourcemanager.address.rm1</name>
	<value>hadoop103:8032</value><!--指定rm2的内部通信地址-->
</property>
<property>
<name>yarn.resourcemanager.scheduler.address.rm1</name>
	<value>hadoop103:8030</value><!--指定AM向rm2申请资源的地址-->
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address.rm1</name>
	<value>hadoop103:8031</value><!--指定供NM连接的地址-->
</property>	
<!--rm3的配置-->
<property>
	<name>yarn.resourcemanager.hostname.rm1</name>
	<value>hadoop104</value><!--指定rm3 的主机名-->
</property>
<property>
	<name>yarn.resourcemanager.webapp.address.rm1</name>
	<value>hadoop104:8088</value><!--指定rm3的web端地址-->
</property>	
<property>
	<name>yarn.resourcemanager.address.rm1</name>
	<value>hadoop104:8032</value><!--指定rm3的内部通信地址-->
</property>
<property>
<name>yarn.resourcemanager.scheduler.address.rm1</name>
	<value>hadoop104:8030</value><!--指定AM向rm3申请资源的地址-->
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address.rm1</name>
	<value>hadoop104:8031</value><!--指定供NM连接的地址-->
</property>		

<!--指定 zookeeper 集群的地址-->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>hadoop102:2181,hadoop103:2181,hadoop104: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,HADDOP_COMMON_HOME,HADOOP_HDFS_HOME,HADDOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAORED_HOME</value>
</property>
</configuration>

4 启动yarn

[ranan@hadoop102 hadoop]$ start-yarn.sh

# 查看服务状态
[ranan@hadoop102 hadoop]$ yarn rmadmin -getServiceState rm1
standby

Hadoop HDFS-HA

访问hadoop102:8088发现直接跳到了hadoop103:8088,因为这里hadoop103:8088是Active。

上一篇:Consider boosting spark.yarn.executor.memoryOverhead


下一篇:Linux集群之HA(高可用集群)篇