在Ubuntu Server 8.10上搭建Hadoop-0.19.0环境
在UbuntuServer8.10上搭建基于Hadoop-0.19.0的分布式运行环境
(VMwareworkstation版)
长期以来,一直很喜欢研究分布式的技术,也一直想尝试搭建一个分布式编程环境,最近看到一些文章讨论Hadoop很多,而且也看到Google也使用Hadoop开发了搜索引擎,因此想尝试着自己也弄一个玩玩,在网上查到了几篇文章讨论了Hadoop环境的搭建,但是讲的都不是很明白,我跟随这些文章Stepbystep,本以为会是很顺利,但是却遇到诸多磕磕绊绊,很棘手,在网上查了很久,试了很多方法,走了很多弯路才最终解决。好在所有问题都解决了,昨天晚上,终于把环境搭起来,并运行了一遍,Hadoop的Wordcount例子,很顺利地通过了,今天准备把自己的这些天的“搭建之旅”,讲出来,算是给自己的工作做一个注解吧。
之所以选择Ubuntu,是因为这个操作系统很简洁,很容易配置,而且占用硬盘空间比较小,我的T61上2G内存支持2个虚拟机Ubuntu服务器是没问题的,而且速度很快,虚拟机环境我选择的是VMware-workstation-6.5.1-126130,官网上Download的。开始在我的XPProfessional上安装VMware,并在它上面安装UbuntuServer8.10,一切都很顺利,都是默认设置,包括硬盘(8G)和内存(512M)分配等,配置低可要吃苦头哦,值得一提的有两点,
1、Ubuntu在安装时候需要把SSHServer安装上,这样免得你以后安装SSH软件比较麻烦,因为Hadoop是通过SSH来与各个机器通讯的。安装时候记得不不要安装Ubuntu自带的JDK,也就是VirualMachineHost(BSDOpenJDK),没用,我们需要的SUNJDK。
2、是网络配置,现在网上很多讲VM上网络配置的文章,我看了好几篇都没有看明白,也是因为自己一直没有碰过VMware。别的不说了,我只说一下我的经历吧,我在家里搭建了一个环境,在单位也搭建了一个环境。家里的是宽带PPPoE上网的,单位是静态IP的局域网通过代理上网。由于我不想用NAT上网,所以就都用了Bridged的方式,而且都是Replicatedphysicalnetworkconnectionstate,这种方式使得虚拟机都在独立存在于网上的,容易访问,有种看得见摸得找的感觉。
网址的配置
家里:我使用的是DHCP动态分配网址,配置文件/etc/network/interfaces,我没有改动,就是:
ifaceeth0inetdhcp
autoeth0
单位:修改了/etc/network/interfaces,添加了IP地址,子网掩码,网关。
ifaceeth0inetstatic
address10.8.83.200
netmask255.255.255.0
gateway10.8.83.254
autoeth0
命令如下:sudovi/etc/network/interfaces,至于vi的操作命令俺在这里就不说了,自己上网查吧。
DNS配置:
家里的配置,我也没有管,也是自动获取的。而单位的配置是修改了/etc/resolv.conf文件。在文件的最末行添加了以下代码:nameserver10.8.83.11。
还有重要的两个配置需要注意:
1、需要配置/etc/hostname:
命令如下:sudo/etc/hostname
改掉localhost,换成,你自己喜欢的名字,如我的就是ubuntu1,这样你安装的系统就有了一个主机名了,但是一定唯一。
2、需要配置/etc/hosts
命令如下:sudo/etc/hosts
打开这个文件在文件第一行会显示如下文字:
127.0.0.1localhost
下面的文字不要看。添加上一行如下:
127.0.0.1ubuntu1.localdomainubuntu1
然后保存文件。如果你是静态IP,将127.0.0.1换成你所指定的IP,如果你是动态DHCP的IP,那么你需要查找到动态分配给这个虚拟机的IP,然后替换127.0.0.1。
这样网络配置就完成了,重启网络使之生效:sudo/etc/init.d/networkingrestart
由于单位是通过代理来上网的,因此单位还需要配置代理,代理在安装的时候我就配置过,可一上网就连接不上,我估计是配置错了,上网一查,很多人说如果设置全局代理,可以在profile里增加配置。其实我的需求很简单,就是能aptupdate就可以了,因此选择修改~/.bashrc,在.bashrc文件末尾添加如下内容(根据你的实际情况替换yourproxyaddress和proxyport):
exporthttp://[user:password]@yourproxyaddress:proxyport。
使用的命令如下:sudovi~/.bashrc
这样在家里和单位尝试pingwww.sohu.com,都可以ping通。没问题。
配置好了网络就开始,安装更新代码和JDK。我首先sudoapt-getupdate,这个命令使得Ubuntu在更新源下载了很多更新代码,时间好长,建议大家修改一下更新源的配置。
如果你没有安装SSHServer那么可以用以下命令来安装:
sudoapt-getinstallopenssh-serveropenssh-client
停止ssh:/etc/init.d/sshstop
启动ssh:/etc/init.d/sshstart
重启ssh:/etc/init.d/sshrestart
安装了ssh,你也可以用SecureCRT访问Ubuntu比直接登录方便些。
接着开始安装JDK,安装的时间也很长,默认的下载源很不稳定,时而300KB,时而300B,简直熬人呀!
命令是:
sudoapt-getinstallsun-java6-jdk,如果你不确定是不是已经安装过了JDK,可以用命令:java-version来看看。
如果说,javaversion不是sun的,或者是说java不是内部命令,那么就需要安装了。
值得一提的是,配置环境变量,一般的安装JDK是默认是安装到/usr/lib/jvm/java-6-sun下面的,包括可执行程序以及类库都在这下面,你可以用cd/usr/lib/jvm/java-6-sun命令查看一下。
我配置了两个地方,一个是/etc/environment文件,一个是~/.bashrc文件,分别是这样的:
/etc/environment文件:
CLASSPATH=/usr/lib/jvm/java-6-sun/lib
JAVA_HOME=/usr/lib/jvm/java-6-sun
~/.bashrc的最末行加上
exportJAVA_HOME=/usr/lib/jvm/java-6-sun
exportCLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
exportPATH=.:$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin
注意:PATH中的$PATH一定要加上,不然你的所有命令如vi,sudo都找不到了。都需要加上/sbin/才能执行。
还有,linux下的配置分隔符是“:”,与Windows下的“;”不一样,这对新手来说尤其重要。
添加完了这些变量,你可以用echo名来查看一下是不是正确的,命令如下:
echo$PATH
echo$CLASSPATH
echo$JAVA_HOME
自己可以看看,是不是与设置的一样。
这时候,执行
现在Ubuntu下面还没有Hadoop,好像我也没有找到Ubuntu下面的Hadoop的安装源,因此,我从官网下载了Hadoop-0.19.0的安装包hadoop-0.19.0.tar.gz到XP下面,我准备想办法把它弄到Ubuntu中去,有两种办法,一是通过共享文件夹,一是通过FTP,我选择了后者。
使用命令:apt-getinstalvsftpd,尽管很长时间下载,但是安装很顺利。没有想到,安装完了以后,配置这个ftp目录,却花了我三天时间,主要是自己对于Linux不熟悉,也没有在这个环境下配置ftp的目录,修改了配置文件/etc/vsftpd.conf,但是还是死活上传不了文件,不是告诉我没权限就是告诉我创建文件失败。我的配置文件如下:
anonymous_enable=YES
no_anon_password=YES
local_enable=YES
#这个很重要...
anon_root=/home/ftp/
write_enable=YES
local_umask=022
anon_upload_enable=YES
anon_mkdir_write_enable=YES
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_file=/var/log/vsftpd.log
xferlog_std_format=YES
ftpd_banner=WelcometoblahFTPservice.
chroot_local_user=YES
chroot_list_enable=YES
#(defaultfollows)
chroot_list_file=/etc/vsftpd.chroot_list
secure_chroot_dir=/var/run/vsftpd
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.ke
以上有些配置项在默认的配置文件中是没有的,需要用vi命令手动添加,参数的含义我在这里就不讲了,网上一堆一堆的。我的这个配置,主要是考虑到简单化。
还有一个vsftpd.chroot_list文件,添加两行:
anonymous
ftp
这是FTP的两个用户,其实ftp这个用户已经是在安装vsftpd以后就给你默认创建好了的,修改好了配置文件,重启ftp
命令如下:sudo/etc/init.d/vsftpdrestart,重启OK。
打开filezilla连接,可以看到ftp的根目录,可以下载,但就是无法上传文件,最后报出一个错误是:
500OOPS:vsftpd:refusingtorunwithwritableanonymousroot
查了好多帖子,都是说东说西,说不到点子上,最后查找到一个帖子,终于搞明白了:
我在anon_root=/home/ftp/设置了一个目录是匿名登录后见到的根目录,上传不能上传到这个目录下面,只能上传在其子目录下面,
我看到贴子上解释这个问题用了很多的叹号,可见,这个问题困扰了不止我一个人,应该是很多人呀。
修改目录的权限:sudochmod555/home/ftp
创建一个子目录:sudomkdir/home/ftp/upload
修改这个目录的权限属性:sudochmodo+w/home/ftp/upload
有人说还需要,修改目录的所有者属性,sudochownftpupload,但是我没有用这个命令,因为这是修改所有者命令,如果执行了这个命令,那么上面的修改权属的命令就不用执行了。
最后,当看到文件上传的绿色进度条时候,我兴奋得大喊一声,好不容易呀,终于成功了!
上传文件成功了以后,将文件从/home/ftp/upload/拷贝到/home/cdh/下面,然后用tar命令解压该文件,命令是:
sudotar-xzvfhadoop-0.19.0.tar.gz
然后,将在/home/cdh/hadoop-0.19.0/解压后的文件。这里要注意了,我们使用:ls-lrt命令查看解压后的目录时,可见:
cdh@ubuntu1:/home/cdh$ls-lrt
drwxr-xr-x12rootroot40962008-11-1411:14hadoop-0.19.0
-rw-------1rootnogroup422661802009-01-1802:59hadoop-0.19.0.tar.gz
这个文件夹是root所有的,如果一直是root所有,那么在后边将会无法启动hadoopdfs,所有者必须改成是当前用户cdh的。
命令是:sudochown-Rcdh:cdh/home/cdh/hadoop-0.19.0/
第一个当前cdh是用户名,第二个cdh是组名,也就是系统存在一个cdh组,组中有一个用户名是cdh,这是Ubuntu安装时候默认建立的。
如果你想看到你改变所有者时该命令chown命令所做的工作,可以用以下命令:
sudochown-vRcdh:cdh/home/cdh/hadoop-0.19.0/
执行完成以后,我们再执行命令:ls-lrt,得到的结果是:
drwxr-xr-x14cdhcdh40962009-01-1902:59hadoop-0.19.0
-rw-------1rootroot422661802009-01-1803:59hadoop-0.19.0.tar.gz
这就为以后,启动hadoop创造了条件。
现在需要配置ssh,因为hadoop是通过ssh来启动所有的slaves,命令如下:
sudossh-keygen-tdsa-P''-f~/.ssh/id_dsa
显示结果如下,一路回车,具体就不解释了,参照ssh的相关文档。
Generatingpublic/privatersakeypair.
Enterfileinwhichtosavethekey(/home/cdh/.ssh/id_rsa):
Enterpassphrase(emptyfornopassphrase):
Entersamepassphraseagain:
Youridentificationhasbeensavedin/home/cdh/.ssh/id_rsa.
Yourpublickeyhasbeensavedin/home/cdh/.ssh/id_rsa.pub.
Thekeyfingerprintis:
2e:57:e2:bf:fd:d4:45:5c:a7:51:3d:f1:51:3c:69:68cdh@ubuntu1
再创建一个authorized_keys文件:
sudocat~/.ssh/id_dsa.pub>>~/.ssh/authorized_keys
cat命令本来是是用来显示文件文件内容的命令,但是这里作为生成文件的命令,表示一种追加某文件的内容到另一个文件中。
然后用sshlocalhost来测试一下是不是ssh连接本机不再需要密码了,第一次连接会出现以下提示:
Theauthenticityofhost[ubuntu1]can'tbeestablished.Thekeyfingerprintis:74:32:91:f2:9c:dc:2e:80:48:73:d4:53:ab:e4:d3:1aAreyousureyouwanttocontinueconnecting(yes/no)?
输入yes后回车。然后再次sshlocalhost将不再需要密码。
剩下的就是配置hadoop的配置文件了。我欣喜地把这些文件copy下来,并保存成hadoop-site.xml文件,上传到/home/cdh/hadoop-0.19.0/conf/下面,然后修改conf/hadoop-env.sh,修改了exportJAVA_HOME=/usr/lib/jvm/java-6-sun,并把前面的注释#号去掉。
由于hadoop是运行在多个server上的编程框架,因此我们利用VMware来clone虚拟机,我由于担心三个虚拟机拖垮我的小黑,于是只clone了一个,并将clone机命名为ubuntu2。虚拟机clone完成以后,需要修改两个机器的/etc/hosts,别忘了修改clone机的hostname文件。
对于每一台虚拟机hosts的设置如下:
127.0.0.1localhost
192.168.158.102ubuntu1.localdomainubuntu1
192.168.158.103ubuntu2.localdomainubuntu2
192.168.158.101caodh
最后一行是为了能ping通宿主机。同时在宿主机上也按上面进行配置。重新启动两台机器的网络:
sudo/etc/init.d/networkingrestart
执行结果显示,ubuntu1重新启动成功,而ubuntu2重新启动失败,报得错误很奇怪:
eth0:ERRORwhilegettinginterfaceflags:Nosuchdevice
这个执行结果一度让我打了退堂鼓,想重新再装虚机来创建slaves,但是上网搜了一下,还真有这个错误的解决办法!看来我遇到的问题前人都已经解决了,原来是这样的,新克隆的虚拟机镜像的网卡mac地址已经变更。打开虚拟机的.vmx文件,ethernet0.generatedAddress项记录了该虚拟机的mac地址。查看所有适配器信息
ifconfig-a发现除了原来的eth0外,Ubuntu已经将新网卡命名为eth1。
Ubuntu保存网卡mac地址和设备名的配置文件在/etc/udev/rules.d/70-persistent-net.rules网卡的网络配置保存在/etc/network/interfaces该配置文件中只有原来eth0的配置信息。由于我在家里的虚机是dhcp的,因此,我决定删除/etc/udev/rules.d/70-persistent-net.rules。命令如下:
sudorm/etc/udev/rules.d/70-persistent-net.rules
重新启动ubuntu2,成功获取了一个新的IP,多虚拟机配置成功!
对于每一个虚机你要指定hadoop的节点信息,我把ubuntu1设置成master,ubuntu2设置成slave,相应地修改/home/cdh/hadoop-0.19.0/conf/masters和slaves,把其中的localhost删除,分别设置上ubuntu1和ubuntu2,注意,slaves中可以设置多个slave的,主机名一行一个。
这些配置文件,每一个虚机的都是一样的,只有辛苦一点手动设置上去了。也可以偷懒一下,利用ssh的scp来各个虚机进行copy,命令如下:
scp-rhadoop-0.19.0cdh@ubuntu2:/home/cdh/hadoop-0.19.0
这样也可以保证每个虚机的部署完全一致。
然后,我准备启动hadoop,首先格式化dfs,命令是:
cd/home/cdh/hadoop-0.19.0
bin/hadoopnamenode-format,执行结果,抱错!想来想去是不是那地方配置不对?感觉也不是呀,打开来配置文件仔细看,也没有看出问题,后来恍然大悟,linux下文本文件和windows下的文本文件中对于换行符的定义不一致,于是用vi打开hadoop-site.xml,仔细看,发现的确文件中多出了很多的^M字符,删除之!保存,再次格式化,创建log目录都permissiondenied!这就是我上面所说过的问题,/home/cdh/hadoop-0.19.0/目录的所有者是root,如果按照我上面所讲的,改成了cdh所有,那么就没这个问题了。再次执行格式化,格式化成功!
启动hadoop,是用命令:bin/start-all.sh,又报错,告诉我无法连接上slave,而且告诉我ubuntu2,Deprecated,我百思不得其解,翻看了几个关于hadoop的文章,都没有讲,仔细阅读了hadoop-default.xml文件才知道,
<property>
<name>fs.default.name</name>
<value>ubuntu1:9000</value>
<description>/description>
</property>
中,ubuntu1前面一定要加上hdfs://,即:
<property>
<name>fs.default.name</name>
<value>hdfs://ubuntu1:9000/</value>
<description>/description>
</property>
于是乎我的完整的配置如下:
启动hadoop命令:bin/start-all.sh,启动成功!ubuntu1上namenode,secondarynamenode,jobtracker进程,ubuntu2上datanode,tasktracker进程。
如果你想查看这些进程可以使用命令:lsof-i:9000/lsof-i:9001。
至此,hadoop的环境就算配置成功了。下面我用hadoop提供的example验证了一下我配置的环境。
cdh@ubuntu1:$mkdir-p/home/test-in
cdh@ubuntu1:$cdtest-in
cdh@ubuntu1:$echo"helloworldbyeworldcdh">file1.txt
cdh@ubuntu1:$echo"hellohadoopgoodbyehadoop">file2.txt
#请先将待测的文件放到本地文件系统的/home/test-in目录
cdh@ubuntu1:$cd/home/cdh/hadoop-0.19.0
cdh@ubuntu1:$bin/hadoopdfs–put/home/test-ininput
#将本地文件系统上的/home/test-in目录拷到HDFS的根目录上,目录名改为input
cdh@ubuntu1:$bin/hadoopjarhadoop-0.19.0-examples.jarwordcountinputoutput
#查看执行结果:
#将文件从HDFS拷到本地文件系统中再查看:
cdh@ubuntu1:$bin/hadoopdfs-getoutputoutput
cdh@ubuntu1:$catoutput/*
#也可以直接查看
cdh@ubuntu1:$bin/hadoopdfs-catoutput/*
bye1
cdh1
goodbye1
hadoop2
hello2
world2
测试成功!
参考文献:
1、用Hadoop进行分布式并行编程(第1、2、3部分).IBMCaoYuzhong.URL:http://www.ibm.com/developerworks/cn/opensource/os-cn-hadoop1/index.html
2、分布式计算开源框架Hadoop入门实践.岑文初.URL:http://tech.ddvip.com/2008-09/122172661667224.html
3、GettingStartedwithHadoop.url:http://huang.yunsong.net/2006/getting_started_with_hadoop_part1.html