第5课 YARN 安装以及helloworld (基于centos的CDH)

新老MapReduce的比较

说到YARN肯定要先说下老的MapReduce

MRv1 (MapReduce v1)的架构图

第5课 YARN 安装以及helloworld (基于centos的CDH)
从上图中可以清楚的看出原 MapReduce 程序的流程及设计思路:
  • 首先用户程序 (JobClient) 提交了一个 job,job 的信息会发送到 Job Tracker 中,Job Tracker 是 Map-reduce 框架的中心,他需要与集群中的机器定时通信 (heartbeat), 需要管理哪些程序应该跑在哪些机器上,需要管理所有 job 失败、重启等操作。
  • TaskTracker 是 Map-reduce 集群中每台机器都有的一个部分,他做的事情主要是监视自己所在机器的资源情况。
  • TaskTracker 同时监视当前机器的 tasks 运行状况。TaskTracker 需要把这些信息通过 heartbeat 发送给 JobTracker,JobTracker 会搜集这些信息以给新提交的 job 分配运行在哪些机器上。上图虚线箭头就是表示消息的发送 - 接收的过程。
这里就不说老MapReduce的缺点了,想了解的朋友看最后的参考资料。总之大家如果再看到教程里面出现Job Tracker,Task Tracker的概念就不用看了,一定是老MapReduce

YARN的架构图

第5课 YARN 安装以及helloworld (基于centos的CDH)

  • 重构根本的思想是将 JobTracker 两个主要的功能分离成单独的组件,这两个功能是资源管理和任务调度 / 监控
  • 上图中 ResourceManager 支持分层级的应用队列,这些队列享有集群一定比例的资源。从某种意义上讲它就是一个纯粹的调度器,它在执行过程中不对应用进行监控和状态跟踪。同样,它也不能重启因应用失败或者硬件错误而运行失败的任务。ResourceManager 是基于应用程序对资源的需求进行调度的 ; 每一个应用程序需要不同类型的资源因此就需要不同的容器。
  • 上图中 NodeManager 是每一台机器框架的代理,是执行应用程序的容器,监控应用程序的资源使用情况 (CPU,内存,硬盘,网络 ) 并且向调度器汇报。
  • 每一个应用的 ApplicationMaster 负责相应的调度和协调。一个应用程序无非是一个单独的传统的 MapReduce 任务或者是一个 DAG( 有向无环图 ) 任务。每一个应用的 ApplicationMaster 的职责有:向调度器索要适当的资源容器,运行任务,跟踪应用程序的状态和监控它们的进程,处理任务的失败原因。
概念大概懂就好了,不需要一开始就理解,先做例子,再理解理论。

安装YARN

YARN就是Map Reduce 2代,只不过换了一个名字,逼格比较高而已。如果你是照着我的教程 Alex 的 Hadoop 菜鸟教程: 第4课 Hadoop 安装教程 - HA方式 (2台服务器) 来安装的,那么你会发现有些组件已经装好了。

安装

ResouceManager安装

随便挑选一台机器作为ResourceManager,可以单独开一台机器也可以装在其中一个namenode上面,运行以下命令
[plain] view plain copy
  1. sudo yum install hadoop-yarn-resourcemanager  

启动服务
[plain] view plain copy
  1. service hadoop-yarn-resourcemanager start  


在所有datanode上安装nodemanager和mapreduce

[plain] view plain copy
  1. sudo yum install hadoop-yarn-nodemanager hadoop-mapreduce  

启动服务
[plain] view plain copy
  1. service hadoop-yarn-nodemanager start  

以下两个组件之前的教程中是没说到的,所以请大家不要漏掉安装了

安装Hadoop-client

在所有要运行mapreduce的机器上安装hadoop-client,这个就是一堆运行mapreduce需要的jar包
[plain] view plain copy
  1. yum -y install hadoop-client  

安装好后会多出这个文件夹 
[plain] view plain copy
  1. /usr/lib/hadoop/client-0.20  
后面编译mapreduce的时候会用到

安装JobHistory

[plain] view plain copy
  1. yum -y install hadoop-mapreduce-historyserver  



配置

以下配置如果你在安装的时候已经做过一遍,就不用再做了,如果没做过的请在所有机子上都配置
先cd到 /etc/hadoop/conf 文件夹底下

修改mapred-site.xml

