记录一下 hadoop 集群的搭建过程,一共 3 台机器,操作系统都是 debian 6,hadoop 版本是1.0.4,jre 是源里的 openjdk-6。hadoop 官网的说明挺详细,就是不能快速搭建出一个能跑的环境。在网上找到一篇文章(见参考资料 [1]),虽然文章中用的是 0.20 版本,但是在 1.0.4 上也适用。
这里使用 master,slave1 和 slave2 分别作为三台机器的主机名。为了操作方便,每台机器上都有一个用户 hadoop,密码都一样。以下的配置操作都在 master 上进行。
hadoop 的配置(2013.03.16 更新)
把下载到的 hadoop-1.0.4.tar.gz 解压到 hadoop 的家目录下,建立一个软链接 hadoop 指向解压得到的目录,这样以后更新只需重新建立软链接指向新版本即可。
进入解压后的目录,根据实际情况修改 conf/hadoop-env.sh 中的 JAVA_HOME,使其指向 jdk 的安装目录:
export JAVA_HOME=/usr/lib/jvm/java-6-openjdk
在1.0.4 版本中不需要 HADOOP_HOME 这个环境变量,如果设置了这个变量执行命令的时候会提示“Warning: $HADOOP_HOME is deprecated.”。
然后修改 conf/core-site.xml:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<!-- 用于dfs命令模块中指定默认的文件系统协议 -->
<property>
<name>fs.default.name</name>
<value>hdfs://master:9000/</value>
</property>
<!-- 缓冲区大小,默认4k -->
<!--<property>-->
<!--<name>io.file.buffer.size</name>-->
<!--<value>4194304</value>-->
<!--</property>-->
</configuration>
修改 conf/hdfs-site.xml:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<!-- DFS中存储文件命名空间信息的目录 -->
<property>
<name>dfs.name.dir</name>
<value>/home/hadoop/data/dfs.name.dir</value>
</property>
<!-- DFS中存储文件数据的目录 -->
<property>
<name>dfs.data.dir</name>
<value>/home/hadoop/data/dfs.data.dir</value>
</property>
<!-- 是否对DFS中的文件进行权限控制(测试中一般用false)-->
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
<!-- 数据需要备份的数量,默认是3 -->
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<!-- 数据块大小,单位是字节。必须是512的倍数,因为采用crc校验 -->
<!--<property>-->
<!--<name>dfs.block.size</name>-->
<!--<value>4194304</value>-->
<!--</property>-->
</configuration>
修改conf/mapred-site.xml:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<!-- 用来作JobTracker的节点的(一般与NameNode保持一致) -->
<property>
<name>mapred.job.tracker</name>
<value>master:9001</value>
</property>
<!-- map/reduce的系统目录(使用的HDFS的路径) -->
<property>
<name>mapred.system.dir</name>
<value>mapred.system.dir</value>
</property>
<!-- map/reduce的临时目录(可使用“,”隔开,设置多重路径来分摊磁盘IO) -->
<property>
<name>mapred.local.dir</name>
<value>/home/hadoop/data/mapred.local.dir</value>
</property>
<!--<property>-->
<!--<name>mapred.map.tasks</name>-->
<!--<value>3</value>-->
<!--</property>-->
<!-- 使用hdfs路径 -->
<property>
<name>mapreduce.jobtracker.staging.root.dir</name>
<value>/user</value>
</property>
<!--超时设置-->
<!--<property>-->
<!--<name>mapred.task.timeout</name>-->
<!--<value>0</value>-->
<!--</property>-->
</configuration>
最后在 conf/masters 中添加 master 机器的 ip 或主机名:
master
在 conf/slaves 中添加所有 salves,一行一个:
slave1
slave2
其它的配置项使用默认的即可,以上选项具体作用可以参考官网说明和参考资料 [1]。
然后把配置好的 hadoop-1.0.4 整个目录分别复制到每台 slave 机器的 hadoop 的家目录下,并且建立软链接 hadoop。至此 hadoop 的配置就完成了。
ssh 的配置
因为 master 需要 ssh 登录到 slave 上进行某些操作,因此使用公钥认证的方式,避免手动输入密码。
使用命令
ssh-keygen -t rsa
在 $HOME/.ssh 下生成两个文件:id_rsa 和 id_rsa.pub。把 id_rsa.pub 的内容添加到 authorized_keys 中:
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
把 authorized_keys 复制到每个 slave 上的 ~/.ssh 目录下。完成后在 master 测试一下 ssh 登录 slave1 和 slave2,这时应该能直接登录而不用手动输入密码了。
启动和停止 hadoop
以上配置完后就可以启动 hadoop 了。先格式化新的 hdfs:
$HOME/hadoop/bin/hadoop namenode -format
然后启动 hdfs 服务:
$HOME/hadoop/bin/start-dfs.sh
最后启动 map/reduce:
$HOME/hadoop/bin/start-mapred.sh
停止 hadoop 时先停止 map/reduce 服务:
$HOME/hadoop/bin/stop-mapred.sh
再停止 hdfs 服务:
$HOME/hadoop/bin/stop-dfs.sh
另外也可以用 $HOME/hadoop/bin 下的 start-all.sh 和 stop-all.sh 来启动和停止。
一些问题和解决方法
从网上找到的答案,顺手做的笔记,没记下出处。
Q:执行 hadoop -put 时报错:Name node is in safe mode.
A:hadoop dfsadmin -safemode leave
Q:reduce 执行到 16% 或 17% 时停住不动,查看 hadoop-{user}-jobtracker-{host}.log 中有这样一条错误提示:Failed fetch notification #1 for map task:
A:在每台机器中的 /etc/hosts 中填写其它机器的 ip 和对应的主机名,不管在配置文件中写的是 ip 还是主机名。
Q:出现错误:File /user/hadoop/test could only be replicated to 0 nodes, instead of 1
A:停止 hadoop,删除 hdfs 目录和 /tmp/hadoop-{user}* 和 /tmp/hsperfdata_{user}/,重新格式化,然后重启 hadoop 服务。
Q:出现错误:org.apache.hadoop.util.DiskChecker$DiskErrorException: Could not find any valid local directory for ttprivate/taskTracker/hadoop/jobcache/job_201207301453_0036/jobToken
at org.apache.hadoop.fs.LocalDirAllocator$AllocatorPerContext.getLocalPathForWrite(LocalDirAllocator.java:381)
at org.apache.hadoop.fs.LocalDirAllocator.getLocalPathForWrite(LocalDirAllocator.java:146)
at org.apache.hadoop.fs.LocalDirAllocator.getLocalPathForWrite(LocalDirAllocator.java:127)
at org.apache.hadoop.mapred.TaskTracker.localizeJobTokenFile(TaskTracker.java:4271)
at org.apache.hadoop.mapred.TaskTracker.initializeJob(TaskTracker.java:1177)
at org.apache.hadoop.mapred.TaskTracker.localizeJob(TaskTracker.java:1118)
at org.apache.hadoop.mapred.TaskTracker$5.run(TaskTracker.java:2430)
at java.lang.Thread.run(Thread.java:636)
A:重启一下出问题的 slave,不行的话同上操作
Q:Caused by: java.lang.OutOfMemoryError: Java heap space
A:修改 conf/mapred-site.xml,修改 mapred.child.java.opts 的值为 -Xmx512m 或更大。
Q: 出现错误 ERROR security.UserGroupInformation: PriviledgedActionException as:ou cause:org.apache.hadoop.security.AccessControlException: org.apache.hadoop.security.AccessControlException: Permission denied: user=ou, access=EXECUTE, inode="":hadoop:supergroup:rwx------
A: 两个解决方法:(1) 在 ~/.bashrc 中添加一句:export HADOOP_USER_NAME='hadoop',这样每个用户都默认使用 hadoop 执行;(2)在 mapred-site.xml 中添加选项:
<property>
<name>mapreduce.jobtracker.staging.root.dir</name>
<value>/user</value>
</property>