1、Hadoop依赖软件

Hadoop基于Java语言开发,因此其运行严重依赖于JDK(Java Development Kit),并且Hadoop的许多功能依赖于Java 6及以后的版本才提供的特性。Hadoop可以良好地运行于经过测试的各JDK,如Sun JDK、OpenJDK、Oracle JRockit、IBM JDK各自实现的某些版本。但迄今为止,HotSpot JVM仍是性能最好且与Hadoop搭配运行最稳定的实现。http://wiki.apache.org/hadoop/HadoopJavaVersions页面给出了Hadoop目前几大著名企业实现的Hadoop集群中所使用的JDK版本,Hortonworks已经为JDK 1.6.0_31在RHEL5/CentOS5、RHEL6/CentOS6、SLES11运行Hadoop、HBase、Pig, Hive、HCatalog、Oozie、Sqoop等进行了认证。建议参考它们的测试结果进行选择。
在选择安装版本,Sun JDK有几种不同格式的安装包,其使用及功能上并没有区别;但如果在安装Hadoop使用CDH的RPM格式的包的话,它们依赖于RPM格式的JDK,不过,ASF提供的RPM包并没有定义任何外在的依赖关系,因此,其可以使用基于任何方式安装配置的JDK,但这也意味着得手动解决依赖关系。无论如何,一个生产环境的Hadoop集群应该运行在64位的操作系统上,JDK等也要使用相应的64位版本,否则,单JVM进程将无法使用大于2GB以上的内存。
除了JDK之外,Hadoop集群的正常运行还可能根据实际环境依赖于其它的一些软件以实现集群的维护、监控及管理等。这些软件诸如cron、ntp、ssh、postfix/sendmail及rsync等。cron通常用于在Hadoop集群中过期的临时文件、归档压缩日志等定期任务的执行;ntp则用于为集群的各节点实现时间同步;ssh并非是必须的,但在MapReduce或HDFS的master节点上一次性启动整个集群时通过要用到ssh服务;postfix/sendmail则用于将cron的执行结果通知给管理员;rsync可用于实现配置文件的同步等。

2、Hadoop的运行环境

2.1 各节点的主机名

Hadoop在基于主机引用各节点时会有一些独特的方式,这已经让很多的Hadoop管理员为此头疼不已。实际使用中,应该避免集群中的各节点尤其是从节点(DataNode和TaskTracker)使用localhost作为本机的主机名称,除非是在伪分布式环境中。

2.2 用户、组及目录

前文已经说明,一个完整的Hadoop集群包含了MapReduce集群和HDFS集群,MapReduce集群包含JobTracker和TaskTracker两类进程和许多按需启动的任务类进程(如map任务),HDFS集群包含NameNode、SecondaryNameNode和DataNode三类进程。安全起见,应该以普通用户的身份启动这些进程,并且MapReduce集群的进程与HDFS集群的进程还应该使用不同的用户,比如分别使用mapred和hdfs用户。使用CDH的RPM包安装Hadoop时,这些用户都会被自动创建,如果基于tar包安装,则需要手动创建这些用户。

Hadoop的每一个进程都会访问系统的各类资源,然而,Linux系统通过PAM限定了用户的资源访问能力,如可打开的文件数(默认为1024个)及可运行的进程数等,这此默认配置在一个略具规模的Hadoop集群中均会带来问题。因此,需要为mapred和hdfs用户修改这些限制,这可以在/etc/security/limits.conf中进行。修改结果如下。

# Allow users hdfs, mapred, and hbase to open 32k files. The

# type '-' means both soft and hard limits.

#

# See 'man 5 limits.conf' for details.

# user type resource value

hdfs - nofile 32768

mapred - nofile 32768

3、Hadoop的分布式模型

Hadoop通常有三种运行模式:本地(独立)模式、伪分布式(Pseudo-distributed)模式和完全分布式(Fully distributed)模式。

安装完成后,Hadoop的默认配置即为本地模式,此时Hadoop使用本地文件系统而非分布式文件系统,而且其也不会启动任何Hadoop守护进程,Map和Reduce任务都作为同一进程的不同部分来执行。因此,本地模式下的Hadoop仅运行于本机。此种模式仅用于开发或调试MapReduce应用程序但却避免了复杂的后续操作。

