工作中用GATK找indel时非常慢,查看GATK官网的介绍,说GATK支持Map/Reduce框架,所以突发奇想,GATK在Hadoop平台上跑是否会快一些呢?于是,开始搭建Hadoop的平台,网上有很多这方面的资料,但是只有自己实践了才知道是否可行,这里介绍我自己搭建的过程以及遇到的问题,记录下来。
选择机器:node105 (Master机器,我用做NameNode、JobTracker) ip:172.16.4.105
node71 (Slave机器,我用做DataNode,TaskTracker) ip:172.16.4.71
node81 (Slave机器,我用做DataNode,TaskTracker) ip:172.16.4.81
机器说明:每台机器上都应该安装好jdk版本1.5以上,我这里软件环境如下:
jdk: 1.6.0_25 安装包是jdk-6u25-linux-x64-rpm.bin
hadoop:hadoop-0.20.2
呵呵,以上的ip地址和机器名都不是我单位真实的ip地址,变动了一下的,在这里说明一下,ok,下面开始搭建啦。
第一步,首先所有机器相互ping一下,保证通过机器名称能够ping通,注意不要通过ip去ping啊,一定要通过机器名去ping。如果ping不通的话,修改/etc/hosts里面的配置,这里稍微介绍一下hosts文件,/etc/hosts是主机名查询静态表,可以理解为将主机名解析成ip地址的解析文件,格式如下:
[root@node105 ~]#cat /etc/hosts
127.0.0.1 localhost localhost
172.16.4.105 node105 hadoophost
172.16.4.71 node71 node71
172.16.4.81 node81 node71
总共有三列,第一列是ip地址,第二列是主机名,第三列是别名。其实环境搭建熟悉了之后,你会发现,第二列第三列的名字可以随便命,只要保证host和slave机器名称一致,以及hadoop配置文件中master和slave中的配置一致就行了,但是初学搭建的话,还是按照网上说的来做,别名也和主机名写一样算了。
第二步,新建hadoop用户。由于hadoop要求所有机器上hadoop部署目录结构要一致,而且要求有相同用户名的帐号,所以在三台机器上都要新建hadoop用户。
第三步,配置NameNode可以通过ssh无密码登录到所有的DataNode。由于Hadoop的HDFS进行数据备份时一般是通过scp进行的,所以这里需要配置ssh为无密码公钥认证方式。
以hadoop用户登录NameNode,操作如下:
[hadoop@node105 ~]$mkdir .ssh
[hadoop@node105 ~]$chmod 755 .ssh
在NameNode上新建一个.ssh目录,并且将权限改成755,这一点很关键,否则后面ssh始终需要输入密码。
[hadoop@node105 ~]$ssh-keygen -t rsa
Enter file in which to save the key (/home/hadoop/.ssh/id_rsa):
出现这个提示按回车,后面碰到提示也是一直回车,完成之后查看.ssh目录下会生成文件id_rsa和id_rsa.pub。
介绍一下,这个id_rsa是私钥,id_rsa.pub是公钥。对于SSH服务来说,node105为SSH客户端,而node71,node81为SSH服务端,因此在node71,node81上需要确定sshd服务已经启动。当node105要向node71发起ssh连接时,无密码公钥认证过程如下:node105发起连接请求;node71生成一个随机数并用node105的公钥加密,然后发送给node105;node105收到加密后的数后用私钥解密,并将解密后的数发送回node71;node71确认解密的数无误,允许建立连接。
刚刚介绍了SSH工作原理,由此可知,node105上生成的公钥还需要拷贝到node71、node81上去。
[hadoop@node105 .ssh]$ cat id_rsa.pub >authorized_keys
[hadoop@node105 .ssh]$ chmod 644 authorized_keys
检查node71和node81目录/home/hadoop/.ssh下面是否存在authorized_keys,不存在则将node105上的authorized_keys拷贝过去,存在则将其内容追加到后面。
至此,SSH无密码认证方式应该已经配置好了,最好ssh node71测试一下,如果还要输入密码的话,请检查.ssh目录权限是否为755,authorized_keys权限是否为644。
第四步:安装Hadoop。Hadoop安装的前提条件是Jdk已经安装并且配置好了,如果没配好的要先配好JDK。我用的hadoop包是hadoop-0.20.2.tar,hadoop其实不需要安装,解压就可以了,我的路径如下:
[hadoop@node105 ~]$ ll -th /home/hadoop/HadoopInstall/
total 145M
drwxrwxr-x 2 hadoop hadoop 4.0K Nov 16 07:19 hadoop-conf
drwxrwxr-x 13 hadoop hadoop 4.0K Nov 15 10:27 hadoop-0.20.2
lrwxrwxrwx 1 hadoop hadoop 13 Nov 15 07:10 hadoop -> hadoop-0.20.2
-rw-r--r-- 1 hadoop hadoop 145M Nov 15 06:09 hadoop-0.20.2.tar
解压的文件夹是hadoop-0.20.2,但是为了方便版本更新,我建立了一个符号连接hadoop,指向该目录,另外,新建了hadoop-conf目录,将hadoop的配置文件core-site.xml, hadoop-env.sh, hdfs-site.xml, mapred-site.xml, masters,slaves从/home/hadoop/HadoopInstall/hadoop/conf下面拷贝到该目录下去。
配置Hadoop环境变量,在.bashrc中加入:
export HADOOP_CONF_DIR=$HOME/HadoopInstall/hadoop-conf
export HADOOP_HOME=/home/hadoop/HadoopInstall/hadoop
export PATH=$HADOOP_HOME/bin:$PATH
第五步:Hadoop配置,更改hadoop-conf中的配置文件,一般按说明更改就好,下面简单列一下我的设置:
[hadoop@node105 hadoop-conf]$ cat 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>hadoop.tmp.dir</name>
<value>/home/hadoop/tmp</value>
</property>
<property>
<name>fs.default.name</name>
<value>hdfs://172.16.4.105:9000</value>
</property>
</configuration>
[hadoop@node105 hadoop-conf]$ cat hadoop-env.sh
。。。。省略 。。。。。。。这里只需要根据JDK实际情况修改JAVA_HOME的路径
export JAVA_HOME=/usr/java/jdk1.6.0_25
export CLASSPATH=$JAVA_HOME/lib:$JAVA_HOME/jre/lib:.
export PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin
[hadoop@node105 hadoop-conf]$ cat 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>2</value> 注意:这里如果为1的话,一旦机器挂掉,所有的数据可能都没了
</property>
<property>
<name>dfs.name.dir</name>
<value>/home/hadoop/name</value>
</property>
<property>
<name>dfs.data.dir</name>
<value>/home/hadoop/data</value>
</property>
</configuration>
[hadoop@node105 hadoop-conf]$ cat 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>172.16.4.105:9001</value>
</property>
<property>
<name>mapred.map.tasks</name>
<value>20</value>
</property>
<property>
<name>mapred.reduce.tasks</name>
<value>18</value>
</property>
<property>
<name>mapred.tasktracker.map.tasks.maximum</name>
<value>23</value>
</property>
<property>
<name>mapred.tasktracker.reduce.tasks.maximum</name>
<value>23</value>
</property>
</configuration>
[hadoop@node105 hadoop-conf]$ cat masters
172.16.4.105
[hadoop@node105 hadoop-conf]$ cat slaves
172.16.4.71
172.16.4.81
配置文件修改好之后,将HadoopInstall文件夹scp到node71、node81上去,保证slaves节点的配置和master的配置是一样的。
[hadoop@node105 ~]$ scp -r /home/hadoop/HadoopInstall node71:/home/hadoop
至此,hadoop平台应该应该搭建好了,下面启动hadoop测试下喽
[hadoop@node105 ~]$ hadoop namenode -format
[hadoop@node105 ~]$ /home/hadoop/HadoopInstall/hadoop/bin/start-all.sh
[hadoop@node105 ~]$ jps
10261 NameNode
10518 JobTracker
10607 Jps
10435 SecondaryNameNode
以上是启动后在master节点上jps看到启动的服务,在slave节点jps可以看到:
[hadoop@node81 ~]$ jps
2388 DataNode
2517 TaskTracker
2720 Jps
说明:如果不能运行jps,可能是java环境变量没有配好,解决的办法是在/etc/profile中加入
export JAVA_HOME=/usr/java/jdk1.6.0_25
export JRE_HOME=/usr/java/jdk1.6.0_25/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
然后source一下,就应该可以用了。
[hadoop@node105 ~]$ echo “hello test1 today” > f1
[hadoop@node105 ~]$ echo “hello test2 today” > f2
下面拷贝文件到HDFS文件系统里面去,命令如下:
[hadoop@localhost ~]$ hadoop dfs -copyFromLocal f1 input
11/11/16 05:51:57 INFO hdfs.DFSClient: Exception in createBlockOutputStream java.net.NoRouteToHostException: No route to host
11/11/16 05:51:57 INFO hdfs.DFSClient: Abandoning block blk_-5130390462892393594_1407
发生了错误“No route to host”,我觉得可能有两种原因,一个是因为/etc/hosts文件中的名称与hadoop配置文件masters和slaves的设置不一致,或者所有节点之间的/etc/hosts文件中的名称不一致;另一个原因是9000端口没开,因为在core-site.xml里面设置了fs.default.name为hdfs://172.16.4.105:9000,如果9000端口没开,就会有问题,我碰到的是后一种,解决办法如下:
master上:iptables -I INPUT -p tcp --dport 9000 -j ACCEPT
slaves上:iptables -I INPUT -s 172.16.4.105 -p tcp -j ACCEPT
继续拷贝文件f2,又报了另一个错误,如下
[hadoop@localhost ~]$ hadoop dfs -copyFromLocal f2 input
11/11/16 06:38:45 INFO hdfs.DFSClient: Exception in createBlockOutputStream java.io.IOException: Bad connect ack with firstBadLink 172.16.4.81:50010
11/11/16 06:38:45 INFO hdfs.DFSClient: Abandoning block blk_7365545969279586857_1445
经检查,81节点的50010端口是开着的,但是仍然会报这个错误,原因可能是防火墙不允许该端口开放,解决的办法是关闭防火墙。
/etc/init.d/iptables stop
把所有机器的防火墙都关掉了,我想应该有其他的解决方法,只是我对iptables命令不熟悉,不知道怎么设置,所以只能把所有的防火墙都关了。
防火墙关闭之后,我删除hdfs上的文件,再重新拷贝,则不会有错误了。
[hadoop@node105 ~]$ hadoop dfs -rm input/f*
Deleted hdfs://hadoophost:9000/user/hadoop/input/f1
Deleted hdfs://hadoophost:9000/user/hadoop/input/f2
[hadoop@node105 ~]$ hadoop dfs -copyFromLocal f* input
OK啦,文件拷贝成功!下面运行hadoop自带的例子程序,
[hadoop@node105 hadoop]$ hadoop jar hadoop-0.20.2-examples.jar wordcount input output
11/11/16 07:23:38 INFO input.FileInputFormat: Total input paths to process : 2
11/11/16 07:23:38 INFO mapred.JobClient: Running job: job_201111160626_0001
11/11/16 07:23:39 INFO mapred.JobClient: map 0% reduce 0%
11/11/16 07:23:47 INFO mapred.JobClient: map 50% reduce 0%
11/11/16 07:23:50 INFO mapred.JobClient: map 100% reduce 0%
11/11/16 07:23:59 INFO mapred.JobClient: map 100% reduce 5%
11/11/16 07:24:02 INFO mapred.JobClient: map 100% reduce 22%
11/11/16 07:24:05 INFO mapred.JobClient: map 100% reduce 27%
11/11/16 07:24:08 INFO mapred.JobClient: map 100% reduce 38%
11/11/16 07:24:11 INFO mapred.JobClient: map 100% reduce 55%
11/11/16 07:24:14 INFO mapred.JobClient: map 100% reduce 61%
11/11/16 07:24:17 INFO mapred.JobClient: map 100% reduce 72%
11/11/16 07:24:20 INFO mapred.JobClient: map 100% reduce 88%
11/11/16 07:24:23 INFO mapred.JobClient: map 100% reduce 100%
11/11/16 07:24:28 INFO mapred.JobClient: Job complete: job_201111160626_0001
11/11/16 07:24:28 INFO mapred.JobClient: Counters: 17
11/11/16 07:24:28 INFO mapred.JobClient: Job Counters
11/11/16 07:24:28 INFO mapred.JobClient: Launched reduce tasks=18
11/11/16 07:24:28 INFO mapred.JobClient: Launched map tasks=2
11/11/16 07:24:28 INFO mapred.JobClient: Data-local map tasks=2
11/11/16 07:24:28 INFO mapred.JobClient: FileSystemCounters
11/11/16 07:24:28 INFO mapred.JobClient: FILE_BYTES_READ=134
11/11/16 07:24:28 INFO mapred.JobClient: HDFS_BYTES_READ=14
11/11/16 07:24:28 INFO mapred.JobClient: FILE_BYTES_WRITTEN=1256
11/11/16 07:24:28 INFO mapred.JobClient: HDFS_BYTES_WRITTEN=18
11/11/16 07:24:28 INFO mapred.JobClient: Map-Reduce Framework
11/11/16 07:24:28 INFO mapred.JobClient: Reduce input groups=2
11/11/16 07:24:28 INFO mapred.JobClient: Combine output records=2
11/11/16 07:24:28 INFO mapred.JobClient: Map input records=2
11/11/16 07:24:28 INFO mapred.JobClient: Reduce shuffle bytes=224
11/11/16 07:24:28 INFO mapred.JobClient: Reduce output records=2
11/11/16 07:24:28 INFO mapred.JobClient: Spilled Records=4
11/11/16 07:24:28 INFO mapred.JobClient: Map output bytes=22
11/11/16 07:24:28 INFO mapred.JobClient: Combine input records=2
11/11/16 07:24:28 INFO mapred.JobClient: Map output records=2
11/11/16 07:24:28 INFO mapred.JobClient: Reduce input records=2
注意:我这里是在/home/hadoop/HadoopInstall/hadoop下面去运行的程序,如果不在该目录下的话,hadoop-0.20.2-examples.jar应该写绝对路径,即运行命令应该改为:
hadoop jar /home/hadoop/HadoopInstall/hadoop/hadoop-0.20.2-examples.jar wordcount input output
input和output为hdfs上的路径,全路径应该是/user/hadoop/input, /user/hadoop/output;这里output路径还不存在,程序运行完成后该目录就会存在了。
可以网页http://172.16.4.105:50030/jobtracker.jsp 观看任务运行情况,另外,可以在http://172.16.4.105:50070/dfshealth.jsp 观看hdfs的状况。
[hadoop@node105 ~]$ hadoop dfs -ls output 查看结果文件
[hadoop@node105 ~]$ hadoop dfs -cat output/part-r-000* 查看结果
以上运行的是hadoop自带的程序,也可以自己写mapper和reducer,运行自己的程序,参见Hadoop Streaming编程,这里不做介绍,只给出资料链接。
http://dongxicheng.org/mapreduce/hadoop-streaming-programming/
http://hadoop.apache.org/common/docs/r0.19.2/cn/streaming.html
虽然GATK最终没在Hadoop上运行成功,它的Map/Reduce框架是基于另一种分布式并行计算的平台Grid而设计的,如果想在Hadoop平台上运行,可能需要修改GATK的源代码,我的这次实验以失败告终-_-,但是Hadoop Streaming思想真的很牛啊,很适合目前生物软件流程的优化,要好好研究一下啦,加油!