上一节的hadoop集群为一个namenode 三个datanode。但是如果这个namenode挂掉之后整个集群就不能对外服务了。所以本节部署具有HA机制的hadoop集群。
1、在搭建之前首先介绍一下hadoop的相关知识
hdfs实现机制
1、hdfs是通过分布式集群来存储文件的,为客户端提供统一的访问方式
2、文件存储到hdfs集群中去的时候是被分成block的
3、文件的block存放在若干台datanode节点上
4、hdfs文件系统中的文件与真实的block之间有映射关系,由namenode管理
5、每个block在集群中会存储多个副本,可以提高数据的可靠性和吞吐量
客户端存储文件的过程
1、客户端访问namenode,namenode为其文件给出分块和datanode的信息
2、客户端获取信息,根据信息将文件发送到不同的datanode上。
客户端上传文件时,namenode首先往edits log文件汇总记录元数据操作日志,当客户端开始上传文件,完成返回成功信息给namenode,namenode就在内存中写入这次上传操作的新产生的元数据信息。当editslog写满后,需要将这段时间新的元数据刷到fsimage文件中。
namenode和secondnamenode
对于namenode最重要的两个文件:fsimage和edits。fsiamge用于记录目录树信息,即每个文件所属的位置。edits文件用于记录日志信息,对目录树的增删改查都会记录到edits文件中,而不是直接记录到fsimage文件中。
当namenode启动的时候会将fsimage和edits文件合并,那么有个问题就是edits文件有可能很大,在合并过程中可能会占用很长的时间。所以需要设置一定的条件,在edits不太大的时候就将edits文件和fsimage文件合并。这个任务就是分配给secondnamenode的。设置条件的方式有:
1:fs.checkpoint.period:单位秒,默认值3600,检查点的间隔时间,超过改时间启动检查点
2:fs.checkpoint.size:单位字节,默认值67108864,当edits文件超过该大小后,启动检查点
启动之后secondnamenode会将namenode中的fsimage和edits文件下载下来,然后进行合并,最后再返回给namenode。这合并的时间内,namenode新的操作日志数据将会记录在edits.new文件中。
HA机制
由于一台namenode提供服务存在服务挂掉的情况,所以可以使用两台namenode对外提供服务。一台处于active另外一台处于standby状态。对于这两台namenode最大的问题就是edits文件的同步,一般采用zookeeper来保存edits文件,由于一台zookeeper也有可能存在文件,所以也使用多台zookeeper对外提供服务。关于两个namenode的状态切换使用zkfc来进行。
2、搭建前的准备工作
机器规划
目前计划用7台机器进行,具体规划如下
主机名 IP地址 安装的服务
1、NN1 192.168.56.201 namenode、zkfc
2、NN2 192.168.56.202 namenode、zkfc
3、RES1 192.168.56.203 resourcemanager
4、RES1 192.168.56.204 resourcemanager
5、ZOOK1 192.168.56.205 journalnode(存放edits文件)、datanode、nodemanager
6、ZOOK2 192.168.56.206 journalnode(存放edits文件)、datanode、nodemanager
7、ZOOK3 192.168.56.207 journalnode(存放edits文件)、datanode、nodemanager
3、具体步骤
1、配置一台namenode机器
本次使用的环境和上一节中讲述的一致。将上一节的namenode复制一份,重新命名为NameNode1,然后启动NameNode1开始修改ip地址主机名等相关信息。该机器上以及安装了jdk、hadoop并把hadoop的配置到了环境变量中。首先修改ip地址和主机名
>> vim /etc/sysconfig/network-scripts/ifcfg-enp0s3 修改为如下 TYPE=Ethernet IPADDR=192.168.56.201 NETMASK=255.255.255.0
>> hostnamectl set-hostname NN1 //重启网络服务 >> systemctl restart network
修改hosts文件,使通过名称就能互相访问 >>vim /etc/hosts 修改为 192.168.56.201 NN1 192.168.56.202 NN2 192.168.56.203 RES1 192.168.56.204 RES2 192.168.56.205 ZOOK1 192.168.56.206 ZOOK2 192.168.56.207 ZOOK3
2、复制1中的机器
复制出来的名称分别为NN2 RES1 RES2 ZOOK1 ZOOK2 ZOOK3选择完全复制,然后手动去修改ip地址。
在每台机器上需要做的事情为:修改ip地址、修改主机名称、重启网络服务、删除hadoop文件夹
修改ip地址 >> vim /etc/sysconfig/network-scripts/ifcfg-enp0s3 修改主机名 >> hostnamectl set-hostname xxx 重启网络服务 >> systemctl restart network 删除hadoop文件夹,删除的原因在于hadoop需要重新配置,在NN1上配置完成后再复制到其他机器上,所以删除除开NN1外的六台机器上的hadoop >> rm -rf /usr/local/hadoop
3、在ZOOK1 ZOOK2 ZOOK3上安装zookeeper
可以官网下载tar.gz的包,将其传到三台机器上然后解压,目录为/usr/local/,名称为zookeeper
然后对zookeeper进行配置(三台机器ZOOK1 ZOOK2 ZOOK3做同样的配置)
>> cd /usr/local/zookeeper/conf/ >> mv zoo_sample.cfg zoo.cfg >> vim zoo.cfg 修改 dataDir = /usr/local/zookeeper/data 该data文件夹用于存储zookeeper的文件。需要自己手动在相应位置创建 然后在尾部继续添加 server.1=ZOOK1:2888:3888(2888为leader flow通信端口,3888选举机制的端口) server.2=ZOOK2:2888:3888 server.3=ZOOK3:2888:3888
效果如下
然后创建data文件夹(三台zook都要创建)
>> mkdir /usr/local/zookeeper/data
由于zoo.cfg文件中配置了server.x,所以需要在data文件夹下创建myid文件,用于存储id标号(三台zook都要创建)
>> touch /usr/local/zookeeper/data/myid
向myid文件中写入id
在ZOOK1上输入 >>echo 1 > /usr/local/zookeeper/data/myid 在ZOOK2上输入 >>echo 2 > /usr/local/zookeeper/data/myid 在ZOOK3上输入 >>echo 3 > /usr/local/zookeeper/data/myid
启动zookeeper
进入到zookeeper的bin文件夹 >> ./zkServer.sh start 查看启动状态 >> netstat -nltp|grep 2181 >>./zkServer.sh status >>jps
4、在NN1上安装并配置hadoop
由于使用的是上一次遗留的namenode,所以上面已经存在了hadoop的解压包。如果没有解压包的可以直接放一份新的解压包在上面,具体步骤参照上一次的博文。
修改core-site.xml文件
<configuration> <!-- 指定hdfs的nameservice为ns1 ns1表示一个服务,该服务下有两个namenode--> <property> <name>fs.defaultFS</name> <value>hdfs://ns1/</value> </property> <!-- 指定hadoop临时目录 该目录不需要手动创建,启动hadoop后会自动创建--> <property> <name>hadoop.tmp.dir</name> <value>/usr/local/hadoop/tmp</value> </property> <!-- 指定zookeeper地址 --> <property> <name>ha.zookeeper.quorum</name> <value>ZOOK1:2181,ZOOK2:2181,ZOOK3:2181</value> </property> </configuration>
修改hdfs-site.xml文件
<configuration> <!--指定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>NN1:9000</value> </property> <!-- nn1的http通信地址 --> <property> <name>dfs.namenode.http-address.ns1.nn1</name> <value>NN1:50070</value> </property> <!-- nn2的RPC通信地址 --> <property> <name>dfs.namenode.rpc-address.ns1.nn2</name> <value>NN2:9000</value> </property> <!-- nn2的http通信地址 --> <property> <name>dfs.namenode.http-address.ns1.nn2</name> <value>NN2:50070</value> </property> <!-- 指定NameNode的元数据在JournalNode上的存放位置 --> <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://ZOOK1:8485;ZOOK2:8485;ZOOK3:8485/ns1</value> </property> <!-- 指定JournalNode在本地磁盘存放数据的位置 --> <property> <name>dfs.journalnode.edits.dir</name> <value>/usr/local/hadoop/journaldata</value> </property> <!-- 开启NameNode失败自动切换 --> <property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property> <!-- 配置失败自动切换实现方式 --> <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>/usr/local/hadoop/.ssh/id_rsa</value> </property> <!-- 配置sshfence隔离机制超时时间 --> <property> <name>dfs.ha.fencing.ssh.connect-timeout</name> <value>30000</value> </property> </configuration>
修改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> <!-- 指定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>RES1</value> </property> <property> <name>yarn.resourcemanager.hostname.rm2</name> <value>RES2</value> </property> <!-- 指定zk集群地址 --> <property> <name>yarn.resourcemanager.zk-address</name> <value>ZOOK1:2181,ZOOK2:2181,ZOOK3:2181</value> </property> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> </configuration>
修改slaves文件,因为namenode启动的时候要去找datanode,所以可以在slaves文件中配置datanode所处的位置。同时由于yarn框架也要知道自己nodemanager的位置也需要编写slaves文件,同时由于datanode和nodemanager本次都存放在ZOOK1 ZOOK2 ZOOK3上面,所以在slaves文件中只需要配置
>> vim /usr/local/hadoop/etc/hadoop/slaves
5、设置ssh免密登录
==================================下次继续更新,确实太多了