伪分布式模式下,Hadoop将所有进程运行于同一台主机上,但此时Hadoop将使用分布式文件系统,而且各jobs也是由JobTracker服务管理的独立进程。同时,由于伪分布式的Hadoop集群只有一个节点,因此HDFS的块复制将限制为单个副本,其secondary-master和slave也都将运行于本地主机。此种模式除了并非真正意义的分布式之外,其程序执行逻辑完全类似于完全分布式,因此,常用于开发人员测试程序执行。

要真正发挥Hadoop的威力,就得使用完全分布式模式。由于ZooKeeper实现高可用等依赖于奇数法定数目(an odd-numbered quorum),因此,生产环境中,完全分布式环境需要至少三个节点。

4、Hadoop集群伪分布式的实现
4.1 安装前的准备工作
本示例所演示的过程基于RHEL 6.3(64bit)平台,主机名为hadoop.magedu.com,用到的应用程序如下所示。

JDK采用的为Oracle的HotSpot JDK 1.6.0_31,64位版本,文件名为jdk-6u31-linux-x64-rpm.bin;
Hadoop采用的Hortonworks的HDP 1.1中提供的1.0版本的hadoop,tar包格式,文件名为hadoop-1.0.3.16.tar.gz;下载地址链接http://hortonworks.com/thankyou-hdp11/;
注意:本文演示中全部采用支持MRv1的Hadoop版本,因此其可以为CDH3中的0.20.2系列的Hadoop,或HDP 1.1中提供的1.0系列的hadoop。
安全起见,运行Hadoop需要以普通用户的身份进行,按前文的说明,运行MapReduce集群和HDFS集群应该以不同的用户进行。但这里仅为伪分布式模式,是为初步认识hadoop的运行,因此,这里只使用一个普通用户hadoop来完成。接下来建立运行hadoop进程的用户hadoop并给其设定密码;

   
   
   
   
  1. # useradd hadoop
  2. # echo "password" | passwd --stdin hadoop 

而后配置hadoop用户能够以基于密钥的验正方式登录本地主机,以便Hadoop可远程启动各节点上的Hadoop进程并执行监控等额外的管理工作。

   
   
   
   
  1. # su - hadoop
  2. $ ssh-keygen -t rsa -P '' 
  3. $ ssh-copy-id -i .ssh/id_rsa.pub hadoop@localhost

4.2 安装JDK
Hadoop依赖于1.6 update 8或更新版本的Java环境。本文采用的jdk是Oracle官方提供的rpm格式的安装包,在oracle官方的下载页面中即可找到合适的版本。其安装过程非常简单,使用类似如下命令即可。

   
   
   
   
  1. # chmod +x jdk-6u31-linux-x64-rpm.bin 
  2. # ./jdk-6u31-linux-x64-rpm.bin

Hadoop运行时需要能访问到如前安装的Java环境,这可以通过将其二进制程序(/usr/java/jdk1.6.0_31,如果其为其为当前系统上最高版本的JDK,通常会有链接/usr/java/latest指向此目录)所在的目录添加至PATH环境变量的路径中实现,也可以通过设定hadoop-env.sh脚本来进行(后文hadoop的配置章节会有说明)。这里采用前一种方式,编辑/etc/profile.d/java.sh,在文件中添加如下内容:

   
   
   
   
  1. JAVA_HOME=/usr/java/latest/
  2. PATH=$JAVA_HOME/bin:$PATH
  3. export JAVA_HOME PATH

而后切换至hadoop用户,并执行如下命令测试jdk环境配置是否就绪。

   
   
   
   
  1. # su - hadoop
  2. $ java -version

其输出内容应该如下面所示。

java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01, mixed mode)

4.3 hadoop安装配置

4.3.1 安装

   
   
   
   
  1. # tar xf hadoop-1.0.3.16.tar.gz -C /usr/local/
  2. # chown -R hadoop:hadoop /usr/local/hadoop-1.0.3.16/
  3. # ln -sv /usr/local/hadoop-1.0.3.16 /usr/local/hadoop

