实验室里有一个小型的Hadoop集群,是由一个学弟在做本科毕设的时候搭建的。本想偷偷懒,直接用他搭建的环境跑跑实验,可是当初给每个节点的操作系统分配的磁盘空间有限,在跑一些数据量较大迭代次数较多的实验的时候,运行到一半就会导致磁盘空间不足,程序无法继续执行。具体报的错误是“could only be replicated to 0 nodes, instead of 1”。没有办法,为了以后能长时间方便使用集群环境,只能自己重新搭建。
资源介绍:实验室里有六七台空闲主机,我选了其中四台配置还算不错的,用来作为集群环境的主机。由于主机是分批购买的,配置都不太一样,但是大概都满足以下条件: CPU > 2.0HZ, RAM > 2G, 硬盘 500G。
接下来就是整个集群环境搭建的具体步骤。
Step 1. 装系统
我选用的操作系统是Ubuntu 11.04,具体的安装过程就省略了。我在这里只列出磁盘分区、创建用户、主机命名和分配IP的情况。
每台主机的磁盘分区都一致,具体如表1所示。
分区名 | 大小(MB) |
/ | 204800 |
/boot | 200 |
swap | 1024 |
/home | 204800 |
四台主机上都创建了同样的用户,用户名为dummy,密码为dummy
IP地址和主机名的对应关系如表2所示。
IP地址 | 主机名 |
192.168.2.100 | master |
192.168.2.101 | slave1 |
192.168.2.102 | slave2 |
192.168.3.103 | slave3 |
为了方便后面的配置,可以将表2保存在文件ip-host中,文件中的每一行对应表2中的一行,每一行中的IP地址与主机名用tab分隔。文件ip-host如下所示。
#ip-host映射关系
192.168.2.100 master
192.168.2.101 slave1
192.168.2.102 slave2
192.168.2.103 slave3
如果想更改已有系统的主机名,可以采用以下方法(方法中的oldHostName是原来的主机名,newHostName是希望更改后的主机名):
1. sudo su启用root用户
2. 将/etc/hosts文件里的 127.0.1.1 oldHostName 改为 127.0.1.1 newHostName
3. 将/etc/hostname文件中的oldHostName替换为newHostName
4. 运行命令 hostname newHostName
5. exit退出root用户
重启系统修改即可生效。
Step 2. 配置SSH
SSH的配置过程很简单,目的是使master能无密码登录到各个slave节点上。基本过程如下:
(1)在每台主机上运行命令 sudo apt-get install openssh-server 安装ssh server。
(2)在master节点上以dummy用户运行 ssh-keygen -t rsa,一路回车,在/home/dummy/.ssh/下生成密钥对id_rsa和id_rsa.pub。
(3)将master节点上生成的id_rsa.pub复制到各个从节点的/home/dummy/.ssh/下(如果没有.ssh目录可以手动创建),在各个从节点上进入目录/home/dummy/.ssh/,使用命令cat id_rsa.pub >> authorized_keys,将master节点上生成的的公钥id_rsa.pub附加到authorized_keys文件中。
(4)在各个从节点上,sudo su启用root用户,修改/etc/ssh/sshd_config,找到文件中的PasswordAuthentication项,将其值修改为no,保存文件并退出。
(5)在各个从节点上,使用命令service ssh restart重启ssh server,以使配置生效。
(6)ssh配置完成后,将Step1中提到的ip-host文件也复制到各个从节点上。在每个从节点上,切换到root用户,使用命令cat ip-host >> /etc/hosts将映射表附加到hosts文件末尾。
以上都配置完成后,master可以通过ssh登录到各个从节点。可以在master节点上通过使用命令ssh dummy@slave1; ssh dummy@slave2; ssh dummy@slave3来验证。如果配置正确无误,那么master节点可以成功登录每个从节点。
Step 3. 安装JDK
在主节点和各个从节点上都要安装JDK,JDK的安装过程如下所示。
(1)在主节点上,从oracle官网下载"Java SE 6 Update 33",下载的文件类型为可以自我解压的bin文件,文件名为jdk-6u33-linux-i586.bin。
(2)在主节点的目录/home/dummy/下创建一个文件夹,命名为“.java”,将下载的文件置于/home/dummy/.java/下。
(3)进入主节点/home/dummy/.java/目录下,运行命令 chmod a+x jdk-6u33-linux-i586.bin,使该文件变为可执行文件,然后运行命令./jdk-6u33-linux-i586.bin,解压该文件到当前目录下。命令执行成功后会在当前目录下产生一个名字为jdk1.6.0_33的文件夹。为了节省磁盘空间解压后可以删除jdk-6u33-linux-i586.bin。
(4)进入主节点/home/dummy/下,打开该目录下的.bashrc文件,在文件末尾添加如下两行代码。
export JAVA_HOME=/home/dummy/.java/jdk1.6.0_33
export PATH=$JAVA_HOME/bin:$PATH
(5)在主节点的命令行里输入 source .bashrc,以使修改立即生效。
(6)在每个从节点上重复步骤(1)~(5),以便每个从节点上都安装JDK。当然也有更加快捷的方法,在主节点上运行如下命令。
scp /home/dummy/.bashrc dummy@salve1:~/
scp -r /home/dummy/.java dummy@slave1:~/
scp /home/dummy/.bashrc dummy@salve2:~/
scp -r /home/dummy/.java dummy@slave2:~/
scp /home/dummy/.bashrc dummy@salve3:~/
scp -r /home/dummy/.java dummy@slave3:~/
#!!!!!为了使配置立即生效,在每个从节点上都要运行source .bashrc命令。
以上都配置完成,在每个节点的命令行中输入java -version验证配置是否成功。如果出现如下的响应信息,则说明配置已经成功。
java version "1.6.0_33"
Java(TM) SE Runtime Environment (build 1.6.0_33-b03)
Java HotSpot(TM) Server VM (build 20.8-b03, mixed mode)
Step 4. 安装Hadoop
当前Hadoop最高的稳定版本是1.0.3。本次安装使用的Hadoop的版本为hadoop-0.20.203.0 。两个版本的安装过程基本上相同。0.20为一个过渡版本,0.20版本之前和之后的编程API有了比较大的变化,它作为一个呈前启后的版本,既可以使用旧版本的API,又可以使用新版本的API。具体安装过程如下所示。
(1)首先在主节点和各个从节点上创建如下的目录结构:
/home/dummy/hadoop/hadoop-0/
/home/dummy/hadoop/hadoop-1/(该目录用于以后使用1版本)
(2)在主节点上,从Apache的官方网站下载hadoop-0.20.203.0rc1.tar.gz,运行命令 tar zxvf hadoop-0.20.203.0rc1.tar.gz解压该文件,并将解压后的文件hadoop-0.20.203.0移动到/home/dummy/hadoop/hadoop-0/目录下。
(3)进入主节点目录/home/dummy/hadoop/hadoop-0/hadoop-0.20.203.0/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>
<property>
<name>fs.default.name</name>
<value>hdfs://master:54320</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/dummy/hadoop/hadoop-0/tmp</value>
</property>
</configuration>
<!-- mapred-site.xml -->
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>mapred.job.tracker</name>
<value>192.168.2.100:54321</value><!-- 保险起见这里写master对应的IP地址 -->
</property>
</configuration>
<!-- hdfs-site.xml -->
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value> <!-- 复制因子一般为3,由于实验数据比较大,取了1-->
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
</configuration>
输入下面的命令修改masters文件:
echo master > masters
输入下面的命令修改slaves文件:
echo -e 'slave1\nslave2\nslave3' > slaves
在hadoop-env.sh文件中找到以#export JAVA_HOME开头的一行,去掉#,将其值修改为如下形式:
export JAVA_HOME=/home/dummy/.java/jdk1.6.0_33
(4)进入主节点目录/home/dummy/hadoop/hadoop-0/,运行如下的命令将hadoop拷贝到各个从节点
scp -r hadoop-0.20.203.0 dummy@slave1:~/hadoop/hadoop-0/
scp -r hadoop-0.20.203.0 dummy@slave2:~/hadoop/hadoop-0/
scp -r hadoop-0.20.203.0 dummy@slave3:~/hadoop/hadoop-0/
(5)在主节点上打开/home/dummy/.bashrc文件,添加下面两行代码。
export HADOOP_HOME=/home/dummy/hadoop/hadoop-0/hadoop-0.20.203.0
export PATH=$HADOOP_HOME/bin:$PATH
(6)在主节点上运行命令 hadoop namenode -format来格式化HDFS以准备好存储数据。
(7)在主节点上运行命令 start-all.sh,以启动Hadoop的守护进程。
如果以上配置都正确,在主节点上运行jps命令可以看到如下信息:
12213 Jps
11505 JobTracker
11432 SecondaryNameNode
11217 NameNode
从主节点登录到从节点运行jps命令可以看到如下的信息
12240 Jps
11516 DataNode
11662 TaskTracker
以上信息显示,hadoop已经安装成功,可以使用搭建好的集群环境跑MapReduce程序了。
PS: 昨天下午用刚刚搭建好的集群环境跑了一个处理Twitter数据集的程序,这个数据集描述的是社交关系网络,整个文件大小为1.2GB。用MapReduce框架实现了一个PageRank算法,对该数据集进行处理。这回迭代多次也没有问题了。