NameNode 高可用
- NameNode 是HDFS的核心配置,HDFS又是Hadoop的核心组件,NameNode在Hadoop集群中至关重要
- namenode机器宕机,将导致集群不可用,如果namenode数据丢失将的导致整个集群的数据丢失,
- 而namenode的数据更新由比较频繁,所以必须使用namenode高可用
NameNode 高可用两种方案
-
HDFS with NFS
-
HDFS with QJM
HA方案对比
-
都能实现热备
-
都是一个Active NN 和一个 Standby NN
-
都使用 Zookeeper 和 ZKFC 来实现自动失效恢复
-
失效切换都使用 Fencing 配置的方法来active NN
-
NFS 数据共享变更方案把数据存储在共享存储里面,我们还需要考虑NFS的高可用
-
QJM 不需要共享存储,但需要让每一个 DN 都知道两个 NN 的位置,并把块信息和心跳包发送给 Active 和 Standby 这两个 NN
NameNode 高可用(QJM)方案
-
为了解决 NameNode 单点故障,Hadoop 给出了 HDFS 的高可用HA方案:HDFS 通常有两个 NameNode 组成,一个处于 Active 状态,
另一个处于 Standby 状态。ActiveNameNode 对外提供服务,比如处理来自客户端的 RPC 请求,而 StandbyNameNode 则不对外
提供服务,仅同步 ActiveNameNode 的状态,以便能够在它失败时进行切换。 -
为了让 StandbyNode 与 ActiveNode 保持同步,这两个 Node 都与一组称为 JNS 的互相独立的进程保持通信(Journal Node)
当 ActiveNode 上更新了 NameSpace,它将会从 JNS 中读取这个 edits,并持续关注他们对日志的变更,StandbyNode 将日志变更
应用在自己的 NameSpace 中,当 Failover 发生时,Santdby 将会在提升自己为 Active 之前,确保能够从 JNS 中读取所有的edits,
即在 failover 发生之前 Standby 持有的 NameSpace 应该与 Active 保持完全同步 -
还有很重要一点,任何时刻,只有一个 ActiveNameNode,否则将会导致集群操作的混乱,那么两个 NameNode 将会分别有
两种不同的数据状态,可能会导致数据丢失,或者状态异常,这种情况称为 “split-brain” (脑裂,三节点通讯阻断,即集群中
不同的 DataNode 看到了不同的 ActiveNameNode)。对于 JNS 而言,任何时候只允许一个 NameNode 作为 writer;在 failover
期间,原来的 StandbyNode 将会接管 Active 的所有职能,并负责向 JNS 写入日志记录,这种机制阻止了其他NameNode基于处于Active状态的问题。
配置Hadoop的高可用,解决NameNode单点故障问题,使用之前搭建好的hadoop集群
新添加一台nn02,ip为192.168.1.25,之前有一台node4主机,可以用这台主机
步骤一:hadoop的高可用
1)停止所有服务
[root@nn01 ~]# cd /usr/local/hadoop/
[root@nn01 hadoop]# ./sbin/stop-all.sh //停止所有服务
2)启动zookeeper(需要一台一台的启动)这里以nn01为例子
[root@nn01 hadoop]# /usr/local/zookeeper/bin/zkServer.sh start
[root@nn01 hadoop]# sh /usr/local/zookeeper/conf/api.sh //利用之前写好的脚本查看
node1 follower
node2 leader
node3 follower
nn01 observer
3)新加一台机器nn02,这里之前有一台node4,可以用这个作为nn02
[root@node4 ~]# echo nn02 > /etc/hostname
[root@node4 ~]# hostname nn02
4)修改vim /etc/hosts
[root@nn01 hadoop]# vim /etc/hosts
192.168.1.21 nn01
192.168.1.25 nn02
192.168.1.22 node1
192.168.1.23 node2
192.168.1.24 node3
5)同步到nn02,node1,node2,node3
[root@nn01 hadoop]# for i in {22..25}; do rsync -aSH --delete /etc/hosts 192.168.1.$i:/etc/hosts -e 'ssh' & done
6)配置SSH信任关系
注意:nn01和nn02互相连接不需要密码,nn02连接自己和node1,node2,node3同样不需要密码
[root@nn02 ~]# vim /etc/ssh/ssh_config
Host *
GSSAPIAuthentication yes
StrictHostKeyChecking no
[root@nn01 hadoop]# cd /root/.ssh/
[root@nn01 .ssh]# scp id_rsa id_rsa.pub nn02:/root/.ssh/
//把nn01的公钥私钥考给nn02
7)所有的主机删除/var/hadoop/*
[root@nn01 .ssh]# rm -rf /var/hadoop/*
[root@nn01 .ssh]# ssh nn02 rm -rf /var/hadoop/*
[root@nn01 .ssh]# ssh node1 rm -rf /var/hadoop/*
[root@nn01 .ssh]# ssh node2 rm -rf /var/hadoop/*
[root@nn01 .ssh]# ssh node3 rm -rf /var/hadoop/*
8)配置 core-site
[root@nn01 .ssh]# vim /usr/local/hadoop/etc/hadoop/core-site.xml
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://nsdcluster</value>
//nsdcluster是随便起的名。相当于一个组,访问的时候访问这个组
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/var/hadoop</value>
</property>
<property>
<name>ha.zookeeper.quorum</name>
<value>node1:2181,node2:2181,node3:2181</value> //zookeepe的地址
</property>
<property>
<name>hadoop.proxyuser.nfs.groups</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.nfs.hosts</name>
<value>*</value>
</property>
</configuration>
9)配置 hdfs-site
[root@nn01 ~]# vim /usr/local/hadoop/etc/hadoop/hdfs-site.xml
<configuration>
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>dfs.nameservices</name>
<value>nsdcluster</value>
</property>
<property>
<name>dfs.ha.namenodes.nsdcluster</name> //nn1,nn2名称固定,是内置的变量,nsdcluster里面有nn1,nn2
<value>nn1,nn2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.nsdcluster.nn1</name> //声明nn1 8020为通讯端口,是nn01的rpc通讯端口
<value>nn01:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.nsdcluster.nn2</name> //声明nn2是谁,nn02的rpc通讯端口
<value>nn02:8020</value>
</property>
<property>
<name>dfs.namenode.http-address.nsdcluster.nn1</name> //nn01的http通讯端口
<value>nn01:50070</value>
</property>
<property>
<name>dfs.namenode.http-address.nsdcluster.nn2</name> //nn01和nn02的http通讯端口
<value>nn02:50070</value>
</property>
<property>
<name>dfs.namenode.shared.edits.dir</name> //指定namenode元数据存储在journalnode中的路径
<value>qjournal://node1:8485;node2:8485;node3:8485/nsdcluster</value>
</property>
<property>
<name>dfs.journalnode.edits.dir</name> //指定journalnode日志文件存储的路径
<value>/var/hadoop/journal</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.nsdcluster</name> //指定HDFS客户端连接active namenode的java类
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
<name>dfs.ha.fencing.methods</name> //配置隔离机制为ssh
<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>
</configuration>
10)配置yarn-site
[root@nn01 ~]# vim /usr/local/hadoop/etc/hadoop/yarn-site.xml
<configuration>
<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.resourcemanager.ha.enabled</name> //打开HA配置
<value>true</value>
</property>
<property>
<name>yarn.resourcemanager.ha.rm-ids</name> //rm1,rm2代表nn01和nn02
<value>rm1,rm2</value>
</property>
<property>
<name>yarn.resourcemanager.recovery.enabled</name> //打开服务
<value>true</value>
</property>
<property>
<name>yarn.resourcemanager.store.class</name> //存储节点 yarn的resourcemanager在zookeeper上存储信息的一个类
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
<property>
<name>yarn.resourcemanager.zk-address</name> //申明zookeeper服务器
<value>node1:2181,node2:2181,node3:2181</value>
</property>
<property>
<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>
</configuration>
11)同步到nn02,node1,node2,node3
[root@nn01 ~]# for i in {22..25}; do rsync -aSH --delete /usr/local/hadoop/ 192.168.1.$i:/usr/local/hadoop -e 'ssh' & done
12)删除所有机器上面的/user/local/hadoop/logs,方便排错
[root@nn01 ~]# for i in {21..25}; do ssh 192.168.1.$i rm -rf /usr/local/hadoop/logs ; done
13)同步配置
[root@nn01 ~]# for i in {22..25}; do rsync -aSH --delete /usr/local/hadoop 192.168.1.$i:/usr/local/hadoop -e 'ssh' & done
高可用验证
1)初始化ZK集群
[root@nn01 ~]# /usr/local/hadoop/bin/hdfs zkfc -formatZK
...
18/09/11 15:43:35 INFO ha.ActiveStandbyElector: Successfully created /hadoop-ha/nsdcluster in ZK //出现Successfully即为成功
2)在node1,node2,node3上面启动journalnode服务(以node1为例子)
[root@node1 ~]# /usr/local/hadoop/sbin/hadoop-daemon.sh start journalnode
starting journalnode, logging to /usr/local/hadoop/logs/hadoop-root-journalnode-node1.out
[root@node1 ~]# jps
29262 JournalNode
26895 QuorumPeerMain
29311 Jps
3)格式化,先在node1,node2,node3上面启动journalnode才能格式化
[root@nn01 ~]# /usr/local/hadoop//bin/hdfs namenode -format
//出现Successfully即为成功
[root@nn01 hadoop]# ls /var/hadoop/
dfs
4)nn02数据同步到本地 /var/hadoop/dfs
[root@nn02 ~]# cd /var/hadoop/
[root@nn02 hadoop]# ls
[root@nn02 hadoop]# rsync -aSH nn01:/var/hadoop/ /var/hadoop/
[root@nn02 hadoop]# ls
dfs
5)初始化 JNS
[root@nn01 hadoop]# /usr/local/hadoop/bin/hdfs namenode -initializeSharedEdits
18/09/11 16:26:15 INFO client.QuorumJournalManager: Successfully started new epoch 1 //出现Successfully,成功开启一个节点
6)停止 journalnode 服务(node1,node2,node3)
[root@node1 hadoop]# /usr/local/hadoop/sbin/hadoop-daemon.sh stop
[root@node1 hadoop]# jps
29346 Jps
26895 QuorumPeerMain
启动集群
1)nn01上面操作
[root@nn01 hadoop]# /usr/local/hadoop/sbin/start-all.sh //启动所有集群
2)nn02上面操作
[root@nn02 hadoop]# /usr/local/hadoop/sbin/yarn-daemon.sh start resourcemanager
3)查看集群状态
[root@nn01 hadoop]# /usr/local/hadoop/bin/hdfs haadmin -getServiceState nn1
active
[root@nn01 hadoop]# /usr/local/hadoop/bin/hdfs haadmin -getServiceState nn2
standby
[root@nn01 hadoop]# /usr/local/hadoop/bin/yarn rmadmin -getServiceState rm1
active
[root@nn01 hadoop]# /usr/local/hadoop/bin/yarn rmadmin -getServiceState rm2
standby
4)查看节点是否加入
[root@nn01 hadoop]# /usr/local/hadoop/bin/hdfs dfsadmin -report
...
Live datanodes (3): //会有三个节点
...
[root@nn01 hadoop]# /usr/local/hadoop/bin/yarn node -list
访问集群-验证高可用
1)查看并创建
[root@nn01 hadoop]# /usr/local/hadoop/bin/hadoop fs -ls /
[root@nn01 hadoop]# /usr/local/hadoop/bin/hadoop fs -mkdir /aa //创建aa
[root@nn01 hadoop]# /usr/local/hadoop/bin/hadoop fs -ls / //再次 查看
[root@nn01 hadoop]# /usr/local/hadoop/bin/hadoop fs -put *.txt /aa
[root@nn01 hadoop]# /usr/local/hadoop/bin/hadoop fs -ls hdfs://nsdcluster/aa
//也可以这样查看
2)验证高可用,关闭 active namenode
[root@nn01 hadoop]# /usr/local/hadoop/bin/hdfs haadmin -getServiceState nn1
active
[root@nn01 hadoop]# /usr/local/hadoop/sbin/hadoop-daemon.sh stop namenode
[root@nn01 hadoop]# /usr/local/hadoop/bin/hdfs haadmin -getServiceState nn1
//再次查看会报错
[root@nn01 hadoop]# /usr/local/hadoop/bin/hdfs haadmin -getServiceState nn2
//nn02由之前的standby变为active
active
[root@nn01 hadoop]# /usr/local/hadoop/bin/yarn rmadmin -getServiceState rm1
active
[root@nn01 hadoop]# /usr/local/hadoop/sbin/yarn-daemon.sh stop resourcemanager
//停止resourcemanager
[root@nn01 hadoop]# /usr/local/hadoop/bin/yarn rmadmin -getServiceState rm2
active
3) 恢复节点
[root@nn01 hadoop]# /usr/local/hadoop/sbin/hadoop-daemon.sh start namenode
//启动namenode
[root@nn01 hadoop]# /usr/local/hadoop/sbin/yarn-daemon.sh start resourcemanager
//启动resourcemanager
[root@nn01 hadoop]# /usr/local/hadoop/bin/hdfs haadmin -getServiceState nn1
//查看
[root@nn01 hadoop]# /usr/local/hadoop/bin/yarn rmadmin -getServiceState rm1
//查看