然后编辑/etc/profile.d/hadoop.sh,设定HADOOP_PREFIX环境变量的值为hadoop的解压目录,并让其永久有效。编辑/etc/profile,添加如下内容:

   
   
   
   
  1. HADOOP_PREFIX=/usr/local/hadoop
  2. PATH=$HADOOP_PREFIX/bin:$PATH
  3. export HADOOP_PREFIX PATH

切换至hadoop用户,并执行如下命令测试hadoop是否就绪。

   
   
   
   
  1. $ su - hadoop
  2. $ hadoop version

其输出内容应该为如下所示:
Hadoop 1.0.3.16
Subversion git://localhost.localdomain/ on branch hdp-hadoop-1.0.3.16 -r 6cbf3791d67a1c726ce81927045e54eb1f2e3a95
Compiled by jenkins on Mon Oct  1 00:25:03 PDT 2012
From source with checksum d351ec52aec40ae43fb833c8cc54a6c5

4.3.2 配置Hadoop工作于伪分布式模式

安装完成后的Hadoop默认配置就可以启动,但其工作于本地模式;为了模拟hadoop集群的工作环境,完成配置测试,MarReduce程序测试等工作,可以配置其在单台主机模拟提供分布式的hadoop,即伪分布式。
hadoop的配置共有四种级别:集群、进程、作业和单独操作,前两类由集群管理员负责配置,后面的两类则属于程序员的工作范畴。

hadoop的配置文件位于conf目录中,其中的core-site.xmlmapred-site.xmlhdfs-site.xml三个配置文件最为关键。core-site.xml用于配置hadoop集群的特性,它作用于全部进程及客户端,mapred-site.xml配置mapreduce集群的工作属性,hdfs-site.xml配置hdfs集群的工作属性。此三个文件均为XML格式,其每个属性配置请求格式如下:

    some.property.name
    some-value

另外还有三个配置文件需要留意。hadoop-env.sh是Hadoop的多个脚本执行时source的配置信息,其用于为Hadoop指定运行时使用的JDK、各进程的JDK属性、PID文件及日志文件的保存目录等。masters则用于指定辅助名称节点(SecondaryNameNode)的主机名或主机地址,slaves用于指定各从服务器(TaskTracker或DataNode)的主机名或主机地址。对伪分布式的Hadoop集群来讲,这些节点均为本机。
4.3.2.1 编辑conf/core-site.xml

   
   
   
   
  1.  
  2.  
  3.     hadoop.tmp.dir
  4.     /hadoop/temp
  5.  
  6.   
  7.  
  8.     fs.default.name
  9.     hdfs://localhost:8020
  10.     

上面示例中hadoop.tmp.dir属性用于定义Hadoop的临时目录,其默认为/tmp/hadoop-${username}。HDFS进程的许多目录默认都在此目录中,本示例将其定义到了/hadoop/temp目录,需要注意的是,要保证运行Hadoop进程的用户对其具有全部访问权限。fs.default.name属性用于定义HDFS的名称节点和其默认的文件系统,其值是一个URI,即NameNode的RPC服务器监听的地址(可以是主机名)和端口(默认为8020)。其默认值为file:///,即本地文件系统。

   
   
   
   
  1. # mkdir -p /hadoop/temp
  2. # chown -R hadoop:hadoop /hadoop

4.3.2.2 编辑conf/mapred-site.xml

运行MapReduce需要为其指定一个主机作为JobTracker节点,在一个小规模的Hadoop集群中,它通常跟NameNode运行于同一物理主机,在伪分布式环境中,其为本地主机。可以通过mapred.job.trakcer属性定义JobTracker监听的地址(或主机名)和端口(默认为8021),与前面的fs.default.name属性的值不同的是,这不是一个URI,而仅一个“主机-端口”组合。

在MapReduce作业运行过程中,中间数据(intermediate data)和工作文件保存于本地临时文件中。根据运行的MapReduce作业不同,这些数据文件可能会非常大,因此,应该通过mapred.local.dir属性为其指定一个有着足够空间的本地文件系统路径,其默认值为${hadoop.tmp.dir}/mapred/local。mapred.job.tracker可以接受多个以逗号分隔路径列表作为其值,并会以轮流的方式将数据分散存储在这些文件系统上,因此指定位于不同磁盘上的多个文件系统路径可以分散数据I/O。

