Ubuntu上安装,请参考我的另一篇博客,在Ubuntu上安装Hadoop。
环境:CentOS 6.5, OPenJDK 1.7, Hadoop 1.2.1
本文主要参考官网的文档,Hadoop 1.2.1 Getting Started
##1 单机模式(Standalone Mode)
为了能顺利安装成功,我们先练习在单台机器上安装Hadoop。在单台机器上,可以配置成单机模式(Standalone Mode)和伪分布式模式(Pseudo-Distributed Mode),参考官方文档Single Node Setup。
###1.1 下载Hadoop 1.2.1,解压
用浏览器下载或wget,
$ wget http://mirror.olnevhost.net/pub/apache/hadoop/common/stable1/hadoop-1.2.1-bin.tar.gz
$ tar -zxf hadoop-1.2.1-bin.tar.gz -C ~/local/opt
$ cd ~/local/opt/hadoop-1.2.1
###1.2 编辑 conf/hadoop-env.sh,设置 JAVA_HOME
$ echo $JAVA_HOME
/usr/lib/jvm/java
$ vim conf/hadoop-env.sh
取消JAVA_HOME
那一行的注释,设置正确的JDK位置
export JAVA_HOME=/usr/lib/jvm/java
###1.3 运行一个job
默认情况下,Hadoop就被配置为Standalone模式了,此时Hadoop的所有模块都运行在一个java进程里。
我们运行一个例子测试一下。下面的几行命令,把 conf
下的所有xml文件作为输入,在文件中查找指定的正则表达式,把匹配的结果输出到output
目录。
$ mkdir input
$ cp conf/*.xml input
$ bin/hadoop jar hadoop-examples-*.jar grep input output 'dfs[a-z.]+'
$ cat output/*
可以看到正常的结果,说明单机模式运行成功了,下面开始配置伪分布式模式。
##2 伪分布式模式(Pseudo-Distributed Mode)
Hadoop能在单台机器上以伪分布式模式运行,即每个Hadoop模块运行在单独的java进程里。
###2.1 编辑 conf/hadoop-env.sh,设置 JAVA_HOME
$ echo $JAVA_HOME
/usr/lib/jvm/java
$ vim conf/hadoop-env.sh
###2.2 设置无密码SSH登录
先检查一下是能够无密码登录本机,
ssh localhost
如果提示输入密码,说明不能,按如下步骤设置。
$ ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
###2.3 配置
conf/core-site.xml:
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
</property>
</configuration>
conf/hdfs-site.xml:
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
</configuration>
conf/mapred-site.xml:
<configuration>
<property>
<name>mapred.job.tracker</name>
<value>localhost:9001</value>
</property>
</configuration>
###2.4 启动Hadoop
格式化namenode
$ bin/hadoop namenode -format
启动 Hadoop 后台进程
$ bin/start-all.sh
Hadoop的log写入到了${HADOOP_HOME}/logs
目录下。
现在可以用浏览器打开NameNode和JobTracker的web界面了。
- NameNode - http://localhost:50070/
- JobTracker - http://localhost:50030/
###2.5 运行一个例子
运行的例子跟单机模式下的例子相同。
将输入数据拷贝到分布式文件系统中:
$ bin/hadoop fs -put conf input
运行 Hadoop 自带的例子:
$ bin/hadoop jar hadoop-examples-*.jar grep input output 'dfs[a-z.]+'
查看输出文件:
$ bin/hadoop fs -cat output/*
1 dfs.replication
1 dfs.server.namenode.
1 dfsadmin
结束后,关闭 Hadoop:
$ bin/stop-all.sh
stopping jobtracker
localhost: stopping tasktracker
stopping namenode
localhost: stopping datanode
localhost: stopping secondarynamenode
##3 分布式模式(Fully-Distributed Mode)
主要参考官方文档Cluster Setup.
###3.1 准备3台机器
如果你已经有了三台机器,这一步可以省略。
如果没有,则可以用VMware Workstation 或 VirtualBox创建3台虚拟机。首先用vmware workstation 新建一台CentOS 6.5,装好操作系统,选择 Basic Server,安装JDK,参考我的另一篇博客,安装和配置CentOS服务器的详细步骤。安装好后然后用浅拷贝Create a linked clone
克隆出2台,这样有了3台虚拟机。启动3台机器,假设IP分别为192.168.1.131, 192.168.1.132, 192.168.1.133
, 131做为NameNode,JobTracker和SecondaryNameNode,身兼3个角色,这3个角色应该放到3台不同的机器上,这里为了简化,用一台机器来做3个角色;132和133为 slave。三台机器上的用户名是hadoop
,也可以用其他用户名,但必须三台机器都相同。
####3.1.1 关闭防火墙
临时关闭防火墙
$ sudo service iptables stop
下次开机后,防火墙还是会启动。
永久关闭防火墙
$ sudo chkconfig iptables off
由于这几台虚拟机是开发机,不是生产环境,因此不必考虑安全性,可以永久关闭防火墙,还能给开发阶段带来很多便利。
####3.1.2 修改hostname
如果集群中的每一台机器事先已经有了hostname,则这一步可以跳过。
这一步看起来貌似不必要,其实是必须的,否则最后运行wordcount等例子时,会出现“Too many fetch-failures”。因为HDFS用hostname而不是IP,来相互之间进行通信(见后面的注意1)。
在CentOS上修改hostname,包含两个步骤(假设将hostname1改为hostname2,参考这里,但不需要第一步):
- 将
/etc/sysconfig/network
內的 HOSTNAME 改成 yourhostname - 用
hostname
命令,临时修改机器名,sudo hostname yourhostname
用exit
命令退出shell,再次登录,命令提示字符串就会变成[username@yourhostname ~]$
。
用上述方法,将131改名为master,132改名为slave01,133改名为slave02。
注意,对于有的Ubuntu/Debia 系统,会把本机的hostname解析成 127.0.1.1,例如:
127.0.0.1 localhost
127.0.1.1 master
将第二行改为(参考利用Cloudera实现Hadoop)
127.0.0.1 master
####3.1.3 修改所有机器的/etc/hosts
文件
在所有机器的/etc/hosts
文件中,添加所有hostname对应的IP,一般在一台机器上设置好,然后scp到所有机器。例如
192.168.1.131 master
192.168.1.132 slave01
192.168.1.133 slave02
##3.2 配置 master 无密码登陆到所有机器(包括master自己登陆自己)
参考我的另一篇博客,SSH无密码登录的配置
##3.3 把Hadoop压缩包上传到所有机器,并解压
将 hadoop-1.2.1-bin.tar.gz 上传到所有机器,然后解压。注意,所有机器的hadoop路径必须一致,因为master会登陆到slave上执行命令,master认为slave的hadoop路径与自己一样。
下面开始配置,配置好了后,把conf 目录scp到所有其他机器。
###3.4 修改6个配置文件
Hadoop的配置文件比较多,其设计原则可以概括为如下两点:
- 尽可能模块化。例如core-xxx.xml是针对基础公共库core的,hdfs-xxx.xml是针对分布式文件系统HDFS的,mapred-xxx.xml是针对分布式计算框架MapReduce的。
- 动静分离。例如,在Hadoop 1.0.0之前,作业队列权限管理相关的配置被放在mapred-site.xml里,而该文件爱你是不可以动态加载的,每次修改后必须重启Hadoop,但从 1.0.0后,这些配置选项被剥离出来放到独立的配置文件mapred-queue-acls.xml中,该文件可以通过Hadoop命令动态加载。在conf下,core-default.xml, hdfs-default.xml和mapred-default.xml是只读的,core-site.xml, hdfs-site.xml和mapred-site.xml才是用户可以修改的。要想覆盖默认配置,就在xxx-site.xml里修改。
以下操作在master上进行。
###3.4.1 conf/hadoop-env.sh
在 conf/hadoop-env.sh里,设置 JAVA_HOME
。如果集群中,每台机器的JDK不一定统一安装在同一个路径,那就要在每个节点的hadoop-env.sh里分别设置JAVA_HOME
。
export JAVA_HOME=/usr/lib/jvm/java
还要设置HADOOP_PID_DIR
,这里我们令其为HADOOP_PID_DIR=/home/hadoop/local/var/hadoop/pids
,参考Hadoop的pid配置。
export HADOOP_PID_DIR=/home/hadoop/local/var/hadoop/pids
注意,还要禁用IPv6,用命令cat /proc/sys/net/ipv6/conf/all/disable_ipv6
检查一下系统是否启用了IPv6,如果是0,说明启用了。Hadoop在IPv6的情况下运行不正常,因此需禁用IPv6。
不过我们不用真的禁用IPv6,还有另外一种方法,让java优先选择IPv4即可,在conf/hadoop-env.sh 里添加如下一行,
export HADOOP_OPTS="-server -Djava.net.preferIPv4Stack=true $HADOOP_OPTS"
参考Disabling IPv6,以及Web Crawling and Data Mining with Apache Nutch这本书的第66页。
###3.4.2 conf/masters
master
###3.4.3 conf/slaves
slave01
slave02
这里解释一下,masters文件,存放的其实是SecondaryNameNode。关于masters和slaves两个配置文件,更精确的说明见这个StackOverflow答案,hadoop conf/masters and conf/slaves on jobtracker?
###3.4.4 conf/core-site.xml
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://master:9000</value>
</property>
<property>
<name>fs.checkpoint.dir</name>
<value>/home/hadoop/local/var/hadoop/dfs/namesecondary</value>
</property>
</configuration>
Hadoop会自动创建目录。
###3.4.5 conf/hdfs-site.xml
<configuration>
<property>
<name>dfs.name.dir</name>
<value>/home/hadoop/local/var/hadoop/dfs/name</value>
</property>
<property>
<name>dfs.data.dir</name>
<value>/home/hadoop/local/var/hadoop/dfs/data</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
</configuration>
我们只有2台slave,因此dfs.replication
设置为2。
Hadoop会自动在master创建 /home/hadoop/local/var/hadoop/dfs/name 目录,在 slaves上创建 /home/hadoop/local/var/hadoop/dfs/data 目录。
###3.4.6 conf/mapred-site.xml
<configuration>
<property>
<name>mapred.job.tracker</name>
<value>master:9001</value>
</property>
<property>
<name>mapred.local.dir</name>
<value>/home/hadoop/local/var/hadoop/mapred/local</value>
</property>
<property>
<name>mapreduce.jobtracker.staging.root.dir</name>
<value>/user</value>
</property>
</configuration>
###3.5 将配置文件拷贝到所有slaves
$ cd ~/local/opt/hadoop-1.2.1/conf/
$ scp hadoop-env.sh core-site.xml hdfs-site.xml mapred-site.xml masters slaves hadoop@slave01:~/local/opt/hadoop-1.2.1/conf/
$ scp hadoop-env.sh core-site.xml hdfs-site.xml mapred-site.xml masters slaves hadoop@slave02:~/local/opt/hadoop-1.2.1/conf/
###3.6 运行 hadoop
在master上执行以下命令,启动hadoop
$ cd ~/local/opt/hadoop-1.2.1/
#只需一次,下次启动不再需要格式化,只需 start-all.sh
$ bin/hadoop namenode -format
$ bin/start-all.sh
###3.7 检查是否启动成功
在master上执行:
$ jps
2615 NameNode
2767 JobTracker
2874 Jps
在一台slave上执行:
$ jps
3415 DataNode
3582 TaskTracker
3499 SecondaryNameNode
3619 Jps
在另一台slave上执行:
$ jps
3741 Jps
3618 DataNode
3702 TaskTracker
可见进程都启动起来了,说明hadoop运行成功。
###3.8 运行wordcount例子,进一步测试是否安装成功
将输入数据拷贝到分布式文件系统中:
$ cd ~/local/opt/hadoop-1.2.1/
$ bin/hadoop fs -put conf input
运行 Hadoop 自带的例子:
$ bin/hadoop jar hadoop-examples-*.jar wordcount input output
查看输出文件:
$ bin/hadoop fs -ls output
$ bin/hadoop fs -cat output/part-r-00000
如果能看到结果,说明这个例子运行成功。
###3.9 停止 hadoop集群
在master上执行:
$ bin/stop-all.sh
###3.10 (可选)在master上设置环境变量HADOOP_PREFIX,并将HADOOP_PREFIX/bin加入PATH
这一步是为了将bin目录加入PATH,这样可以在任何位置执行hadoop的各种命令。这步是可选的。
Hadoop不推荐使用HADOOP_HOME
,你可以试一下,当设置了HADOOP_HOME
后,执行bin/start-all.sh
,第一行会打印出一行警告信息,Warning: $HADOOP_HOME is deprecated.
应该用HADOOP_PREFIX
代替,见邮件列表里的这封邮件。
给所有机器设置环境变量HADOOP_PREFIX
,并将$HADOOP_PREFIX/bin
加入PATH。
在 ~/.bashrc
中添加如下4行:
export HADOOP_PREFIX=$HOME/local/opt/hadoop-1.2.1
export PATH=$PATH:$HADOOP_PREFIX/bin
source使之立刻生效,
$ source ~/.bashrc
##4. 排除错误
本文已经尽可能的把步骤详细列出来了,但是我相信大部分人不会一次成功。这时候,查找错误就很重要了。查找错误最重要的手段是查看hadoop的日志,一般在logs目录下。把错误消息复制粘贴到google,搜索一下,慢慢找错误。
##注意
- 所有配置文件只能用hostname,不能用IP。两年前我不懂,还为此在stackoverflow上发了帖子。hadoop会反向解析hostname,即使是用了IP,也会使用hostname 来启动TaskTracker。参考hdfs LAN ip address hostname resolution,hadoop入门经验总结- 杨贵堂的博客,hadoop集群配置。
- 在第2.5步骤,如果出现
SafeModeException
异常,不用担心,等待几分钟即可。因为hadoop刚刚启动时,会进入安全模式进行自检,这需要花点时间。 - 如果在任何一步失败,可以
stop-all.sh
, 然后hadoop namenode -format
,重试几次,一般可以成功。如果还是不成功,多看看 logs目录下的日志文件,把错误消息复制粘贴到google,搜索答案。