教你如何搭建多节点Hadoop集群
我毕业设计做的是Hadoop和R结合做Data Mining,向系主任申请用CST部门的Hadoop Cluster做毕业设计,结果系老大不让,因为我要安装第三方软件RHadoop,出于安全方面的考虑,最后系里给了我10个VM,让我自己折腾去.
下面我就讲讲我是怎么配置Hadoop集群的。(期间出了好多问题,希望大家能互相交流,发现问题的话,请不要吝啬回复啊!哈哈,谢谢了。)
VM的系统是Ubuntu 11.10 oneiric,运行在学校的cluster上。我在CST服务器上有一个Cloud Image,可以进行远程桌面登陆也可以ssh登陆,然后可以用这个Cloud Image(以下简称CI)对那10个VM进行管理。 CI和VM之间(VM和VM之间)的通信用的是路由器上的NAT(Network Address Translation)功能实现的。我配置服务器的时候出错就在这个上面了。/etc/hosts文件设置需要一点注意,这个后面会详细介绍。
我用的Hadoop版本是写这篇日志的时候最新的Apache Hadoop 1.0.4(Stable Version),JDK用的是Oracle的1.7.0。
假设10个VM的地址是:
- 局域网内的地址 eth0地址 DNS Domain Name Host Name
- 179.16.1.1 179.16.1.1 CI.example CI
- 192.168.1.1 172.16.1.1 master.example master
- 192.168.1.2 172.16.1.2 slave1.example slave1
- 192.168.1.3 172.16.1.3 slave2.example slave2
- 192.168.1.4 172.16.1.4 slave3.example slave3
- 192.168.1.5 172.16.1.5 slave4.example slave4
- 192.168.1.6 172.16.1.6 slave5.example slave5
- 192.168.1.7 172.16.1.7 slave6.example slave6
- 192.168.1.8 172.16.1.8 slave7.example slave7
- 192.168.1.9 172.16.1.9 slave8.example slave8
- 192.168.1.10 172.16.1.10 slave9.example slave9
假设你在VM上的sudo权限用户是vm。
首先,我在CI上把系主任给的ssh RSA private Key放到自己的home目录下的.ssh文件夹下,并改名为id_rsa。这样改的话就不用在ssh命令后写-i选项了。(/home/me/.ssh/id_rsa)
做完这一步后,还需要依次登录到10个VM上。确保你在VM上的这个账号有root权限或sudo权限。
Bash命令如下:
for (( i = 1 ; i<11 ; i++ )) ; do ssh -l vm 192.168.1.$i ; done 第一次登录的话会有警告: The authenticity of host 'master (192.168.1.1)' can't be established. ECDSA key fingerprint is ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'master,192.168.1.1' (ECDSA) to the list of known hosts. 这时你得输入yes(上面的红色字体),然后回车,以便连接到服务器。你会发现你home目录下的.ssh文件夹下会多出个known_hosts文件。里面有你已经登录过的服务器的指纹(fingerprint)和ssh public key。下次再登录的时候就不会出现这个警告了。具体请查看man ssh。 同时在多个服务器上执行相同命令的工具,在网上找到的有:puppet、FAI、pssh。 因为只有10个节点,所以我用的是pssh。要是多的话大概就得用前两个了。 在CI上安装pssh: me@CI:$ sudo apt-get install pssh 具体怎么使用pssh ,自己问man去。(man parallel-ssh). 下面是我自己设置的.bash_aliases文件:
- alias pssh='parallel-ssh'
- alias pscp='parallel-scp'
- alias pssha='parallel-ssh -i -h /home/me/Workspace/all.hosts '
- alias psshs='parallel-ssh -i -h /home/me/Workspace/slave.hosts '
- alias psshm='parallel-ssh -i -H vm@master '
- alias pscpa='parallel-scp -h /home/me/Workspace/all.hosts '
- alias pscps='parallel-scp -h /home/me/Workspace/slave.hosts '
- alias psshah='parallel-ssh -i -h /home/me/Workspace/hall.hosts '
- alias psshsh='parallel-ssh -i -h /home/me/Workspace/hslave.hosts '
- alias psshmh='parallel-ssh -i -H hduser@master '
- alias pscpah='parallel-scp -h /home/me/Workspace/hall.hosts '
- alias pscpsh='parallel-scp -h /home/me/Workspace/hslave.hosts '
上面的all.hosts 和slave.hosts是这样的,我只列出来其中的几条
vm@master
vm@slave1
vm@slave2
...
至于hall.hosts和hslave.hosts,如下(hduser是我们后面要建的用户。)
hduser@master
hduser@slave1
hduser@slave2
...
其中all和slave的区别只在于有没有master那一行。Slave的文件没有master那一行。
关于/etc/hosts文件:(用于解析网络主机地址。)
在CI上这么设置:
- 179.16.1.1 CI.example CI
- 192.168.1.1master.examplemaster
- 192.168.1.2slave1.exampleslave1
- 192.168.1.3slave2.exampleslave2
- 192.168.1.4slave3.exampleslave3
- 192.168.1.5slave4.exampleslave4
- 192.168.1.6slave5.exampleslave5
- 192.168.1.7slave6.exampleslave6
- 192.168.1.8slave7.exampleslave7
- 192.168.1.9slave8.exampleslave8
- 192.168.1.10slave9.exampleslave9
在VM(master)上设置如下:
- 172.16.1.1master.examplemaster
- 192.168.1.2slave1.exampleslave1
- 192.168.1.3slave2.exampleslave2
- 192.168.1.4slave3.exampleslave3
- 192.168.1.5slave4.exampleslave4
- 192.168.1.6slave5.exampleslave5
- 192.168.1.7slave6.exampleslave6
- 192.168.1.8slave7.exampleslave7
- 192.168.1.9slave8.exampleslave8
- 192.168.1.10slave9.exampleslave9
在VM(slave1)上设置如下:
- 192.168.1.1master.examplemaster
- 172.16.1.2slave1.exampleslave1
- 192.168.1.3slave2.exampleslave2
- 192.168.1.4slave3.exampleslave3
- 192.168.1.5slave4.exampleslave4
- 192.168.1.6slave5.exampleslave5
- 192.168.1.7slave6.exampleslave6
- 192.168.1.8slave7.exampleslave7
- 192.168.1.9slave8.exampleslave8
- 192.168.1.10slave9.exampleslave9
其他的VM上的/etc/hosts文件以此类推。如果你没有NAT的话就没必要这么设置了。因为局域网地址和eth0地址是同一个地址。
注意红色字体的区别。(在slavex上设置的话得把相应的那一行改成eth0的地址。目的是为了让服务端口绑定到正确的地址上。)
这么设置的原因是NAT的缘故:
客户端A向服务器B发送服务请求的时候是发送到局域网地址192.168.1.x上,通过路由器后会被映射到服务器的eth0地址172.16.1.x上。因此自己的地址要写成eth0地址,这样别的机器才能访问自己。
好了,网络设置设好了。
接下来配置Hadoop。
从apache官网上下载最新的stable version:hadoop-1.0.4.tar.gz
在CI上解压缩:
me@CI:$ tar xzf hadoop-1.0.4.tar.gz
me@CI:$ mv hadoop-1.0.4 hadoop
进入hadoop文件夹下的conf文件夹,这个文件夹下的配置文件是可以修改的。
Hadoop的默认配置文件在$HADOOP_HOME/src下的core、hdfs、mapred等文件夹下。
关于具体参数设置的说明文件是$HADOOP_HOME/docs文件夹下的core-default.html、hdfs-default.html、mapred-default.html等default.html文件。
下面贴上我自己的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:8020</value>这个是必须得设置的,设置你的namenode在哪个服务器和端口。
- </property>
- <property>
- <name>io.file.buffer.size</name>
- <value>65536</value>
- </property>
- <property>
- <name>webinterface.private.actions</name>
- <value>true</value>
- </property>
- <property>
- <name>fs.inmemory.size.mb</name>
- <value>100</value>
- </property>
- <property>
- <name>io.sort.factor</name>
- <value>100</value>
- </property>
- <property>
- <name>io.sort.mb</name>
- <value>100</value>
- </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.name.dir</name>
- <value>/hadoop/dfs/name</value>这个是你namenode服务器上存放hdfs系统meta data的地方。根据自己喜好设置路径,这个只做参考。
- </property>
- <property>
- <name>dfs.data.dir</name>
- <value>/hadoop/dfs/data</value>这个是你其他所有datanode服务器上存放hdfs系统data的本地路径。仅做参考。
- </property>
- <property>
- <name>dfs.namenode.handler.count</name>
- <value>20</value>
- </property>
- <property>
- <name>dfs.datanode.handler.count</name>
- <value>5</value>
- </property>
- <property>
- <name>dfs.replication</name>这个不用说了吧,文件在hdfs系统中的复件份数,最低是1。
- <value>3</value>
- </property>
- <property>
- <name>dfs.datanode.max.xcievers</name>
- <value>1024</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>这个是你的jobtracker服务所在的服务器和端口,因为我只有10个主机,所以我把这个服务跟namenode服务开在了同一个服务器上--master上。
- <value>master:8021</value>
- </property>
- <property>
- <name>mapred.system.dir</name>
- <value>/hadoop/mapred/system</value>存放mapred控制文件的路径。
- </property>
- <property>
- <name>mapred.local.dir</name>
- <value>/hadoop/mapred</value>存放mapred中间结果的地方。
- </property>
- <property>
- <name>mapred.reduce.parallel.copies</name>
- <value>10</value>
- </property>
- <property>
- <name>mapred.map.child.java.opts</name>
- <value>-Xmx512M</value>
- </property>
- <property>
- <name>mapred.reduce.child.java.opts</name>
- <value>-Xmx512M</value>
- </property>
- </configuration>
在conf文件夹下还有两个文件是与服务器有关的:masters,slaves。
masters文件:我们只有一个master服务器
master
slaves文件:我们有9个slave服务器。
slave1
slave2
slave3
slave4
slave5
slave6
slave7
slave8
slave9
剩下的就是conf文件夹下的hadoop-env.sh文件了,设置hadoop可执行文件运行环境.
- hadoop-env.sh文件: http://www.xiaoxiongboke.com
- # Set Hadoop-specific environment variables here.
- # The only required environment variable is JAVA_HOME. All others are
- # optional. When running a distributed configuration it is best to
- # set JAVA_HOME in this file, so that it is correctly defined on
- # remote nodes.
- export HADOOP_HOME=/opt/hadoop #这个是我的hadoop home路径。就是你的hadoop的安装路径。
- # The java implementation to use. Required.
- export JAVA_HOME=/usr/lib/jvm/jdk #这个就是你的java安装路径了。
- # Extra Java CLASSPATH elements. Optional.
- export HADOOP_CLASSPATH=/home/hduser/java/
- # The maximum amount of heap to use, in MB. Default is 1000.
- # export HADOOP_HEAPSIZE=2000
- # Extra Java runtime options. Empty by default.
- # export HADOOP_OPTS=-server
- # Command specific options appended to HADOOP_OPTS when specified
- export HADOOP_NAMENODE_OPTS="-Dcom.sun.management.jmxremote $HADOOP_NAMENODE_OPTS"
- export HADOOP_SECONDARYNAMENODE_OPTS="-Dcom.sun.management.jmxremote $HADOOP_SECONDARYNAMENODE_OPTS"
- export HADOOP_DATANODE_OPTS="-Dcom.sun.management.jmxremote $HADOOP_DATANODE_OPTS"
- export HADOOP_BALANCER_OPTS="-Dcom.sun.management.jmxremote $HADOOP_BALANCER_OPTS"
- export HADOOP_JOBTRACKER_OPTS="-Dcom.sun.management.jmxremote $HADOOP_JOBTRACKER_OPTS"
- # export HADOOP_TASKTRACKER_OPTS=
- # The following applies to multiple commands (fs, dfs, fsck, distcp etc)
- # export HADOOP_CLIENT_OPTS
- # Extra ssh options. Empty by default.
- # export HADOOP_SSH_OPTS="-o ConnectTimeout=1 -o SendEnv=HADOOP_CONF_DIR"
- # Where log files are stored. $HADOOP_HOME/logs by default.
- # export HADOOP_LOG_DIR=${HADOOP_HOME}/logs
- # File naming remote slave hosts. $HADOOP_HOME/conf/slaves by default.
- # export HADOOP_SLAVES=${HADOOP_HOME}/conf/slaves
- # host:path where hadoop code should be rsync'd from. Unset by default.
- # export HADOOP_MASTER=master:/home/$USER/src/hadoop
- # Seconds to sleep between slave commands. Unset by default. This
- # can be useful in large clusters, where, e.g., slave rsyncs can
- # otherwise arrive faster than the master can service them.
- # export HADOOP_SLAVE_SLEEP=0.1
- # The directory where pid files are stored. /tmp by default.
- # export HADOOP_PID_DIR=/var/hadoop/pids
- # A string representing this instance of hadoop. $USER by default.
- # export HADOOP_IDENT_STRING=$USER
- # The scheduling priority for daemon processes. See 'man nice'.
- # export HADOOP_NICENESS=10
export HADOOP_HOME_WARN_SUPPRESS="TRUE" #如果设置了hadoop_home,运行hadoop命令时会有警告,这条设置可以避免这些烦人的警告。
现在我们的hadoop设置文件也改好了。
接下来我们安装oracle的jdk。从oracle的官网下载文件jdk-7-linux-x64.tar.gz
用我们的pscpa命令拷贝文件到各个服务器。(以下命令在我的.bash_aliases文件里。)
拷贝jdk文件到所有服务器的home文件夹。
me@CI:$ pscpa jdk-7-linux-x64.tar.gz /home/vm
解压缩到/usr/lib/jvm文件夹
me@CI:$ pssha ‘sudo tar xzf jdk-7-linux-x64.tar.gz -C /usr/lib/jvm ;
sudo mv /usr/lib/jvm/jdk1.7.0 /usr/lib/jvm/jdk’
最好不要以高权限用户运行hadoop命令和服务(安全角度。)。
所以我们新建一个用户和组:
新建用户组hadoop
me@CI:$ pssha ‘sudo groupadd hadoop’
新建用户hduser(名字怎么取看你自己喜好了,hadoop专用用户。)
建议使用newusers命令新建用户。(具体请man newusers)
me@CI:$ pssha 'sudo newusers <
> EOF
> '
然后拷贝文件并设置文件和文件夹属性:
me@CI:$ pssha 'sudo mkdir /home/hduser/.ssh ; sudo cp /etc/skel/.* /home/hduser ; sudo cp /home/vm/.ssh/authorized_keys /home/hduser/.ssh ; sudo chown -R hduser:hadoop /home/hduser ; sudo chmod 600 /home/hduser/.ssh/authorized_keys'
为了让hduser能ssh登录其他slave,应该把private key拷贝到master上hduser的.ssh文件夹下。
me@CI:$ scp /home/me/.ssh/id_rsa hduser@master:/home/hduser/.ssh
最后再登录到master上。
me@CI:$ ssh hduser@master
hduser@master:~$ for (( i=1 ; i < 10 ; i++ )) ; do ssh slave$i ; done 上面这一步是为了让master在所有slave上登录一遍。登录过以后就不会再有警告了。 退回到CI上,接下来要在CI上工作。 接下来在每个服务器上建立hadoop需要的文件夹: me@CI:$ pssha ‘sudo -p mkdir /hadoop/dfs ; sudo -p mkdir /hadoop/mapred/system/ ; sudo chown -R hduser:hadoop /hadoop’ 最后一步,安装我们已经配置好的hadoop文件到每个服务器: 压缩我们配置好的hadoop文件夹: me@CI:$ tar czf hadoop.tar.gz hadoop 拷贝到每个服务器: me@CI:$ pscpa hadoop.tar.gz /home/vm 解压缩到/opt文件夹下: me@CI:$ pssha tar xzf hadoop.tar.gz -C /opt 还有最后一步,把/opt/hadoo/bin加到PATH里去。 me@CI:$ echo 'PATH=/opt/hadoop/bin:$PATH' > path.apend
me@CI:$ pscpa path.apend /home/vm
me@CI:$ pssha ‘cat path.apend | sudo tee -a /home/hduser/.bashrc’
me@CI:$ pssha ‘rm path.apend’
到了这里应该就安装并配置好hadoop了。
接下来在CI上以hduser的身份登录到master服务器上启动hadoop
me@CI:$ ssh hduser@master
检查hadoop是否安装并配置成功
hduser@master:~$ hadoop version
格式化namenode:
hduser@master:~$ hadoop namenode format
运行example job
- hduser@master:~$ hadoop fs -put conf input
- hduser@master:~$ hadoop jar /opt/hadoop/ hadoop-examples-1.0.4.jar
- Browse the web interface for the NameNode and the JobTracker; by default they are available at:(访问hdfs和jobtracker,复制下面的链接到你CI的浏览器地址栏。)
- · NameNode - http://master:50070/
- · JobTracker - http://master:50030/
参考文献:
http://hadoop.apache.org/docs/r1.0.4/single_node_setup.html
http://hadoop.apache.org/docs/r1.0.4/cluster_setup.html
http://www.michael-noll.com/tutorials/running-hadoop-on-ubuntu-linux-single-node-cluster/
http://www.michael-noll.com/tutorials/running-hadoop-on-ubuntu-linux-multi-node-cluster/
http://gbif.blogspot.com/2011/01/setting-up-hadoop-cluster-part-1-manual.html