[html] view plain copy
  1. <configuration>  
  2.   <property>    
  3.        <name>mapreduce.framework.name</name>    
  4.        <value>yarn</value>    
  5.   </property>  
  6.   <property>  
  7.        <name>mapreduce.jobhistory.address</name>  
  8.        <value>host1:10020</value>    
  9.   </property>  
  10.   <property>  
  11.        <name>mapreduce.jobhistory.webapp.address</name>  
  12.        <value>host1:19888</value>    
  13.   </property>  
  14. <property>  
  15.     <name>yarn.app.mapreduce.am.staging-dir</name>  
  16.     <value>/user</value>  
  17.   </property>  
  18. </configuration>  

  • mapreduce.jobhistory.address 和 mapreduce.jobhistory.webapp.address 是用于配置  jobHistory 的地址的。jobHistory会记录job运行的历史记录,强烈建议打开!
  • yarn.app.mapreduce.am.staging-dir 是job运行时的临时文件夹,默认值是/tmp/hadoop-yarn/staging

修改yarn-site.xml 

在 <configuration/> 节点里面插入一个属性
[html] view plain copy
  1. <property>        
  2.       <name>yarn.resourcemanager.hostname</name>        
  3.       <value>host1</value>        
  4.   </property>  


建立yarn在hdfs上的日志文件夹

[plain] view plain copy
  1. sudo -u hdfs hadoop fs -mkdir -p /var/log/hadoop-yarn  
  2. sudo -u hdfs hadoop fs -chown yarn:mapred /var/log/hadoop-yarn  

并根据你的hdfs-site.xml 里面的 fs.defaultFS 这项的属性来修改所有节点上的 yarn-site.xml文件里面的 yarn.nodemanager.remote-app-log-dir 属性值。比如我的fs.defaultFS里面配置为hdfs://mycluster ,那么我的 yarn.nodemanager.remote-app-log-dir  变成这样

继续修改yarn-site.xml

[html] view plain copy
  1. <property>  
  2.     <description>Where to aggregate logs to.</description>  
  3.     <name>yarn.nodemanager.remote-app-log-dir</name>  
  4.     <value>hdfs://mycluster/var/log/hadoop-yarn/apps</value>  
  5. </property>  

在我这个例子中,就是把 host1 和 host2 上的这个文件都改了,并且重启服务

[plain] view plain copy
  1. service hadoop-yarn-nodemanager restart  

修改core-site.xml

增加jobHistory 相关配置

[html] view plain copy
  1. <property>  
  2.    <name>hadoop.proxyuser.mapred.groups</name>  
  3.    <value>*</value>  
  4. </property>  
  5. <property>  
  6.    <name>hadoop.proxyuser.mapred.hosts</name>  
  7.    <value>*</value>  
  8. </property>  

Yarn运行job的时候需要一个临时文件夹,默认是用 /tmp/hadoop-yarn/staging ,最好改一下

编辑mapred-site.xml

[html] view plain copy
  1. <property>  
  2.     <name>yarn.app.mapreduce.am.staging-dir</name>  
  3.     <value>/user</value>  
  4. </property>  

然后在hdfs上建立相应的文件夹

[plain] view plain copy
  1. sudo -u hdfs hdfs dfs -mkdir -p /user/history  
  2. sudo -u hdfs hdfs dfs -chmod -R 1777 /user/history  
  3. sudo -u hdfs hdfs dfs -chown mapred:hadoop /user/history  


这是mapred-site.xml最终的样子

[plain] view plain copy
  1. <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>  
  2.   
  3. <configuration>  
  4.   <property>  
  5.        <name>mapreduce.framework.name</name>  
  6.        <value>yarn</value>  
  7.   </property>  
  8.   <property>  
  9.        <name>mapreduce.jobhistory.address</name>  
  10.        <value>host1:10020</value>  
  11.   </property>  
  12.   <property>  
  13.        <name>mapreduce.jobhistory.webapp.address</name>  
  14.        <value>host1:19888</value>  
  15.   </property>  
  16.   <property>  
  17.     <name>yarn.app.mapreduce.am.staging-dir</name>  
  18.     <value>/user</value>  
  19.   </property>  
  20. </configuration>  

这是core-site.xml最终的样子

[plain] view plain copy
  1. <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>  
  2.   
  3. <configuration>  
  4.   <property>  
  5.     <name>fs.defaultFS</name>  
  6.     <value>hdfs://mycluster</value>  
  7.   </property>  
  8.   <property>  
  9.      <name>hadoop.tmp.dir</name>  
  10.      <value>/data/hdfs/tmp</value>  
  11.   </property>  
  12.   <property>  
  13.      <name>ha.zookeeper.quorum</name>  
  14.      <value>host1:2181,host2:2181</value>  
  15.   </property>  
  16.   <property>  
  17.      <name>hadoop.proxyuser.mapred.groups</name>  
  18.      <value>*</value>  
  19.   </property>  
  20.   <property>  
  21.      <name>hadoop.proxyuser.mapred.hosts</name>  
  22.      <value>*</value>  
  23.   </property>  
  24. </configuration>  