另外,MapReduce使用分布式文件系统为各TaskTracker保存共享数据,这可以通过mapred.system.dir属性进行定义,其默认值为${hadoop.tmp.dir}/mapred/system。下面给出了一个较简单的mapred-site.xml文件示例。
   
   
   
   
  1.  
  2.  
  3.     mapred.job.tracker
  4.     localhost:8021
  5.  

4.3.2.3 编辑conf/hdfs-site.xml,定义hdfs的属性
HDFS集群进程有许多属性可以定义其工作路,如dfs.name.dir属性定义的HDFS元数据持久存储路径默认为${hadoop.tmp.dir}/dfs/name、dfs.data.dir属性定义的DataNode用于存储数据块的目录路径默认为${hadoop.tmp.dir}/dfs/data、fs.checkpoint.dir属性定义的SecondaryNameNode用于存储检查点文件的目录默认为${hadoop.tmp.dir}/dfs/namesecondary。
为了数据可用性及冗余的目的,HDFS会在多个节点上保存同一个数据块的多个副本,其默认为3个。而只有一个节点的伪分布式环境中其仅用保存一个副本即可,这可以通过dfs.replication属性进行定义。如下所示的内容即可作为最简单的hdfs-site.xml配置文件。

   
   
   
   
  1.  
  2.  
  3.     dfs.replication
  4.     1
  5.  

4.3.2.4 格式化名称节点

如普通文件系统一样,HDFS文件系统必须要先格式化,创建元数据数据结构以后才能使用。以hadoop用户运行如下命令即可实现。

   
   
   
   
  1. $ hadoop namenode -format

其输出信息应该如下面所示。

13/01/06 11:43:50 INFO namenode.NameNode: STARTUP_MSG: 
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG:   host = hadoop.magedu.com/172.16.200.11
STARTUP_MSG:   args = [-format]
STARTUP_MSG:   version = 1.0.3.16
STARTUP_MSG:   build = git://localhost.localdomain/ on branch hdp-hadoop-1.0.3.16 -r 6cbf3791d67a1c726ce81927045e54eb1f2e3a95; compiled by 'jenkins' on Mon Oct  1 00:25:03 PDT 2012
************************************************************/
13/01/06 11:43:51 INFO util.GSet: VM type       = 64-bit
13/01/06 11:43:51 INFO util.GSet: 2% max memory = 19.33375 MB
13/01/06 11:43:51 INFO util.GSet: capacity      = 2^21 = 2097152 entries
13/01/06 11:43:51 INFO util.GSet: recommended=2097152, actual=2097152
13/01/06 11:43:51 INFO namenode.FSNamesystem: fsOwner=hadoop
13/01/06 11:43:51 INFO namenode.FSNamesystem: supergroup=supergroup
13/01/06 11:43:51 INFO namenode.FSNamesystem: isPermissionEnabled=true
13/01/06 11:43:51 INFO namenode.FSNamesystem: dfs.block.invalidate.limit=100
13/01/06 11:43:51 INFO namenode.FSNamesystem: isAccessTokenEnabled=false accessKeyUpdateInterval=0 min(s), accessTokenLifetime=0 min(s)
13/01/06 11:43:51 INFO namenode.FSEditLog: dfs.namenode.edits.toleration.length = -1
13/01/06 11:43:51 INFO namenode.NameNode: Caching file names occuring more than 10 times 
13/01/06 11:43:51 INFO common.Storage: Image file of size 112 saved in 0 seconds.
13/01/06 11:43:51 INFO namenode.FSEditLog: closing edit log: position=4, editlog=/hadoop/temp/dfs/name/current/edits
13/01/06 11:43:51 INFO namenode.FSEditLog: close success: truncate to 4, editlog=/hadoop/temp/dfs/name/current/edits
13/01/06 11:43:51 INFO common.Storage: Storage directory /hadoop/temp/dfs/name has been successfully formatted.
13/01/06 11:43:51 INFO namenode.NameNode: SHUTDOWN_MSG: 
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at hadoop.magedu.com/172.16.200.11
************************************************************/

4.3.2.5 启动hadoop

