一、namenode高可用:
namenode存储了数据和地址的映射(fsimage),当节点发生故障的时候,
备份节点应该和故障节点具有相同的数据,因此有两种方式实现高可用。
1、使用NFS:将数据放在一个共享的目录下。
2、使用QJM:准备两台namenode,一个用于备份,
datanode向namenode回复数据与地址的映射时,
不仅向namenode回复,也要向备份的namenode回复。
两个namenode节点,一个处于活跃状态(active)用于处理请求,(active仅有一个)
另外一个namenode节点处于备份状态(standby)仅备份数据。
active节点是通过zookeeper选举出来的。
fsedits数据变更日志的备份(同步):active向JNS(JournalNodes)中写数据,standby从JNS中读数据。
二、yarn高可用:(resourcemanager)
原理和namenode高可用相同。
也要使用zookeeper集群
三、高可用配置:
1、主机准备:
192.168.1.60 nn01 角色:namenode、resourcemanager
192.168.1.66 nn02 角色:namenode、resourcemanager
192.168.1.61 node1 角色:datanode、zookeeper、journalnode
192.168.1.62 node2 角色:datanode、zookeeper、journalnode
192.168.1.63 node3 角色:datanode、zookeeper、journalnode
# 保证nn01连接所有主机都不需要密码(包括本机)
# 保证nn02连接node1、node2、node3、nn02不需要密码
# 修改/etc/hosts,同步到所有主机
2、修改配置文件(在nn01上执行,然后同步到所有主机):
①、core-site.xml
vim /usr/local/hadoop/etc/hadoop/core-site.xml
<configuration>
<!-- 核心配置文件 -->
<!-- http://hadoop.apache.org/docs/r2.7.7/hadoop-project-dist/hadoop-common/core-default.xml 找对应参数 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://namenodeGroup</value>
<!--
由于由两个namenode,active(活动节点)是被选举出来的,
需要把两个namenode定义成一个组,这里写namenode组的名字
-->
<!-- <description> 使用什么样的存储,file:///表示本地存储,配置伪分布式;hdfs://nameNode的ip </description> -->
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/var/hadoop</value>
<!-- <description> hadoop核心数据存储目录,一般是单独的磁盘所挂载的目录 </description> -->
</property>
<property>
<!-- zookeeper集群的地址,配3个,自动连接第一个,如果出现问题自动连接下一个 -->
<name>ha.zookeeper.quorum</name>
<value>node1:2181,node2:2181:node3:2181</value>
</property>
<property>
<!-- nfs代理用户的组,nfsuser是设置的代理用户 -->
<name>hadoop.proxyiser.nfsuser.groups</name>
<value>*</value>
</property>
<property>
<!-- nfs代理用户的主机,nfsuser是设置的代理用户 -->
<name>hadoop.proxyiser.nfsuser.hosts</name>
<value>*</value>
</property>
</configuration>
②、hdfs-site.xml
vim /usr/local/hadoop/etc/hadoop/hdfs-site.xml
<configuration>
<!-- HDFS配置文件 -->
<!-- http://hadoop.apache.org/docs/r2.7.7/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml 找对应参数 -->
<property>
<!-- 定义,namenode组的名称,core-site.xml中使用就在这里定义 -->
<name>dfs.nameservices</name>
<value>namenodeGroup</value>
</property>
<property>
<!-- 定义namenodeGroup组中的角色,相当于为主机起的名字 -->
<name>dfs.ha.namenodes.namenodeGroup</name>
<value>nn1,nn2</value> <!-- 角色名,自定义 -->
</property>
<property>
<!-- 定义角色对应的主机 角色nn1对应nn01主机 -->
<name>dfs.namenode.rpc-address.namenodeGroup.nn1</name>
<value>nn01:8020</value> <!-- 角色对应的主机以及端口 -->
</property>
<property>
<!-- 定义角色对应的主机 角色nn2对应nn02主机 -->
<name>dfs.namenode.rpc-address.namenodeGroup.nn2</name>
<value>nn02:8020</value> <!-- 角色对应的主机以及端口 -->
</property>
<property>
<!-- 定义namenode,nn1对应的主机的namenode是nn01的50070 -->
<name>dfs.namenode.http-address.namenodeGroup.nn1</name>
<value>nn01:50070</value>
</property>
<property>
<!-- 定义namenode,nn2对应的主机的namenode是nn02的50070 -->
<name>dfs.namenode.http-address.namenodeGroup.nn2</name>
<value>nn02:50070</value>
</property>
<property>
<!-- JNS,用于同步fsedits数据变更日志 -->
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://node1:8485;node2:8485;node3:8485/fsedits_log</value>
</property>
<property>
<!-- 保存数据变更日志的目录 -->
<name>dfs.journalnode.edits.dir</name>
<value>/var/hadoop/journal</value>
</property>
<property>
<!-- 高可用软件,zookeeperFailoverController -->
<name>dfs.client.failover.proxy.provider.namenodeGroup</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
<!-- 管理standby备份主机的方法,ssh -->
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<!-- 秘钥存放位置 -->
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>
<property>
<!-- 故障时,是否自主切换主从 -->
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.replication</name>
<value>3</value>
<!-- <description> 副本策略,数据存几份,3份中有2份备份数据 </description> -->
</property>
<property>
<!-- 为了删除datanode节点, 写在这个文件中的主机在删除前会自动迁移数据-->
<name>dfs.hosts.exclude</name>
<value>/usr/local/hadoop/etc/hadoop/exclude</value>
</property>
</configuration>
③、yarn-site.xml
vim /usr/local/hadoop/etc/hadoop/yarn-site.xml
<configuration>
<!-- Map-Reduce配置文件 -->
<!-- http://hadoop.apache.org/docs/r2.7.7/hadoop-yarn/hadoop-yarn-common/yarn-default.xml 找对应参数 -->
<property>
<!-- 开启resourcemanager高可用 -->
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<property>
<!-- 定义两个角色,代表不同的resourcemanager主机 -->
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<property>
<!-- resourcemanager故障时自动切换 -->
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
<property>
<!-- resourcemanager使用管理软件 -->
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
<property>
<!-- 指定zookeeper集群 -->
<name>yarn.resourcemanager.zk-address</name>
<value>node1:2181,node2:2181,node3:2181</value>
</property>
<property>
<!-- resourcemanager集群的id -->
<name>yarn.resourcemanager.cluster-id</name>
<value>yarn-ha</value>
</property>
<property>
<!-- 定义角色对应的主机 -->
<name>yarn.resourcemanager.hostname.rm1</name>
<value>nn01</value>
</property>
<property>
<!-- 定义角色对应的主机 -->
<name>yarn.resourcemanager.hostname.rm2</name>
<value>nn02</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value> <!-- 官方提供的框架 -->
<!-- <description> nodemanager使用什么计算框架,计算框架的名称,问开发人员所使用的框架是什么 </description> -->
</property>
</configuration>
# 同步到nn02、node1、node2、node3上
for i in {61..63} 66; do rsync -aSH --delete /usr/local/hadoop/ 192.168.1.$i:/usr/local/hadoop -e 'ssh' & done
3、验证
# 启动zookeeper集群(node1、node2、node3都要进行操作)
/usr/local/zookeeper/bin/zkServer.sh start
# 初始化zookeeper集群(在nn01上操作)
/usr/local/hadoop/bin/hdfs zkfc -formatZK # 出现Successfully即为成功
# 启动journalnode服务(在node1、node2、node3上操作)
/usr/local/hadoop/sbin/hadoop-daemon.sh start journalnode
# 格式化journalnode(在nn01上执行,先启动才可以初始化)
/usr/local/hadoop//bin/hdfs namenode -format # 出现Successfully即为成功
# 为了保证nn01和nn02的数据完全一致,需要将nn01的数据同步到nn02(我这里是在nn02上进行的操作)
rsync -aSH nn01:/var/hadoop/ /var/hadoop/
# 初始化JNS(nn01上操作)
/usr/local/hadoop/bin/hdfs namenode -initializeSharedEdits # 出现Successfully即为成功
# 停止 journalnode 服务(node1、node2、node3)
/usr/local/hadoop/sbin/hadoop-daemon.sh stop journalnode
# 启动hadoop集群(在nn01上操作)
/usr/local/hadoop/sbin/start-all.sh
# 启动resourcemanager热备(nn02上操作)
/usr/local/hadoop/sbin/yarn-daemon.sh start resourcemanager
# 查看集群状态(nn01上执行)
# namenode、resourcemanager的active和standby都是选举产生的
/usr/local/hadoop/bin/hdfs haadmin -getServiceState nn1 # namenode
/usr/local/hadoop/bin/hdfs haadmin -getServiceState nn2
/usr/local/hadoop/bin/yarn rmadmin -getServiceState rm1 # resourcemanager
/usr/local/hadoop/bin/yarn rmadmin -getServiceState rm2
# 查看节点是否加入
/usr/local/hadoop/bin/hdfs dfsadmin -report
/usr/local/hadoop/bin/yarn node -list
这里假设nn01是namenode和resourcemanager的active节点
关闭nn01上对应的服务服务(模拟故障),则nn02会变成active
如果nn01故障恢复,则nn01则变为standby