重启服务令配置生效

先停止 hadoop-yarn-resourcemanager  和 hadoop-yarn-nodemanager ,然后先启动 hadoop-yarn-resourcemanager 再启动 hadoop-yarn-nodemanager 。
官网上有提示说要确保每次resourcemanager 都比 nodemanager 起的早

再启动jobHistory
[plain] view plain copy
  1. service hadoop-mapreduce-historyserver start  

Helloworld

该例子的主要目的是: 运行wordcount单词计数案例,计算词语出现的次数

环境

  • 装了CDH5的hadoop
  • 本例子在之前安装的2台server (host1, host2) 搭成的hadoop集群之上运行
  • 根据cdh官方文档的教程做一个简单的例子,但是cdh的教程写的不严谨,有很多坑等着你去跳,所以我改造了一下写成了这篇文章

STEP 1 在HDFS文件系统上建立input文件夹

HDFS就像是在我们实际的文件空间上虚拟出来的一个文件空间,而且这个文件空间是跨好多台电脑的,在这个空间里面也可以建立文件夹,建立文件等操作
现在我们登陆到部署好hadoop的server上(host1),cd到home目录下,然后切换到hdfs的世界里:
[plain] view plain copy
  1. $ hdfs dfs -mkdir /user  
  2. $ hdfs dfs -mkdir /user/cloudera  
  3. $ hdfs dfs -ls /user  
  4. Found 1 items  
  5. drwxr-xr-x   - root hadoop          0 2014-07-02 14:52 /user/cloudera  
  6. $ hdfs dfs -mkdir /user/cloudera/wordcount /user/cloudera/wordcount/input  


说明

有些教程会把命令写成 “hadoop fs -ls /” 这样的写法,这种写法是老hadoop的写法,现在新的写法是 hdfs dfs -ls ,所以请使用新的写法。其实hadoop开发组目前是极力的把hadoop 跟 hdfs 的概念分清楚,以免大家有误解,hadoop其实是HDFS跟MapReduce两种技术的总和,存储部分是hdfs,所以现在hadoop的开发组希望大家了解这种概念,进而使用hdfs这样更专业和精确的术语

补充

如果在 / 根目录下看不到tmp目录,就请先建立这个目录,并分配权限为hdfs.hdfs以免别的程序比如hive或者hbase建立了这个目录,如果这样的话tmp文件夹的所有者就未必是hdfs了,会对别的程序造成影响

[plain] view plain copy
  1. [[email protected] ~]# sudo -u hdfs hdfs dfs -mkdir /tmp  
  2. [[email protected] ~]# sudo -u hdfs hdfs dfs -chmod -R 1777 /tmp  


STEP 2 建立测试的文本

$ echo "Hello World Bye World" > file0
$ echo "Hello Hadoop Goodbye Hadoop" > file1
$ hdfs dfs -put file* /user/cloudera/wordcount/input


STEP 3 编译 WordCount.java

[plain] view plain copy
  1. $ vim WordCount.java  


把下面的代码粘贴进去

