前言
hadoop高可用是其商用化时三大重点之一,另外两大重点是yarn的资源配置与分布式存储,其次我们要知道高可用,俗称HA,它核心是zookeeper提供的zkfc机制,其实就是一组名为journal node的线程在负责着主、备namenode节点的元数据同步问题
而高可用在极端的情况下可能发生脑裂、假死问题,所以大家非商业模式要正式使用的情况下,只是自己本地测试环境那最好还是做单主节点就好了
本篇博文将以商用为目的记录配置HA的方式,结点数目商用时最低7台,大家自己配置的时候据情况而定属于自己的合适结点策略
节点
集群部署节点角色的规划(7节点,由于是最低档次所以zk放在了datanode同节点,zkfc、journal node是zk和hdp自带的服务)
hdp1 namenode zkfc
hdp2 namenode zkfc his
hdp3 resourcemanager
hdp4 resourcemanager
hdp5 datanode nodemanager zookeeper journal node
hdp6 datanode nodemanager zookeeper journal node
hdp7 datanode nodemanager zookeeper journal node
------------------
集群部署节点角色的规划(3节点)
hdp1 namenode resourcemanager zkfc nodemanager datanode zookeeper journal node
hdp2 namenode resourcemanager zkfc nodemanager datanode zookeeper journal node
hdp3 datanode nodemanager zookeeper journal node
直观上看就是比普通单namenode测试集群多出了一组namenode和resourcemanager,以及两个namenode数据同步依赖的zookeeper以及zkfc机制和journal node进程,配置的时候其实zookeeper集群可以单独再分出三台,这个具体看商用时的规划,这里提到是为了提醒大家配置的时候zookeeper和journal node并不是非要在一起,journal node时hadoop主动连接zookeeper启动,his是历史服务器节点
安装
第一步:解压hadoop并将保证hadoop与JAVA的环境变量存在,现在市面上用的基本都是2.0,配置文件都在hadoop根目录的etc/hadoop中,我们要进入其中并修改一系列的-env.sh
结尾文件中的JAVA_HOME,这一点和之前大家安装单namenode节点本地测试环境一样
第二步:修改core-site.xml
<configuration>
<!--
集群的 namenode组 访问地址在这里指定!注意我说的组是主、备的统称,该值必须和hdfs-site.xml文件中的组名配置一致,
这里之所以强调就是防止大家两个文件写的不一样,大家使用自己的配置就可以,不是必须为hdp1 ,我这里只是为了方便,所以组名定义为了hdp1
-->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hdp1</value>
</property>
<!-- hadoop的基础路径,这个路径是hadoop运行时其存放数据时的默认根路径,这个路径一定要改,因为默认路径是linux下的一个临时数据目录,相当容易被删除 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/hadoop/hadoopData</value>
</property>
<!-- ZooKeeper集群的地址和端口。注意,数量一定是奇数,且不少于三个节点-->
<property>
<name>ha.zookeeper.quorum</name>
<value>hdp5:2181,hdp6:2181,hdp7:2181</value>
</property>
<!--修改core-site.xml中的ipc参数,防止出现连接journalnode服务ConnectException,默认10s-->
<property>
<name>ipc.client.connect.max.retries</name>
<value>100</value>
</property>
<property>
<name>ipc.client.connect.retry.interval</name>
<value>10000</value>
</property>
</configuration>
第三步:修改hdfs-site.xml
<configuration>
<!--指定hdfs的nameservice服务组名字,再次声明hdp1只是一个名字啊,不是hdp1这个节点,大家觉得别扭可以改成别的,但一定要和core-site.xml中的保持一致 -->
<property>
<name>dfs.nameservices</name>
<value>hdp1</value>
</property>
<!-- 这个配置时用来标识hdp1下面有主、备共两个NameNode,并且为他们标识名字,我配置的分别是nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.hdp1</name>
<value>nn1,nn2</value>
</property>
<!-- nn1的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.hdp1.nn1</name>
<value>hdp1:9000</value>
</property>
<!-- nn1的http通信地址 -->
<property>
<name>dfs.namenode.http-address.hdp1.nn1</name>
<value>hdp1:50070</value>
</property>
<!-- nn2的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.hdp1.nn2</name>
<value>hdp2:9000</value>
</property>
<!-- nn2的http通信地址 -->
<property>
<name>dfs.namenode.http-address.hdp1.nn2</name>
<value>hdp2:50070</value>
</property>
<!-- 指定NameNode的edits元数据在JournalNode上的存放位置,这个配置本质上的目的就是在zk上使用一个zk节点,保存namenode同步数据,应该注意这里的zk节点说的是zkCli里面的 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hdp5:8485;hdp6:8485;hdp7:8485/hdp1</value>
</property>
<!-- 指定JournalNode在本地磁盘存放数据的位置 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/home/hadoop/app/hdpdata/journaldata</value>
</property>
<!-- 开启NameNode死亡自动切换 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- 指定该集群出故障时,哪个实现类负责执行故障切换 -->
<property>
<name>dfs.client.failover.proxy.provider.hdp1</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行-->
<property>
<name>dfs.ha.fencing.methods</name>
<value>
sshfence
</value>
</property>
<!-- 使用sshfence隔离机制时需要ssh免登陆,因此需要指定公钥路径,大家集群中ssh之后的公钥文件在哪里就指定那里,一般在用户主目录下的 .ssh文件夹里面-->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop/.ssh/id_rsa</value>
</property>
<!-- 配置sshfence隔离机制超时时间 -->
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>
<!-- namenode与datanode存储多路径配置,且更改datanode磁盘写入规则 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///${hadoop.tmp.dir}/dfs/data,file:///${hadoop.tmp.dir}/dfs/data1</value>
</property>
<property>
<name>dfs.datanode.fsdataset.volume.choosing.policy</name>
<value>org.apache.hadoop.hdfs.server.datanode.fsdataset.AvailableSpaceVolumeChoosingPolicy</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///${hadoop.tmp.dir}/dfs/name,file:///${hadoop.tmp.dir}/dfs/name1</value>
</property>
</configuration>
第四步:修改mapred-site.xml
<configuration>
<!-- 指定mr框架为yarn方式 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!-- 历史服务器的外部服务端口 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>hdp2:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hdp2:19888</value>
</property>
<!--历史服务器的MR相关日志文件存储,该值指向一个hdfs路径,下面两个配置也是-->
<property>
<name>yarn.app.mapreduce.am.staging-dir</name>
<value>/hisdata/staging</value>
</property>
<!--已结束的MR-日志-->
<property>
<name>mapreduce.jobhistory.done-dir</name>
<value>/hisdata/done</value>
</property>
<!-- 正在进行的MR-日志 -->
<property>
<name>mapreduce.jobhistory.intermediate-done-dir</name>
<value>/hisdata/done_intermediate</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的名字,对应主备namenode -->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<!-- 分别指定RM的地址 -->
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>hdp3</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>hdp4</value>
</property>
<!-- 指定zk集群地址 -->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>hdp5:2181,hdp6:2181,hdp7:2181</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!-- 阻止磁盘检查 -->
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
<!--配置外部端口-->
<!-- yarn对applicationmaster服务的端口 -->
<property>
<name>yarn.resourcemanager.scheduler.address.rm1</name>
<value>hdp3:8030</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address.rm2</name>
<value>hdp4:8030</value>
</property>
<!-- yarn对nodemanager服务的地址 -->
<property>
<name>yarn.resourcemanager.resource-tracker.address.rm1</name>
<value>hdp3:8031</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address.rm1</name>
<value>hdp4:8031</value>
</property>
<!--yarn对客户端服务的端口 -->
<property>
<name>yarn.resourcemanager.address.rm1</name>
<value>hdp3:8032</value>
</property>
<property>
<name>yarn.resourcemanager.address.rm2</name>
<value>hdp4:8032</value>
</property>
<!-- yarn对管理员服务的地址 -->
<property>
<name>yarn.resourcemanager.admin.address.rm1</name>
<value>hdp3:8033</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address.rm2</name>
<value>hdp4:8033</value>
</property>
<!-- yarn web UI服务的地址 -->
<property>
<name>yarn.resourcemanager.web.address.rm1</name>
<value>hdp3:8088</value>
</property>
<property>
<name>yarn.resourcemanager.web.address.rm2</name>
<value>hdp4:8088</value>
</property>
<!--开启Continer日志聚合,否则无法在web页面查看mr的日志-->
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<!--Continer日志路径,MR任务结束后将从mapred-site.xml配置的MR日志路径中聚合结果存放在这个目录中,使得日志可以背访问、使用-->
<property>
<name>yarn.nodemanager.remote-app-log-dir</name>
<value>/hisdata/ContinerLogs</value>
</property>
<!-- 以下三项配置是修改hadoop对历史MR任务的保存态度,使得重启后yarn-ui的历史MR记录不会丢失 -->
<property>
<!-- 开启作业保留 -->
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
<property>
<!-- 指定保存与加载历史任务的类,总计三个可选项,但高可用集群必须使用ZK -->
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
<property>
<!-- yarn重启后等待历史任务被加载的时间 -->
<name>yarn.resourcemanager.work-preserving-recovery.scheduling-wait-ms</name>
<value>10000</value>
</property>
</configuration>
第六步:修改slaves
这里要注意的是,slaves中只需要指定datanode所在节点就可以
hdp5
hdp6
hdp7
第七步:修改capacity-scheduler.xml,这个文件中有默认值,我们找到如下的配置并修改为对应的值
<property>
<name>yarn.scheduler.capacity.resource-calculator</name>
<value>org.apache.hadoop.yarn.util.resource.DominantResourceCalculator</value>
</property>
第八步:检查ssh免密,这一步主要是为了提醒大家配置免密,没有配置的看我之前发的大数据本地测试环境搭建的博文配置,配置的时候要注意整个集群都要配置免密,如果是按照我之前的博文配置的也需要把新增的节点配置好免密
第九步:scp分发hadoop集群
第十步:首次启动!!!
启动时,请严格按照下面的启动顺序来不然,就可以GG了。
1、先启动zookeeper集群
bin/zkServer.sh start
2、在所有的datanode节点上手动启动journalnode进程,命令如下
hadoop-daemon.sh start journalnode
运行之后jsp检查,查看是否有journalnode进程
3、格式化namenode,在主namenode,也就是hdp1上执行命令:
bin/hdfs namenode -format
4、格式化zkfc,在主namenode上运行一次就可以,命令如下:
hdfs zkfc -formatZK
5、在主namenode上运行start-dfs.sh
命令,启动hdfs
6、上面步骤中主namenode格式化后,会在之前core-site.xml中hadoop.tmp.dir配置的目录下生成hdfs的数据文件,我们要做的就是用命令把这个目录下所有文件拷贝到另一台备用namenode节点所在的机器的相同目录下
因此,登录备用namenode节点运行如下命令,手工启动备用节点,会自动拷贝主namenode文件,这个使用注意运行命令后提示出现"(Y or N) "
时一定要选Y
让备用节点后续处于交互式随着主namenode启动而启动,注意一定要确保主namenode格式化无异常
bin/hdfs namenode -bootstrapStandby
7、启动yarn,在hdp3节点运行start-yarn.sh
8、在hdp4上确定是否启动了备份的resourcemanager,因为高可用集群中namenode会自动切换,但是resourcemanager需要手动启,命令如下
yarn-daemon.sh start resourcemanager
9、在hdp2上启动历史服务器
mr-jobhistory-daemon.sh start historyserver
10、到此高可用的配置就结束了,我给大家找了一下测试用的命令大家可以试一试
可以浏览器访问:
http://hdp1:50070
NameNode 'hdp1:9000' (active)
http://hdp2:50070
NameNode 'hdp2:9000' (standby)
验证HDFS HA
首先向hdfs上传一个文件
hadoop fs -put /etc/profile /profile
hadoop fs -ls /
然后再kill掉active的NameNode
kill -9 <进程id>
浏览器访问:
http://hdp1:50070
会发现之前主的namenode已经用不了了
http://hdp2:50070
这个时候hdp2上的NameNode变成了active
在执行命令:
hadoop fs -ls /
-rw-r--r-- 3 root supergroup 1926 2014-02-06 15:36 /profile
刚才上传的文件依然存在!!!
在之前的主namenode上手动启动被我们kill的NameNode
hadoop-daemon.sh start namenode
通过浏览器访问:http://hdp1:50070
可以发现原来主的namenode又可以使用了
验证YARN:
运行一下hadoop提供的demo中的WordCount程序:
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.4.1.jar wordcount /profile /out
还有一些测试集群工作状态的一些指令 :
hdfs dfsadmin -report 查看hdfs的各节点状态信息
cluster1n/hdfs haadmin -getServiceState nn1 获取一个namenode节点的HA状态
scluster1n/hadoop-daemon.sh start namenode 单独启动一个namenode进程
hadoop-daemon.sh start zkfc 单独启动一个zkfc进程
到此HA-Hadoop配置完毕,总的来说和单namenode的配置和运行有些不同,下面我大致总结一下不同点
1、在我之前的博文中env类型的运行环境文件在本篇HA中只配置了一个,但是大家最好还是把另外两个的也配置好
2、slaves在HA中只需要指定datanode运行节点就可以
3、site类的文件中,core里面多了一个zk集群地址
4、hdfs里面没有配置副本数量,是因为默认就是3个,想配的话大家找到相关配置加进去就可以了
5、没有配置辅助节点位置,这个是因为大家配置好了之后会发现在启动之后辅助节点和它所属的namenode在一起,而且之前我在单namenode配置是为了防止都配置在一个节点上,那个节点撑不住一下挂了就GG了,而HA中我们单独拉出了一台机子给namenode所以就没有考虑辅助节点另外配置,而且大家想想HA中一个namenode挂了那身为小弟的辅助节点还活着干吗???不过大家如果想分开配,也可以自己找找,反正我没有遇到过高可用还要考虑他们两个分开的搭建方式
6、yarn中我们细化了配置,实现了高可用的yarn
最后,强调一遍启动方式
上面的启动方式是刚配置好的首次启动方式,后期启动没那么麻烦,只需要如下操作即可
1、启动zookeeper集群
2、启动主namenode
3、启动主-副两个yarn节点进程
4、启动历史服务器