搭建Hadoop HA(高可用)集群
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集群的规划:
1 号服务器 | 2 号服务器 | 3 号服务器 | |
---|---|---|---|
name | hadoop103 | hadoop104 | hadoop105 |
IP | 192.168.64.103 | 192.168.64.104 | 192.168.64.105 |
HDFS | NameNode、DataNode | DataNode | SecondaryNameNode、DataNode |
HA 的主要目的是消除 NameNode 的单点故障,需要将 hdfs 集群规划成以下模样:
1 号服务器 | 2 号服务器 | 3 号服务器 | |
---|---|---|---|
name | hadoop103 | hadoop104 | hadoop105 |
IP | 192.168.64.103 | 192.168.64.104 | 192.168.64.105 |
HDFS | NameNode、DataNode | NameNode、DataNode | NameNode、DataNode |
HDFS-HA 核心问题
怎么保证三台 namenode 的数据一致
答:
- Fsimage:让一台 NameNode 生成数据,让其他机器的 NameNode 同步
- Edits:需要引进新的模块 JournalNode 来保证 edtis 的文件的数据一致性
相当于其他机器的NameNode在主机NameNode存活时充当类似于SecondaryNameNode的角色。
怎么让同时只有一台 NameNode 是 active,其他所有的机器的NameNode都是 standby 的
两种策略:
- 手动分配
- 自动分配
SecondaryNameNode 在 HA 架构中并不存在,定期合并 fsimage 和 edtis 的活谁来干
答:由 standby 的 NameNode 来干
如果 NameNode 真的发生了问题,怎么让其他的 NameNode 上位干活
- 手动故障转移
- 自动股炸转移
HDFS-HA手动模式
环境准备
- 修改 IP
- 修改主机名及主机名和 IP 地址的映射
- 关闭防火墙
- ssh 免密登录
- 安装 JDK,配置环境变量等
以上步骤在搭建集群时应该已经做过了,主要是检查一下,降低后续出错概率。
规划集群
1 号服务器 | 2 号服务器 | 3 号服务器 | |
---|---|---|---|
name | hadoop103 | hadoop104 | hadoop105 |
IP | 192.168.64.103 | 192.168.64.104 | 192.168.64.105 |
HDFS | NameNode、DataNode、JournalNode | NameNode、DataNode、JournalNode | NameNode、DataNode、JournalNode |
配置HDFS-HA集群
准备工作
建议在搭建HA集群时将原本的集群拷贝一份,这样如果搭建失败原本的集群仍可继续使用。
我原本的Hadoop位置为:
先拷贝到ha目录下:
新建ha目录:
1
hadoop103@hadoop103:/usr/local$ sudo mkdir ha
修改ha目录权限:
1
hadoop103@hadoop103:/usr/local$ sudo chown hadoop103:hadoop103 ha
将原集群文件拷贝过来
1
hadoop103@hadoop103:/usr/local$ cp -r hadoop/ ha/
这样新的集群文件路径为:
删除data和logs目录:
1 | hadoop103@hadoop103:/usr/local/ha/hadoop$ rm -rf data/ logs/ |
这一步的效果:
修改配置文件
这里的修改是把原本的配置删除,写入下面的配置
core-site.xml
1
2hadoop103@hadoop103:/usr/local/ha/hadoop$ cd etc/hadoop/
hadoop103@hadoop103:/usr/local/ha/hadoop/etc/hadoop$ vim core-site.xmlvim打开文件后,修改
<configuration></configuration>
内的内容,如下:1
2
3
4
5
6
7
8
9
10
11
12
13<configuration>
<!-- 把多个 NameNode 的地址组装成一个集群 myhacluster -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://myhacluster</value>
</property>
<!-- 指定 hadoop 运行时产生文件的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/usr/local/ha/hadoop/data</value>
</property>
</configuration>内容写好后按 esc,再输入
:wq
保存退出。pdfs-site.xml
1
hadoop103@hadoop103:/usr/local/ha/hadoop/etc/hadoop$ vim hdfs-site.xml
vim打开文件后,修改
<configuration></configuration>
内的内容,如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90<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>myhacluster</value>
</property>
<!-- 集群中 NameNode 节点都有哪些 -->
<property>
<name>dfs.ha.namenodes.myhacluster</name>
<value>nn1,nn2,nn3</value>
</property>
<!-- NameNode 的 RPC 通信地址 -->
<property>
<name>dfs.namenode.rpc-address.myhacluster.nn1</name>
<value>hadoop103:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.myhacluster.nn2</name>
<value>hadoop104:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.myhacluster.nn3</name>
<value>hadoop105:8020</value>
</property>
<!-- NameNode 的 http 通信地址 -->
<property>
<name>dfs.namenode.http-address.myhacluster.nn1</name>
<value>hadoop103:9870</value>
</property>
<property>
<name>dfs.namenode.http-address.myhacluster.nn2</name>
<value>hadoop104:9870</value>
</property>
<property>
<name>dfs.namenode.http-address.myhacluster.nn3</name>
<value>hadoop105:9870</value>
</property>
<!-- 指定 NameNode 元数据在 JournalNode 上的存放位置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hadoop103:8485;hadoop104:8485;hadoop105:8485/myhacluster</value>
</property>
<!-- 访问代理类:client 用于确定哪个 NameNode 为 Active -->
<property>
<name>dfs.client.failover.proxy.provider.myhacluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 关闭检查权限 -->
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
<!-- 配置隔离机制,即同一时刻只能有一台服务器对外响应 -->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
<value>shell(true)</value>
</property>
<!-- 使用隔离机制时需要 ssh 秘钥登录-->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop103/.ssh/id_rsa</value>
</property>
</configuration>
分发ha目录下的hadoop文件
分别在hadoop104、hadoop105下创建ha目录并修改权限
hadoop104:
1
2hadoop104@hadoop104:/usr/local$ sudo mkdir ha
hadoop104@hadoop104:/usr/local$ sudo chown hadoop104:hadoop104 hahadoop105:
1
2hadoop105@hadoop105:/usr/local$ sudo mkdir ha
hadoop105@hadoop105:/usr/local$ sudo chown hadoop105:hadoop105 ha在hadoop103上执行分发脚本命令
如果你还没有集群分发脚本命令,可参看:集群分发脚本
1
hadoop103@hadoop103:/usr/local/ha$ xsync hadoop/
最好再到hadoop104、hadoop105查看是否分发成功。
分发成功后有一个地方需要修改:
在hdfs-site.xml文件的最后:
1 | <!-- 使用隔离机制时需要 ssh 秘钥登录--> |
这里的/home/hadoop103/.ssh/id_rsa
需要修改。
- hadoop104修改为
/home/hadoop104/.ssh/id_rsa
- hadoop105修改为
/home/hadoop105/.ssh/id_rsa
启动HDFS-HA集群
注意,启动前先关闭原本的hadoop集群
先去修改环境变量:
1
vim ~/.bashrc
将 HADOOP_HOME 部分改为如下(其实就是把原本的/usr/local/hadoop改成/usr/local/ha/hadoop):
1
2
3
4#HADOOP_HOME
export HADOOP_HOME=/usr/local/ha/hadoop
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin内容修改好后按 esc,再输入
:wq
保存退出。环境变量生效:
1
source ~/.bashrc
注意:三台机器都要这样修改,否则集群启动时可能会调用原本集群的配置。
启动JournalNode服务
hadoop103:
1
hadoop103@hadoop103:/usr/local/ha/hadoop$ hdfs --daemon start journalnode
hadoop104:
1
hadoop104@hadoop104:/usr/local/ha/hadoop$ hdfs --daemon start journalnode
hadoop105:
1
hadoop105@hadoop105:/usr/local/ha/hadoop$ hdfs --daemon start journalnode
在初次启动时有这样的警告:
1
WARNING: /usr/local/ha/hadoop/logs does not exist. Creating.
这个不用管它,它说的是没有logs文件(本来就还没有,它提示它创建了)
启动好后检查一下:
在 nn1 (hadoop103) 上格式化hadoop,并启动
1
2hadoop103@hadoop103:/usr/local/ha/hadoop$ hdfs namenode -format
hadoop103@hadoop103:/usr/local/ha/hadoop$ hdfs --daemon start namenode检查一下是否启动:
在 nn2(hadoop104)和nn3(hadoop105)上,同步nn1的元数据信息
执行前一定要先启动nn1——NameNode
hadoop104:
1
hadoop104@hadoop104:/usr/local/ha/hadoop$ hdfs namenode -bootstrapStandby
hadoop105:
1
hadoop105@hadoop105:/usr/local/ha/hadoop$ hdfs namenode -bootstrapStandby
启动 nn2 和 nn3:
hadoop104:
1
hadoop104@hadoop104:/usr/local/ha/hadoop$ hdfs --daemon start namenode
hadoop105:
1
hadoop105@hadoop105:/usr/local/ha/hadoop$ hdfs --daemon start namenode
检查是否启动成功:
如图则成功。
查看web页面
访问 http://hadoop103:9870 、 http://hadoop104:9870 、 http://hadoop105:9870
如图可以看出:
- hadoop103、hadoop104、hadoop105都是standby的状态。
- 可以看到集群名称空间为:myhacluster,是我们想要设置的。
- Namenode ID:分别也是nn1、nn2、nn3。
- 同样还有其他信息,可以检查。
所有服务器启动datanode
hadoop103:
1
hadoop103@hadoop103:/usr/local/ha/hadoop$ hdfs --daemon start datanode
hadoop104:
1
hadoop104@hadoop104:/usr/local/ha/hadoop$ hdfs --daemon start datanode
hadoop105:
1
hadoop105@hadoop105:/usr/local/ha/hadoop$ hdfs --daemon start datanode
启动后检查是否成功启动:
将 nn1 切换为 Active
1
hadoop103@hadoop103:/usr/local/ha/hadoop$ hdfs haadmin -transitionToActive nn1
此时查看hadoop103的web端:http://hadoop103:9870
可以看到状态已经变成Active了。
也可以通过命令查看是否为Active:
1
hadoop103@hadoop103:/usr/local/ha/hadoop$ hdfs haadmin -getServiceState nn1
结果如图:
也可验证状态修改成功。
HDFS-HA自动模式
HDFS- HA自动故障转移工作机制
自动故障转移为 HDFS 部署增加了两个新组件:ZooKeeper 和 ZKFailoverController(ZKFC)
Zookeeper集群搭建参看:搭建Zookeeper集群
如图所示:
ZooKeeper 是维护少量协调数据,通知客户端这些数据的改变和监视客户端故障的高可用服务。
HDFS-HA自动故障转移的集群配置规划
1 号服务器 | 2 号服务器 | 3 号服务器 | |
---|---|---|---|
name | hadoop103 | hadoop104 | hadoop105 |
IP | 192.168.64.103 | 192.168.64.104 | 192.168.64.105 |
HDFS | NameNode、DataNode、JournalNode、Zookeeper、ZKFC | NameNode、DataNode、JournalNode、Zookeeper、ZKFC | NameNode、DataNode、JournalNode、Zookeeper、ZKFC |
HDFS-HA自动故障转移
修改配置
注意:一下修改配置都是在原配置文件中添加以下内容。
hdfs-site.xml
1
2
3
4
5<!-- 启用 nn 故障自动转移 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>core-site.xml
1
2
3
4
5<!-- 指定 zkfc 要连接的 zkServer 地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>hadoop103:2181,hadoop104:2181,hadoop105:2181</value>
</property>
利用分发脚本分发配置:
1
hadoop103@hadoop103:/usr/local/ha/hadoop$ xsync etc/hadoop/hdfs-site.xml etc/hadoop/core-site.xml
hadoop104和hadoop105的hdfs-site.xml中需要修改内容:
1
2
3
4
5<!-- 使用隔离机制时需要 ssh 秘钥登录-->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop103/.ssh/id_rsa</value>
</property>这里的
/home/hadoop103/.ssh/id_rsa
需要修改。- hadoop104修改为
/home/hadoop104/.ssh/id_rsa
- hadoop105修改为
/home/hadoop105/.ssh/id_rsa
启动
启动前先关闭所有的HDFS服务:
1
hadoop105@hadoop105:/usr/local/ha/hadoop$ myhadoop stop
检查是否成功关闭:
启动Zookeeper集群
Zookeeper集群搭建参看:搭建Zookeeper集群
1
hadoop103@hadoop103:~$ zk start
检查启动状态:
成功启动Zookeeper后,再初始化HA在Zookeeper中的状态:
1
hadoop103@hadoop103:~$ hdfs zkfc -formatZK
启动HDFS服务:
1
hadoop103@hadoop103:~$ start-dfs.sh
启动后检查一下状态:
去zkCli(Zookeeper的客户端)查看NameNode选举锁节点的内容:
1
hadoop103@hadoop103:~$ $ZOOKEEPER_HOME/bin/zkCli.sh
客户端中输入
get -s /hadoop-ha/myhacluster/ActiveStandbyElectorLock
查看集群选举状态:从
myhaclusternn3 hadoop105
可以看出:选举的Active节点是集群中的nn3节点,即hadoop105。可分别访问http://hadoop103:9870、http://hadoop104:9870、http://hadoop105:9870
检查后的确如此(我这里就不贴图了)。
验证是否可以故障转移
通过
jpsall
命令查看所有进程的进程号:这里可以看到hadoop105中的NameNode的进程号为:26598。
结束这个进程(在hadoop105中):
1
hadoop105@hadoop105:~$ kill -9 26598
此时jpsall查看后hadoop105的NameNode服务就停止了。再次查看新的Active节点是谁(重复上一步的步骤)结果为:
从
myhaclusternn1 hadoop103
可以看出,新选举出的Active节点是集群中的nn1,即hadoop103。这样就可以验证自动故障转移成功了。当然也可以去Web端查看验证:分别访问:http://hadoop103:9870、http://hadoop104:9870、http://hadoop105:9870
理论情况就是hadoop103的状态变为Active、hadoop104还是StandBy、hadoop105访问不上。
YARN-HA集群搭建
YARN-HA核心问题
- 如果当前 active ResourceManager 挂了,怎么将其他 standby ResourceManager 上位?
答:核心原理跟 hdfs 一样,利用了 Zookeeper 的临时节点。 - 当前 ResourceManager 上有很多的计算程序在等待运行,其他的 ResourceManager 怎么将这些程序接手过来接着跑?
答:ResourceManager 会将当前的所有计算程序的状态存储在 Zookeeper 中,其他 ResourceManager 上位后会去读取,然后接着跑。
YARN-HA规划集群
1 号服务器 | 2 号服务器 | 3 号服务器 | |
---|---|---|---|
name | hadoop103 | hadoop104 | hadoop105 |
IP | 192.168.64.103 | 192.168.64.104 | 192.168.64.105 |
YARN | NodeManager、ResourceManager | ResourceManager、NodeManager | NodeManager、ResourceManager |
YARN-HA具体配置
在hadoop103上修改yarn-site.xml文件内容:
1 | hadoop103@hadoop103:/usr/local/ha/hadoop/etc/hadoop$ vim yarn-site.xml |
将yarn-site.xml文件内容修改为:
1 | <configuration> |
按esckbd>之后输入:wq
保存退出。
将配置文件分发出去:
1 | hadoop103@hadoop103:/usr/local/ha/hadoop/etc/hadoop$ xsync yarn-site.xml |
启动YARN
在hadoop103下执行:
在启动前一定要先启动 Zookeeper 集群
1
hadoop103@hadoop103:/usr/local/ha/hadoop$ start-yarn.sh
查看启动情况:
查看服务状态:
1
hadoop103@hadoop103:/usr/local/ha/hadoop$ yarn rmadmin -getServiceState rm1
结果为:standby。
1
hadoop103@hadoop103:/usr/local/ha/hadoop$ yarn rmadmin -getServiceState rm2
结果为:active。
1
hadoop103@hadoop103:/usr/local/ha/hadoop$ yarn rmadmin -getServiceState rm3
结果为:standby。
整体如图:
去Zookeeper客户端查看ResourceManager选举锁节点内容:
1
hadoop103@hadoop103:/usr/local/ha/hadoop$ $ZOOKEEPER_HOME/bin/zkCli.sh
输入:
get -s /yarn-leader-election/cluster-yarn1/ActiveStandbyElectorLock
效果如图:
从
cluster-yarn1rm2
可以看出:当前YARN-HA集群多Active节点为rm2。web端查看YARN的状态
访问:http://hadoop103:8088、http://hadoop104:8088、http://hadoop105:8088
总结
两者都搭建好后就是Hadoop-HA集群了,即Hadoop高可用集群。
搭建好后集群最终效果:
1 号服务器 | 2 号服务器 | 3 号服务器 | |
---|---|---|---|
name | hadoop103 | hadoop104 | hadoop105 |
IP | 192.168.64.103 | 192.168.64.104 | 192.168.64.105 |
HDFS | NameNode、DataNode、JournalNode、Zookeeper、ZKFC | NameNode、DataNode、JournalNode、Zookeeper、ZKFC | NameNode、DataNode、JournalNode、Zookeeper、ZKFC |
YARN | NodeManager、ResourceManager | ResourceManager、NodeManager | NodeManager、ResourceManager |