在Hadoop架构中提供了三类搭建方式,第一类是给测试或开发人员使用的伪分布式或单NN节点搭建方式,第二类是用来商用化并解决NN单点故障的HA搭建方式,第三类就是这里要说的联邦模式,它本身也是一种供给商用的模式,但是它的应用在国内不多,它是用来解决HA单ActionNN压力问题的,在技术顶设上,一个Hadoop集群内部同一时间只允许存在一个生效的NN,但是当你的数据量非常庞大,庞大到你的DataNode资源已经不能用海量形容的地步时,你觉得一个NN能够提供稳定可行的元数据维护吗?同时这也是为什么这个模式国内用的很少的原因,因为能够有这种规模集群的公司一只手数的过来,就那几家。比如李老板家有款外部数据服务叫BOS,当时博主在李老板公司里面做牛马的时候,对自己人都限速,限速真的成了李老板家的传统了,靠背。
联邦模式,它是依靠Hadoop提供的ViewFS组件,这个组件自身提供了一个树根节点,并允许多个Hadoop集群,已分支节点的形式挂在这个根节点上组成一个更大的Hadoop集群视图关系网,而且一个分支节点下可以有多个hadoop集群,这些集群被视为命名空间存在,所有在联邦中的Hadoop之间横向分摊了元数据存储压力,当然这里说的分摊并不是数据块切片那样的分摊,而是每一个根节点下的命名空间,由ViewFS提供转发的能力,让跨集群存储以及访问数据能够更加简单和透明,注意你可以在任何一个NN上访问到整个联邦中的数据,因为元数据层面虽然是水平分摊的,但是集群中所有的DataNode是共享的。
配置Hadoop联邦模式你只需要在原来的单一集群基础上修改如下配置即可,但是注意
配置的时候需要格式化hdfs,所以要不是新集群,就要考虑数据备份。
本篇只介绍联邦和单一集群搭建不同的配置,至于相同的就不再展示了,这里给大家提供我之前发的大家文档
Hadoop3.x==》https://blog.csdn.net/dudadudadd/article/details/139547748
Hadoop2.x==》https://blog.csdn.net/dudadudadd/article/details/109858613
第一步:修改所有集群的core-site.xml
文件。单一的hadoop集群在namenode访问上通常只有如下的配置
bash
<property>
<name>fs.defaultFS</name>
<value>hdfs://hdp</value>
</property>
这个配置在一开始说的三种搭建类型中的前两种中,是一个hdfs前缀的访问路径,意在告诉客户端hdfs访问入口,而在联邦模式中他要改成如下设置,用来关联viewfs(根节点)-分支-命名空间
之间的联系
xml
<property>
<name>fs.defaultFS</name>
<value>viewfs:///</value>
</property>
<property>
<name>fs.viewfs.mounttable.default.link./nameservice01</name>
<value>hdfs://bi/</value>
</property>
<property>
<name>fs.viewfs.mounttable.default.link./nameservice02</name>
<value>hdfs://dt/</value>
</property>
对与上面的这个配置要注意的点如下:
- fs.defaultFS配置值改为viewfs前缀的一个路径,告诉hadoop你要启用联邦视图组件,并指定默认访问的入口,也就是默认去那个根节点的分支下找数据,这一点和之前的搭建方式差别不大,如上配置中的
viewfs:///
指不特意指定某个分支,既默认访问default,如果你要指定则改为viewfs://视图分支/
,注意后期在访问一个不存在的资源会报错。 - fs.viewfs.mounttable.default.link./nameservice01配置值的格式是固定的,就和配置NN或RM组时类似,
fs.viewfs.mounttable.视图分支.link./命名空间
,视图分支按照实际需求直接在配置中书写既视为定义,不需要像NN那样提前定义名称之类的,属于随用随写,至于命名空间也不是说要和配置项中hdfs路径后面的一样,它起到的作用是后期使用的时候,hadoop转发的依据,因此业内为了方便使用才写成一样的,就是说在后期使用的时候完整的数据访问路径是viewfs://分支/命名空间/文件路径
,所以配置项中的./nameservice02
和下面路径中的hdfs://dt/
不是非要一样,./nameservice02
是viewfs内部的视图内容,一定不要混淆。但是hdfs://dt/中的dt必须是你后面配置hdfs是的NN服务器名,这个不能不一样
第二步:去修改所有节点的hdfs-site.xml
,单独的Hadoop集群中对于NameNode的配置是以主副HA组成的一组nameservices实现的,就像下面这样
xml
<property>
<name>dfs.nameservices</name>
<value>hdp</value>
</property>
。。。。省略对应的高可用配置项
而在联邦模式中你需要让每一个集群知道它所在联邦中所有的NN,比如如下配置
xml
<property>
<name>dfs.nameservices</name>
<value>bi,dt</value>
</property>
<!-- bi下面有两个NameNode,分别是nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.bi</name>
<value>nn1,nn2</value>
</property>
<!-- dt下面有两个NameNode,分别是nn3,nn4 -->
<property>
<name>dfs.ha.namenodes.dt</name>
<value>nn3,nn4</value>
</property>
<!-- nn1的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.bi.nn1</name>
<value>mini01:9000</value>
</property>
<!-- nn1的http通信地址 -->
<property>
<name>dfs.namenode.http-address.bi.nn1</name>
<value>mini01:50070</value>
</property>
<!-- nn2的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.bi.nn2</name>
<value>mini02:9000</value>
</property>
<!-- nn2的http通信地址 -->
<property>
<name>dfs.namenode.http-address.bi.nn2</name>
<value>mini02:50070</value>
</property>
<!-- nn3的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.dt.nn3</name>
<value>mini03:9000</value>
</property>
<!-- nn3的http通信地址 -->
<property>
<name>dfs.namenode.http-address.dt.nn3</name>
<value>mini03:50070</value>
</property>
<!-- nn4的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.dt.nn4</name>
<value>mini04:9000</value>
</property>
<!-- nn4的http通信地址 -->
<property>
<name>dfs.namenode.http-address.dt.nn4</name>
<value>mini04:50070</value>
</property>
<!-- 配置失败自动切换实现方式 -->
<property>
<name>dfs.client.failover.proxy.provider.bi</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.dt</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 注意上面的配置是联邦中所有集群都要有的,而且本身也需要为不同角色配置,但是其他本身是集群公用的,但却又独属于这个集群的配置,则要分集群去写,比如下面的配置 -->
<!-- 指定NameNode的edits元数据在JournalNode上的存放位置 -->
<!-- 在bi命名空间的集群中用如下配置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://JournalNode地址/bi</value>
</property>
<!-- 在dt名称空间的集群中用如下配置 # 在bi集群中注释掉 -->
<!--
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://mini05:8485;mini06:8485;mini07:8485/dt</value>
</property>
-->
<!-- 至于其他的集群公用配置,又不属于某个集群独属的配置则不需要变 -->
<!-- 指定JournalNode在本地磁盘存放数据的位置 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/app/hadoop/journaldata</value>
</property>
<!-- 开启NameNode失败自动切换 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行-->
<!-- 其中shell(/bin/true) 表示可执行一个脚本 比如 shell(/app/yunwei/hadoop_fence.sh) -->
<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>/app/.ssh/id_rsa</value>
</property>
<!-- 配置sshfence隔离机制超时时间 单位:毫秒 -->
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>
第三步:确定所有的集群中RM和历史日志服务器指定的是一套,因为联邦中的计算资源是共享的
第四步:随着架构版本的不同,你需要去更改slaves或workers文件,这里面要包含整个联邦所有的node节点,说白了就是单集群的时候只需要有自己集群的就行,但是联邦集群因为底层计算和存储资源是共享的所以和NN配置的时候类似的操作,要让所有集群知道联邦中所有的计算和存储资源是谁
集群其他的配置不需要变,原来什么样,现在就什么样,注意我的意思是其他配置任然保持对一个集群自己负责就行,不需要考虑联邦因素,所以你自己按照自己的实际情况是调整
第五步:开始格式化集群
- 确保zk是启动的
- 在联邦中我们配置文件中写的journalnode所在节点上,运行命令启动对应服务
hadoop-daemon.sh start journalnode
,单一的集群我们一般不关注启动节点的,但是联邦中集群不止有一个。 - 依次在每个集群上格式化主备NN,格式化的时候注意,所有集群必须指定同一个集群ID,也就是说命令为
hdfs namenode -format -clusterID CID-8c9c1d4b-5aa3-4d12-b717-31a56884da7f
,后面的UUID找个生成UUID的网站生产一个就行,还有不要在这一步的时候备份主NN,因为联邦的Hadoop启动的时候是所有的NN都会启动,所以先把主NN那一套格式化搞完,让主NN启动起来之后再备份 - 格式化zkfc也和NN一样,在每个集群上依次执行
hdfs zkfc -formatZK
,不过初始化每个集群自己的zkfc就行,没有特殊配置,就是说每个集群各自在主NN上运行格式化zkfc - 在任何一个NN上启动hdfs,执行一次
start-dfs.sh
就行,会启动整个联邦的NN,这一步启动了主NN之后,再去备份备用NN - 在整个联邦指定的RM上启动yarn
start-yarn.sh
第一次因为涉及到格式化所以严格按照上面的步骤来,后面启动就和单集群没差别了,也是zk-hdfs-yarn-其他服务
在格式化的第5点,启动hdfs之后,留意一下输出日志,按照写本文是用的测试集群来说正常情况下会启动4个NN、6个DN、2个zkfc、3个journal,也就是如下的输出
bash
[root@node1 hadoop]# start-dfs.sh
Starting namenodes on [node1 node2 node4 node5]
node1: starting namenode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-namenode-node1.out
node4: starting namenode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-namenode-node4.out
node5: starting namenode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-namenode-node5.out
node2: starting namenode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-namenode-node2.out
node5: starting datanode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-datanode-node5.out
node1: starting datanode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-datanode-node1.out
node4: starting datanode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-datanode-node4.out
node2: starting datanode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-datanode-node2.out
node6: starting datanode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-datanode-node6.out
node3: starting datanode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-datanode-node3.out
Starting journal nodes [node1 node2 node3]
node1: starting journalnode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-journalnode-node1.out
node3: starting journalnode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-journalnode-node3.out
node2: starting journalnode, logging to /opt/hadoop-2.7.2/logs/hadoop-root-journalnode-node2.out
Starting ZK Failover Controllers on NN hosts [node1 node2 node4 node5]
node1: starting zkfc, logging to /opt/hadoop-2.7.2/logs/hadoop-root-zkfc-node1.out
node2: starting zkfc, logging to /opt/hadoop-2.7.2/logs/hadoop-root-zkfc-node2.out
node4: starting zkfc, logging to /opt/hadoop-2.7.2/logs/hadoop-root-zkfc-node4.out
node5: starting zkfc, logging to /opt/hadoop-2.7.2/logs/hadoop-root-zkfc-node5.out
至于初始化第6点的yarn,启动之后也要关注一下,因为有些时候备用的RM不跟随着交互启动,需要自己启动一下
最后通过web页面就可以看到整个集群的资源了,而且访问四个NN,会发现有两个生效的
最后你要测试一下联邦的相关能力是否正常,首先访问任意一个生效的NN的Web文件系统页面,正常情况下刚开始是什么也没有的,如下
但是,你通过客户端查询根路径,你会发现客户端可以打印出命名空间开头的路径
bash
[root@node1 hadoop-2.7.2]# hadoop fs -ls /
Found 2 items
-r-xr-xr-x - root root 0 2024-08-24 12:02 /nameservice01
-r-xr-xr-x - root root 0 2024-08-24 12:02 /nameservice02
此后,用客户端操作数据的时候就必须加上正确的命名空间前缀,不然就会提示你不符合联邦试图,如下
bash
[root@node1 hadoop-2.7.2]# hadoop fs -mkdir /test01
mkdir: InternalDir of ViewFileSystem is readonly; operation=mkdirsPath=/test01
[root@node1 hadoop-2.7.2]# hadoop fs -ls /
Found 2 items
-r-xr-xr-x - root root 0 2024-08-24 12:06 /nameservice01
-r-xr-xr-x - root root 0 2024-08-24 12:06 /nameservice02
[root@node1 hadoop-2.7.2]# hadoop fs -mkdir /nameservice01/test01
[root@node1 hadoop-2.7.2]#
同时在web上不会显示命名空间,因为对与web来说,所有NN之间共享了元数据信息,虽然底层会去交互数据信息,但在页面上只会展示所有的数据路径,也就是不带命名空间的路径
同样的,其他第三方访问hdfs数据也要带上前缀,比如写代码之类的,并且要注意我上面的配置是挂载在了联盟默认分支上,因此我的访问路径不用带分支,但完整的路径因该是viewfs://分支/命名空间/文件路径
,但是一般来讲按照正常的访问高可用集群NN的方式访问也是可以的