- 目录
HDFS -HA模式的工作机制示意图集群规划——三节点高可用Hadoop HA集群搭建前期准备创建新的虚拟机配置虚拟机克隆虚拟机配置环境变量,刷新(master、slave1、slave2都配置一下环境变量)安装zookeeper集群配置文件拷贝文件拷贝jdk、zookeeper到slave1和slave2节点修改02和03节点的myid安装hadoop集群配置文件修改JAVA_HOME 在hadoop-env.sh yarn-env.sh mapred-env.sh 中core-site.xmlhdfs-site.xmlmapred-site.xmlyarn-site.xmlslaves拷贝文件到其他节点删除hadoop目录中share目录下的doc文档设置免密将配置好的hadoop拷贝到其他节点启动集群同步时间启动zookeeper集群启动journalnode格式化namenode格式化zkfc启动HDFS启动yarnjps查看进程查看网页测试上传文件到HDFS验证HA模式杀死namenode进程重启namenode进程杀死namenode上的ZKFC关闭集群:二次启动
HDFS -HA模式的工作机制示意图
说明:
1.在hadoop2.0中通常由两个NameNode组成,一个处于active状态,另一个处于standby状态。Active NameNode对外提供服务,而Standby NameNode则不对外提供服务,仅同步active namenode的状态,以便能够在它失败时快速进行切换。
hadoop2.0官方提供了两种HDFS HA的解决方案,一种是NFS,另一种是QJM。这里我们使用简单的QJM。在该方案中,主备NameNode之间通过一组JournalNode同步元数据信息,一条数据只要成功写入多数JournalNode即认为写入成功。通常配置奇数个JournalNode
这里还配置了一个zookeeper集群,用于ZKFC(DFSZKFailoverController)故障转移,当Active NameNode挂掉了,会自动切换Standby NameNode为active状态.
2.hadoop-2.2.0中依然存在一个问题,就是ResourceManager只有一个,存在单点故障,hadoop-2.6.4解决了这个问题,有两个ResourceManager,一个是Active,一个是Standby,状态由zookeeper进行协调
集群规划——三节点高可用
主机名 | IP | 安装软件 | 运行进程 |
master | 192.168.8.101 | jdk、hadoop、zookeeper | NameNode、DFSZKFailoverController(zkfc) ResourceManager DataNode、NodeManager JournalNode、QuorumPeerMain |
slave1 | 192.168.8.102 | jdk、hadoop、zookeeper | NameNode、DFSZKFailoverController(zkfc) ResourceManager DataNode、NodeManager JournalNode、QuorumPeerMain |
slave2 | 192.168.8.103 | jdk、hadoop、zookeeper | DataNode、NodeManager JournalNode、QuorumPeerMain |
Hadoop HA集群搭建
前期准备
创建新的虚拟机
配置虚拟机
- 配置网卡
- 虚拟网络编辑器、本地网络配置器
- 重启网卡,ping内外网
- CRT连接虚拟机,修改编码格式、字体、背景
- 修改主机名
- 配置映射(3台节点)
- 关闭防火墙
克隆虚拟机
- 克隆slave1,slave2
- slave1,slave2 修改网卡(IP)
- 重启网卡,ping内外网
- CRT连接虚拟机,修改编码格式、字体、背景
- 修改主机名
- 检查映射(3台节点)
- 检查防火墙
- 上传JDK、hadoop、zookeeper(主节点)
配置环境变量,刷新(master、slave1、slave2都配置一下环境变量)
export JAVA_HOME=/opt/software/jdk1.8.0_162
export HADOOP_HOME=/opt/software/hadoop-2.7.3
export ZOOKEEPER_HOME=/opt/software/zookeeper-3.4.6
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$ZOOKEEPER_HOME/bin
安装zookeeper集群
server.ID=host:port:port ID就是myid文件中配置的数字。下面会有介绍 第一个端口( port )是从( follower )机器连接到主( leader )机器的端口, 第二个端口是用来进行 leader 选举的端口。 每台机器使用三个端口,分别是: clientPort ,2181 ; port , 2888 ; port , 3888 。 |
配置文件
cd /opt/software/zookeeper-3.4.6/conf/
cp zoo_sample.cfg zoo.cfg
vi zoo.cfg
dataDir=/opt/software/zookeeper-3.4.6/zkData
dataLogDir=/opt/software/zookeeper-3.4.6/logs
server.1=master:2888:3888
server.2=slave1:2888:3888
server.3=slave2:2888:3888
mkdir /opt/software/zookeeper-3.4.6/zkData
mkdir /opt/software/zookeeper-3.4.6/logs
echo 1 > /opt/software/zookeeper-3.4.6/zkData/my
拷贝文件
拷贝jdk、zookeeper到slave1和slave2节点
scp -r jdk1.8.0_162/ slave1:$PWD
scp -r zookeeper-3.4.6/ slave1:$PWD
scp -r jdk1.8.0_162/ slave2:$PWD
scp -r zookeeper-3.4.6/ slave2:$PWD
修改02和03节点的myid
slave1:echo 2 > /opt/software/zookeeper-3.4.6/zkData/myid
cat myid
slave2:echo 3 > /opt/software/zookeeper-3.4.6/zkData/myid
cat myid
安装hadoop集群
配置文件
cd /opt/software/hadoop-2.7.3/etc/hadoop/
修改JAVA_HOME 在hadoop-env.sh yarn-env.sh mapred-env.sh 中
export JAVA_HOME=/opt/software/jdk1.8.0_162
core-site.xml
<configuration>
<!-- 指定hdfs的nameservice为ns1 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://ns1/</value>
</property>
<!-- 指定hadoop临时目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/software/hadoop-2.7.3-HA/tmpData</value>
</property>
<!-- 指定zookeeper地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>master:2181,slave1:2181,slave2:2181</value>
</property>
</configuration>
mkdir /opt/software/hadoop-2.7.3-HA/tmpData
hdfs-site.xml
<!--指定hdfs的nameservice为ns1,需要和core-site.xml中的保持一致 -->
<property>
<name>dfs.nameservices</name>
<value>ns1</value>
</property>
<!-- ns1下面有两个NameNode,分别是nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.ns1</name>
<value>nn1,nn2</value>
</property>
<!-- nn1的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.ns1.nn1</name>
<value>master:9000</value>
</property>
<!-- nn1的http通信地址 -->
<property>
<name>dfs.namenode.http-address.ns1.nn1</name>
<value>master:50070</value>
</property>
<!-- nn2的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.ns1.nn2</name>
<value>slave1:9000</value>
</property>
<!-- nn2的http通信地址 -->
<property>
<name>dfs.namenode.http-address.ns1.nn2</name>
<value>slave1:50070</value>
</property>
<!-- 指定NameNode的元数据在JournalNode上的存放位置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://master:8485;slave1:8485;slave2:8485/ns1</value>
</property>
<!-- 指定JournalNode在本地磁盘存放数据的位置 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/root/hdpdata/journaldata</value>
</property>
<!-- 开启NameNode失败自动切换 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!--zkfc 配置失败自动切换实现方式-->
<property>
<name>dfs.client.failover.proxy.provider.ns1</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行-->
<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>/root/.ssh/id_rsa</value>
</property>
<!-- 配置sshfence隔离机制超时时间 -->
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>
</configuration>
mkdir -p /root/hdpdata/journaldata
mapred-site.xml
<configuration>
<!-- 指定mr框架为yarn方式 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
yarn-site.xml
<configuration>
<!-- 开启RM高可用 -->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<property>
<name>yarn.resourcemanager.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- ha.id的配置,rm1和rm2不一样,且其他slaves不用配 -->
<property>
<name>yarn.resourcemanager.ha.id</name>
<value>rm1</value>
</property>
<!-- 指定RM的cluster id -->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>yrc</value>
</property>
<!-- 指定RM的名字 -->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<!-- 分别指定RM的地址 -->
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>master</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>slave1</value>
</property>
<!-- 指定zk集群地址 -->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>master:2181,slave1:2181,slave2:2181</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
</configuration>
slaves
master
slave1
slave2
拷贝文件到其他节点
删除hadoop目录中share目录下的doc文档
cd /opt/software/hadoop-2.7.3-HA/share/
rm -rf doc/
设置免密
首先要配置master、slave1、slave2的免密码登陆。
#在hadoop01上生产一对钥匙:ssh-keygen -t rsa
#将公钥拷贝到其他节点,包括自己
ssh-coyp-id master
ssh-coyp-id slave1
ssh-coyp-id slave2
#注意:两个namenode之间要配置ssh免密码登陆,别忘了配置slave1到master的免登陆
在slave1上生产一对钥匙:
ssh-keygen -t rsa
ssh-coyp-id -i slave1
将配置好的hadoop拷贝到其他节点
scp -r hadoop-2.7.3-HA/ slave1:$PWD
scp -r hadoop-2.7.3-HA/ slave2:$PWD
- 测试Hadoop是否安装成功
[root@masteropt]# hadoop version
[root@slave1 opt]# hadoop version
[root@slave2 opt]# hadoop version
显示对用版本就成功了!
启动集群
同步时间
使用date命令
date -s "2017-4-14 10:16:00"
在单点故障HDFS集群的基础上建立
启动zookeeper集群
分别在master、slave1、slave2上执行:zkServer.sh start
查看各节点的状态(一个leader,两个follower):zkServer.sh status
启动journalnode
分别在master、slave1、slave2上执行:hadoop-daemon.sh start journalnode
运行jps命令检验,master、slave1、slave2上多了JournalNode进程
格式化namenode
在master上执行命令:hdfs namenode -format——格式化master的namenode
bin/hdfs namenode –format
启动 master的namenode——sbin/hadoop-deamon.sh start namenode
在slave1上同步master namenode元数据
bin/hdfs namenode -bootstrapStandby
启动slave1的namenode——sbin/hadoop-deamon.sh start namenode
或者可使用下面这种方法进行namenode同步操作:
格式化后会根据core-site.xml中的hadoop.tmp.dir配置生成临时文件,
这里我配置的是/opt/software/hadoop-2.7.3-HA/tmpData,
然后将
/opt/software/hadoop-2.7.3-HA/tmpData/
拷贝到slave1的
/opt/software/hadoop-2.7.3-HA/tmpData
下:
scp -r dfs/ slave1:$PWD
关于namenode的格式化操作:
格式化namenode,第一次使用需格式化一次,之后就不用再格式化。
如果改一些配置文件了,可能还需要再次格式化.
多次格式化,一定要注意:
如果是这种情况的话,那么一定是多次格式化导致的spaceID不一致。
解决方案:
1、停止dfs
$./stop-dfs.sh
2、删除在hdfs中配置的data目录和tmp目录
$ rm -r /home/data
$ rm -r /home/tmp
重新创建data目录和tmp目录
$ mkdir data
$ mkdir tmp
3、重新格式化namenode
$ hadoop namenode -format
4、重新启动dfs
$./start-dfs.sh
5、查看dfs
$ jps
再次使用hadoop dfsadmin -report查看情况:
格式化zkfc
master执行:hdfs zkfc -formatZK
启动HDFS
master执行:start-dfs.sh
查看namenode状态
[root@master hadoop]# hdfs haadmin -getServiceState nn1
active
[root@master hadoop]# hdfs haadmin -getServiceState nn2
standby
启动yarn
master执行:start-yarn.sh
在slave1上启动resourcemanager: yarn-daemon.sh start resourcemanager
查看yarn状态
[root@master hadoop]# yarn rmadmin -getServiceState rm1
active
[root@master hadoop]# yarn rmadmin -getServiceState rm2
standby
jps查看进程
查看网页
可以看到刚开始我们的HDFS上面是什么都没有的。
问题:
如果发现配置文件需要添加或者修改,那么我们需要重新进行格式化操作。那么就按照上面第一次启动集群的格式化操作再做一遍。如果启动之后发现节点中datanode进程总是发生闪退现象。那么应该是多次对namenode进行format,每一次format主节点NameNode产生新的clusterID、namespaceID,于是导致主节点的clusterID、namespaceID与各个子节点DataNode不一致。当format过后再启动hadoop,hadoop尝试创建新的current目录,但是由于已存在current目录,导致创建失败,最终引起DataNode节点的DataNode进程启动失败,从而引起hadoop集群完全启动失败。因此可以通过直接删除数据节点DataNode的current文件夹,进行解决该问题。
测试
上传文件到HDFS
上传一个文件到hdfs:hadoop fs /root/wc.txt /
新建文件夹在hdfs上:
开始上传:
验证HA模式
到web页面查看文件以及namenode状态,然后kill掉为active的namenode,到另一个namenode页面上查看数据以及namenode状态,当namenode状态由standby变为active,也能查看数据,则安装集群成功。
再次启动被kill掉的namenode,到web页面查看,namenode状态变为standby。
杀死namenode进程
Node1网页无法连接
重启namenode进程
杀死namenode上的ZKFC
Node1和node2切换主从关系
关闭集群:
关闭Hadoop集群stop-all.sh
关闭zookeeper集群zkServer.sh stop
二次启动
如果觉得本人写的有问题,可参考下面这位博主博客链接:
hadoop完全分布式搭建HA(高可用)