Hadoop HA高可用
HA概述
- 所谓HA(High Availablity),即高可用(7*24小时不中断服务)
- 实现高可用最关键的策略是消除单点故障。HA严格来说应该分成各个组件的HA机制:
- HDFS的HA
- YARN的HA
- NameNode主要在以下两个方面影响HDFS集群
- NameNode机器发生意外,如宕机,集群将无法使用,直到管理员重启
- NameNode机器需要升级,包括软件、硬件升级,此时集群也将无法使用
- HDFS HA功能通过配置多个NameNodes(Active/Standby)实现在集群中对NameNode的热备来解决上述问题。如果出现故障,如机器崩溃或机器需要升级维护,这时可通过此种方式将NameNode很快的切换到另外一台机器。
HDFS-HA集群搭建
现有HDFS集群的规划
| hadoop102 | hadoop103 | hadoop104 | | —- | —- | —- | | NameNode | | SecondaryNameNode | | DataNode | DataNode | DataNode |
HA规划
- HA的主要目的是消除NameNode的单点故障,需要将hdfs集群规划如下 | hadoop102 | hadoop103 | hadoop104 | | —- | —- | —- | | NameNode | NameNode | NameNode | | DataNode | DataNode | DataNode |
HDFS-HA核心问题
怎么保证三台NameNode的数据一致
- Fsimage:让一台nn生成数据,让其它机器nn同步
Edits:需要引进新的模块
JournalNode来保证edits的文件的数据一致性怎么同时让只有一台nn是active,其它都是standby
手动分配
-
2nn在ha架构中并不存在,定期合并fsimage和edits的活谁来干?
-
如果nn真的发生了问题,怎么让其它的nn上位干活
手动故障转移
-
HDFS-HA手动模式
环境准备
修改IP
- 修改主机名及主机名和IP地址映射
- 关闭防火墙
- ssh免密登录
- 安装JDK、配置环境变量等
规划机器
| hadoop102 | hadoop103 | hadoop104 | | —- | —- | —- | | NameNode | NameNode | NameNode | | JournalNode | JournalNode | JournalNode | | DataNode | DataNode | DataNode |
配置HDFS-HA集群
- 官方地址:http://hadoop.apache.org/
- 在opt目录下创建一个ha文件夹
cd /optmkdir ha
- 将
/opt/module下的hadoop-3.1.3拷贝到/opt/ha目录下(记得删除data和logs目录)cp -r /opt/module/hadoop-3.1.3 /opt/ha/
配置
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/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>${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>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> <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 --> <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</value> </property> <!-- 使用隔离机制时需要 ssh 秘钥登录--> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/root/.ssh/id_rsa</value> </property> </configuration>分发配置好的hadoop环境到其它节点
vi /etc/profile.d/my_env.sh- 将
HADOOP_HOME部分改为如下 ```xmlJAVA_HOME
export JAVA_HOME=/opt/module/jdk1.8.0_212 export PATH=$PATH:$JAVA_HOME/bin
HADOOP_HOME
export HADOOP_HOME=/opt/ha/hadoop-3.1.3 export PATH=$PATH:$HADOOP_HOME/bin export PATH=$PATH:$HADOOP_HOME/sbin
- 三台机器全部 `source`环境变量
- `source /etc/profile`
<a name="u57ys"></a>
#### 在各个 `JournalNode`节点上,输入以下命令启动 `journalnode` 服务
- `[root@hadoop102 ~]# hdfs --daemon start journalnode`
- `[root@hadoop103 ~]# hdfs --daemon start journalnode`
- `[root@hadoop104 ~]# hdfs --daemon start journalnode`
<a name="j0tD8"></a>
#### 在nn1上(hadoop102),对其进行格式化,并启动
- `hdfs namenode -format` //格式化
- `hdfs --daemon start namenode`
<a name="eaphS"></a>
#### 在nn2和nn3上(hadoop103、hadoop104),同步nn1的元数据信息
- `hdfs namenode -bootstrapStandby`
- `hdfs namenode -bootstrapStandby`
<a name="AMykO"></a>
#### 启动nn2和nn3
- `hdfs --daemon start namenode`
- `hdfs --daemon start namenode`
<a name="QblB0"></a>
#### 查看web页面
- 
- 
- 
<a name="xBI5L"></a>
#### 在所有节点上,启动datanode
- `hdfs --daemon start datanode`
<a name="dqGqx"></a>
#### 将nn1切换为Active
- `hdfs haadmin -transitionToActive nn1`
<a name="ebAex"></a>
#### 查看是否Active
- `hdfs haadmin -getServiceState nn1`
- 
<a name="PvsrB"></a>
## HDFS-HA自动模式
<a name="uH6S4"></a>
### HDFS-HA自动故障转移工作机制
- 自动故障转移为HDFS部署增加了两个新组件:ZooKeeper和ZKFailoverController(ZKFC)进程,如图所示:ZooKeeper是维护少量协调数据,通知客户端这些数据的改变和监视客户端故障的高可用服务。
- 
<a name="VBZ2n"></a>
### HDFS-HA自动故障转移的集群规划
| hadoop102 | hadoop103 | hadoop104 |
| --- | --- | --- |
| NameNode | NameNode | NameNode |
| JournalNode | JournalNode | JournalNode |
| DataNode | DataNode | DataNode |
| Zookeeper | Zookeeper | Zookeeper |
| ZKFC | ZKFC | ZKFC |
<a name="aFTWp"></a>
### 配置HDFS-HA自动故障转移
<a name="Pw7ZE"></a>
#### 具体配置
- 在`hdfs-site.xml`中增加
```xml
<!-- 启用 nn 故障自动转移 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
在
core-site.xml文件中增加<!-- 指定 zkfc 要连接的 zkServer 地址 --> <property> <name>ha.zookeeper.quorum</name> <value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value> </property>分发配置
关闭所有HDFS服务
- 启动Zookeeper集群
zkServer.sh start
- 启动Zookeeper后,然后再初始化HA的Zookeeper中状态
hdfs zkfc -formatZK
启动HDFS服务
自动故障转移配置好以后,然后使用
start-dfs.sh群起脚本启动hdfs集群,有可能会遇到NameNode起来一会后,进程自动关闭的问题。查看NameNode日志,报错信息如下:2020-08-17 10:11:49,676 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: hadoop103/192.168.6.103:8485. Already tried 9 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS) 2020-08-17 10:11:49,678 WARN org.apache.hadoop.hdfs.server.namenode.FSEditLog: Unable to determine input streams from QJM to [192.168.6.102:8485, 192.168.6.103:8485, 192.168.6.104:8485]. Skipping. org.apache.hadoop.hdfs.qjournal.client.QuorumException: Got too many exceptions to achieve quorum size 2/3. 3 exceptions thrown: 192.168.6.103:8485: Call From hadoop102/192.168.6.102 to hadoop103:8485 failed on connection exception: java.net.ConnectException: 拒绝连接; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused 192.168.6.102:8485: Call From hadoop102/192.168.6.102 to hadoop102:8485 failed on connection exception: java.net.ConnectException: 拒绝连接; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused 192.168.6.104:8485: Call From hadoop102/192.168.6.102 to hadoop104:8485 failed on connection exception: java.net.ConnectException: 拒绝连接; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused查看报错日志,可分析出报错原因是因为 NameNode 连接不上 JournalNode,而利 用 jps 命令查看到三台 JN 都已经正常启动,为什么 NN 还是无法正常连接到 JN 呢?这 是因为 start-dfs.sh 群起脚本默认的启动顺序是先启动 NN,再启动 DN,然后再启动 JN, 并且默认的 rpc 连接参数是重试次数为 10,每次重试的间隔是 1s,也就是说启动完 NN 以后的 10s 中内,JN 还启动不起来,NN 就会报错了。
- 解决方案:可以等JN成功启动后,手动启动下三台NN
hdfs --daemon start namenode
也可以在
core-site.xml里适当调大参数<!-- NN 连接 JN 重试次数,默认是 10 次 --> <property> <name>ipc.client.connect.max.retries</name> <value>20</value> </property> <!-- 重试时间间隔,默认 1s --> <property> <name>ipc.client.connect.retry.interval</name> <value>5000</value> </property>YARN-HA配置
YARN-HA工作机制
-
具体配置
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> <!--指定 resourcemanager 的逻辑列表--> <property> <name>yarn.resourcemanager.ha.rm-ids</name> <value>rm1,rm2,rm3</value> </property> <!-- ========== rm1 的配置 ========== --> <!-- 指定 rm1 的主机名 --> <property> <name>yarn.resourcemanager.hostname.rm1</name> <value>hadoop102</value> </property> <!-- 指定 rm1 的 web 端地址 --> <property> <name>yarn.resourcemanager.webapp.address.rm1</name> <value>hadoop102:8088</value> </property> <!-- 指定 rm1 的内部通信地址 --> <property> <name>yarn.resourcemanager.address.rm1</name> <value>hadoop102:8032</value> </property> <!-- 指定 AM 向 rm1 申请资源的地址 --> <property> <name>yarn.resourcemanager.scheduler.address.rm1</name> <value>hadoop102:8030</value> </property> <!-- 指定供 NM 连接的地址 --> <property> <name>yarn.resourcemanager.resource-tracker.address.rm1</name> <value>hadoop102:8031</value> </property> <!-- ========== rm2 的配置 ========== --> <!-- 指定 rm2 的主机名 --> <property> <name>yarn.resourcemanager.hostname.rm2</name> <value>hadoop103</value> </property> <property> <name>yarn.resourcemanager.webapp.address.rm2</name> <value>hadoop103:8088</value> </property> <property> <name>yarn.resourcemanager.address.rm2</name> <value>hadoop103:8032</value> </property> <property> <name>yarn.resourcemanager.scheduler.address.rm2</name> <value>hadoop103:8030</value> </property> <property> <name>yarn.resourcemanager.resource-tracker.address.rm2</name> <value>hadoop103:8031</value> </property> <!-- ========== rm3 的配置 ========== --> <!-- 指定 rm1 的主机名 --> <property> <name>yarn.resourcemanager.hostname.rm3</name> <value>hadoop104</value> </property> <!-- 指定 rm1 的 web 端地址 --> <property> <name>yarn.resourcemanager.webapp.address.rm3</name> <value>hadoop104:8088</value> </property> <!-- 指定 rm1 的内部通信地址 --> <property> <name>yarn.resourcemanager.address.rm3</name> <value>hadoop104:8032</value> </property> <!-- 指定 AM 向 rm1 申请资源的地址 --> <property> <name>yarn.resourcemanager.scheduler.address.rm3</name> <value>hadoop104:8030</value> </property> <!-- 指定供 NM 连接的地址 --> <property> <name>yarn.resourcemanager.resource-tracker.address.rm3</name> <value>hadoop104:8031</value> </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.ZKRMStateSt ore</value> </property> <!-- 环境变量的继承 --> <property> <name>yarn.nodemanager.env-whitelist</name> <value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLAS SPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME</value> </property> </configuration>-
启动YARN
start-yarn.sh- 查看服务状态
yarn rmadmin -getServiceState rm1最终集群规划
| hadoop102 | hadoop103 | hadoop104 | | —- | —- | —- | | NameNode | NameNode | NameNode | | JournalNode | JournalNode | JournalNode | | DataNode | DataNode | DataNode | | Zookeeper | Zookeeper | Zookeeper | | ZKFC | ZKFC | ZKFC | | ResourceManager | ResourceManager | ResourceManager | | NodeManager | NodeManager | NodeManager |