[java] view plain copy
  1. package org.myorg;  
  2.   
  3.   
  4. import java.io.IOException;  
  5. import java.util.*;  
  6.   
  7.   
  8. import org.apache.hadoop.fs.Path;  
  9. import org.apache.hadoop.conf.*;  
  10. import org.apache.hadoop.io.*;  
  11. import org.apache.hadoop.mapred.*;  
  12. import org.apache.hadoop.util.*;  
  13.   
  14.   
  15. public class WordCount {  
  16.   
  17.   
  18.   public static class Map extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> {  
  19.     private final static IntWritable one = new IntWritable(1);  
  20.     private Text word = new Text();  
  21.   
  22.   
  23.     public void map(LongWritable key, Text value, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {  
  24.       String line = value.toString();  
  25.       StringTokenizer tokenizer = new StringTokenizer(line);  
  26.       while (tokenizer.hasMoreTokens()) {  
  27.         word.set(tokenizer.nextToken());  
  28.         output.collect(word, one);  
  29.       }  
  30.     }  
  31.   }  
  32.   
  33.   
  34.   public static class Reduce extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {  
  35.     public void reduce(Text key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {  
  36.       int sum = 0;  
  37.       while (values.hasNext()) {  
  38.         sum += values.next().get();  
  39.       }  
  40.       output.collect(key, new IntWritable(sum));  
  41.     }  
  42.   }  
  43.   
  44.   
  45.   public static void main(String[] args) throws Exception {  
  46.     JobConf conf = new JobConf(WordCount.class);  
  47.     conf.setJobName("wordcount");  
  48.   
  49.   
  50.     conf.setOutputKeyClass(Text.class);  
  51.     conf.setOutputValueClass(IntWritable.class);  
  52.   
  53.   
  54.     conf.setMapperClass(Map.class);  
  55.     conf.setCombinerClass(Reduce.class);  
  56.     conf.setReducerClass(Reduce.class);  
  57.   
  58.   
  59.     conf.setInputFormat(TextInputFormat.class);  
  60.     conf.setOutputFormat(TextOutputFormat.class);  
  61.   
  62.   
  63.     FileInputFormat.setInputPaths(conf, new Path(args[0]));  
  64.     FileOutputFormat.setOutputPath(conf, new Path(args[1]));  
  65.   
  66.   
  67.     JobClient.runJob(conf);  
  68.   }  
  69. }  


然后编译它

[plain] view plain copy
  1. $ mkdir wordcount_classes  
  2. $ javac -cp <classpath> -d wordcount_classes WordCount.java  


这边的 <classpath> 可以填的值根据版本不一样不同:
CDH 4/5
Parcel installation - /opt/cloudera/parcels/CDH/lib/hadoop/*:/opt/cloudera/parcels/CDH/lib/hadoop/client-0.20/*
Package installation - /usr/lib/hadoop/*:/usr/lib/hadoop/client-0.20/*
CDH3 - /usr/lib/hadoop-0.20/hadoop-0.20.2-cdh3u6-core.jar
我们是CDH5
所以完整的命令是
[plain] view plain copy
  1. $ javac -cp /usr/lib/hadoop/*:/usr/lib/hadoop/client-0.20/* -d wordcount_classes WordCount.java  


成功的话没有任何回应,但是在 wordcount_classes 里面出现了org文件夹


STEP 4 创建JAR

[plain] view plain copy
  1. $ jar -cvf wordcount.jar -C wordcount_classes/ .  

执行这条命令的时候注意最后还有一个点符号, 千万别漏掉了

然后把这个 wordcount.jar移动到 /data/ 目录下后面会使用到


STEP 5 运行程序

[plain] view plain copy
  1. $ sudo su - hdfs  


因为hdfs用户的根目录是/var/lib/hadoop-hdfs,所以我们要cd到刚刚有jar文件的目录
[plain] view plain copy
  1. $ cd /data  
  2. $ hadoop jar wordcount.jar org.myorg.WordCount /user/cloudera/wordcount/input /user/cloudera/wordcount/output  
  3. 14/07/03 09:44:16 INFO Configuration.deprecation: session.id is deprecated. Instead, use dfs.metrics.session-id  
  4. 14/07/03 09:44:16 INFO jvm.JvmMetrics: Initializing JVM Metrics with processName=JobTracker, sessionId=  
  5. 14/07/03 09:44:16 INFO jvm.JvmMetrics: Cannot initialize JVM Metrics with processName=JobTracker, sessionId= - already initialized  
  6. ...  


输出了很多东西之后我们去看下结果


注意

如果程序长时间卡主你可以根据日志中提示的
[plain] view plain copy
  1. 15/01/06 07:18:40 INFO mapreduce.Job: The url to track the job: http://host1:8088/proxy/application_1420470115119_0002/  
这句话说的地址去查看日志
还有一个方法更靠谱,就是直接看机器的日志
[plain] view plain copy
  1. vim /var/log/hadoop-yarn/yarn-yarn-nodemanager-host1.localdomain.log  
根据日志来排查问题是最高效的

STEP 6 查看结果

[plain] view plain copy
  1. $ hdfs dfs -cat /user/cloudera/wordcount/output/part-00000  
  2. Bye 1  
  3. Goodbye 1  
  4. Hadoop  2  
  5. Hello   2  
  6. World   2  

还可以到 http://host1:19888/ 去查看job历史记录

STEP 7 删除结果

如果你想再运行一次教程就要先删除掉结果
[plain] view plain copy
  1. $ hdfs dfs -rm -r /user/cloudera/wordcount/output  



hdfs还提供了几个选项用于传递信息给应用(wordcount就是一个应用):
-files 允许应用指定几个在运行目录下的文件(逗号分隔)给应用
-libjars 允许应用添加jar到maps 和 reduces 的 classpath
-archives 可以把归档文件当做参数传递给应用。归档文件:解压开或者unjared(打jar包的相反动作)成一个文件夹,然后用这个文件夹建立一个link,并且这个link的名字是一个zip或者jar文件(以.zip 或者 .jar 结尾)



参考资料

  • http://www.educity.cn/wenda/578863.html
  • http://www.cloudera.com/content/cloudera/en/documentation/cdh5/v5-0-0/CDH5-Installation-Guide/cdh5ig_yarn_cluster_deploy.html?scroll=topic_11_4_3_unique_1 这是官方原版的文档,强烈建议做完例子再去看一遍