Hadoop提供了2个脚本start-dfs.sh和start-mapred.sh,分别用于启动hdfs相关的进程和mapred相关的进程。事实上,为了使用的便捷性,在NameNode和JobTracker运行于同一主机的场景中,Hadoop还专门提供了脚本start-all.sh脚本来自动执行前述两个脚本。不过,需要注意的是,使用这类脚本启动Hadoop集群,其需要当前主机的当前用户能够通过ssh服务以基于密钥认证的方式访问任何一个从节点。
除此之外,管理员也可以使用hadoop-daemon.sh脚本手动启动某一个Hadoop进程,或使用脚本hadoop-daemons.sh脚本手动启动某些进程。
这里通过前一种方式中的start-all.sh脚本来一次性启动所有的进程。

   
   
   
   
  1. $ start-all.sh 

其会输出类似如下内容: 

starting namenode, logging to /usr/local/hadoop-1.0.3.16/libexec/../logs/hadoop-hadoop-namenode-hadoop.magedu.com.out
localhost: starting datanode, logging to /usr/local/hadoop-1.0.3.16/libexec/../logs/hadoop-hadoop-datanode-hadoop.magedu.com.out
localhost: starting secondarynamenode, logging to /usr/local/hadoop-1.0.3.16/libexec/../logs/hadoop-hadoop-secondarynamenode-hadoop.magedu.com.out
starting jobtracker, logging to /usr/local/hadoop-1.0.3.16/libexec/../logs/hadoop-hadoop-jobtracker-hadoop.magedu.com.out
localhost: starting tasktracker, logging to /usr/local/hadoop-1.0.3.16/libexec/../logs/hadoop-hadoop-tasktracker-hadoop.magedu.com.out

运行jps命令可查看正在运行的Hadoop进程。

   
   
   
   
  1. $ jps | grep -iv "jps"

显示结果类似如下内容:

28935 JobTracker

28840 SecondaryNameNode

28691 DataNode

28565 NameNode

29062 TaskTracker

4.3.2.6 Hadoop进程监听的地址和端口

Hadoop启动时会运行两个服务器进程,一个为用于Hadoop各进程之间进行通信的RPC服务器,另一个是提供了便于管理员查看Hadoop集群各进程相关信息页面的HTTP服务器。

用于定义各RPC服务器所监听的地址和端口的属性有如下几个:

  • fs.default.name:定义HDFS的NameNode用于提供URI所监听的地址和端口,默认端口为8020;
  • dfs.datanode.ipc.address:DataNode上RPC服务器监听的地址和端口,默认为0.0.0.0:50020;
  • mapred.job.tracker:JobTracker的PRC服务器所监听的地址和端口,默认端口为8021;
  • mapred.task.tracker.report.address:TaskTracker的RPC服务器监听的地址和端口;TaskTracker的子JVM使用此端口与TaskTracker进行通信,它仅需要监听在本地回环地址127.0.0.1上,因此可以使用任何端口;只有在当本地没有回环接口时才需要修改此属性的值;

除了RPC服务器之外,DataNode还会运行一个TCP/IP服务器用于数据块传输,其监听的地址和端口可以通过dfs.datanode.address属性进行定义,默认为0.0.0.0:50010。

可用于定义各HTTP服务器的属性有如下几个:

  • mapred.job.tracker.http.addrss:JobTracker的HTTP服务器地址和端口,默认为0.0.0.0:50030;
  • mapred.task.tracker.http.address:TaskTracker的HTTP服务器地址和端口,默认为0.0.0.0:50060;
  • dfs.http.address:NameNode的HTTP服务器地址和端口,默认为0.0.0.0:50070;
  • dfs.datanode.http.address:DataNode的HTTP服务器地址和端口,默认为0.0.0.0:50075;
  • dfs.secondary.http.address:SecondaryNameNode的HTTP服务器地址和端口,默认为0.0.0.0:50090;

上述的HTTP服务器均可以通过浏览器直接访问以获取对应进程的相关信息,访问路径为http://Server_IP:Port。如JobTracker的相关信息:

Hadoop系列之九:Hadoop集群伪分布式模式的实现详解_第1张图片

还有NameNode的相关信息:

Hadoop系列之九:Hadoop集群伪分布式模式的实现详解_第2张图片

参考文献:

Hadoop Operations

Hadoop In Action

Hadoop The Definative Guide 3rd Edtion

Hadoop Documentation