最近工做須要,摸索着搭建了Hadoop 2.2.0(YARN)集羣,中間遇到了一些問題,在此記錄,但願對須要的同窗有所幫助。html
本篇文章不涉及hadoop2.2的編譯,編譯相關的問題在另一篇文章《hadoop 2.2.0 源碼編譯筆記》中說明,本篇文章咱們假定已經得到了hadoop 2.2.0的64bit發行包。java
因爲spark的兼容問題,咱們後面使用了Hadoop 2.0.5-alpha的版本(2.2.0是穩定版本),2.0.5的配置有一點細微的差異,文中有特別提示。node
【本節摘自http://www.cnblogs.com/xia520pi/archive/2012/05/16/2503949.html】
linux
Hadoop是Apache軟件基金會旗下的一個開源分佈式計算平臺。以Hadoop分佈式文件系統(HDFS,Hadoop Distributed Filesystem)和MapReduce(Google MapReduce的開源實現)爲核心的Hadoop爲用戶提供了系統底層細節透明的分佈式基礎架構。git
對於Hadoop的集羣來說,能夠分紅兩大類角色:Master和Salve。一個HDFS集羣是由一個NameNode和若干個DataNode組成的。其中NameNode做爲主服務器,管理文件系統的命名空間和客戶端對文件系統的訪問操做;集羣中的DataNode管理存儲的數據。MapReduce框 架是由一個單獨運行在主節點上的JobTracker和運行在每一個集羣從節點的TaskTracker共同組成的。主節點負責調度構成一個做業的全部任 務,這些任務分佈在不一樣的從節點上。主節點監控它們的執行狀況,而且從新執行以前的失敗任務;從節點僅負責由主節點指派的任務。當一個Job被提交 時,JobTracker接收到提交做業和配置信息以後,就會將配置信息等分發給從節點,同時調度任務並監控TaskTracker的執行。github
從上面的介紹能夠看出,HDFS和MapReduce共同組成了Hadoop分佈式系統體系結構的核心。HDFS在集羣上實現分佈式文件系統,MapReduce在集羣上實現了分佈式計算和任務處理。HDFS在MapReduce任務處理過程當中提供了文件操做和存儲等支持,MapReduce在HDFS的基礎上實現了任務的分發、跟蹤、執行等工做,並收集結果,兩者相互做用,完成了Hadoop分佈式集羣的主要任務。apache
CentOS 6.4 64bit
uname -a
Linux ** 2.6.32_1-7-0-0 #1 SMP *** x86_64 x86_64 x86_64 GNU/Linuxtomcat
安裝Java 1.6
將jdk解壓到local目錄下
添加JAVA_HOME環境變量到.bashrc文件中
export JAVA_HOME="/home/<hostname>/local/jdk1.6.0_45/"
export JRE_HOME="/home/<hostname>/local/jdk1.6.0_45/jre/"
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
HADOOP解壓hadoop-2.2.0-bin_64.tar.gz(這個包是我在CentOS6.4 64bit的環境下編譯獲得的) 到用戶根目錄
export HADOOP_HOME=/home/<hostname>/hadoop-2.2.0
安全
[html] view plaincopyprint?bash
export PATH=$JAVA_HOME/bin:$HADOOP_HOME/bin:$PATH
hadoop默認狀況下配置爲本地模式,因此解壓後不修改任何配置,能夠執行本地測試
// 建立本地目錄
mkdir input
// 填充數據
cp conf/*.xml input
// 執行hadoop
bin/hadoop jar hadoop-examples-*.jar grep input output 'dfs[a-z.]+'
// 查看結果
[html] view plaincopyprint?
cat output/*
因爲前期只是測試環境和配置,因此簡單的使用兩個節點:
master機器,充當namenode & datanode
slave機器,充當datanode
設置hostname
HDFS用hostname而不是IP來相互之間進行通訊,hadoop會反向解析hostname,即便是用了IP,也會使用hostname 來啓動TaskTracker,因此全部配置文件只能用hostname,不能用IP(滿滿的都是淚)。咱們給兩個機器分別設置以下:
機器 | IP | HOSTNAME | 角色 |
---|---|---|---|
master | 192.168.216.135 | master | namenode, datanode |
slave | 192.168.216.136 | slave1 | datanode |
臨時更改hostname的命令是(root權限)
hostname <new_name>
永久更改須要修改配置文件/etc/sysconfig/network
[html] view plaincopyprint?
HOSTNAME=<new_name>
設置/etc/hosts文件(每臺機器上都要設置),添加以下內容
[html] view plaincopyprint?
192.168.216.135 master
192.168.216.136 slave1
namenode與datanode的/etc/hosts內容都必須是ip位址與host name的對應,不能使用127.0.0.1代替本機的ip地址,不然hadoop使用hostname找ip時,會以"127.0.0.1"做爲ip位址。
master和全部的slave之間,須要實現雙向ssh無密碼訪問(slave和slave之間能夠不用實現)。
請參見《ssh無密碼訪問》文章,本文再也不詳述
嚴格來講,應該是打開某些對應的端口。爲了簡單起見,咱們這裏關閉selinux和iptalbes.
關閉selinux的方法
[html] view plaincopyprint?
setenforce 1 設置SELinux 成爲enforcing模式
setenforce 0 設置SELinux 成爲permissive模式
若是永久關閉,編輯/etc/selinux/config
[html] view plaincopyprint?
SELINUX=disabled
關閉iptables的方法
[html] view plaincopyprint?
service iptables stop
service ip6tables stop
若是須要永久關閉(各個運行級別)
[html] view plaincopyprint?
chkconfig iptables off
chkconfig ip6tables off
咱們只須要在master機器上配置好全部的配置文件,而後所有拷貝到各個slave機器上便可。
注意配置文件中涉及到的一些訪問地址,都寫成master:port的形式。不少文檔中寫爲localhost或者127.0.0.1,這個是不對的,在多機器集羣中,每個機器上的這些配置,都是指向master節點的。
配置文件位於$HADOOP_HOME/etc/hadoop/目錄下
咱們在根目錄下創建$HADOOP_DATA_HOME目錄(/home/<hostname>/hadoop-data/, 其中<hostname>是你的用戶名), 將dfs和mapred目錄創建在這裏,包括:
$HADOOP_DATA_HOME/dfs/name
$HADOOP_DATA_HOME/dfs/data
$HADOOP_DATA_HOME/mapred/local
$HADOOP_DATA_HOME/mapred/system
將該腳本中的JAVA_HOME設置爲JAVA安裝的位置,該配置文件中,只有JAVA_HOME變量是必須配置的,其它變量都是可選配置的。
因爲咱們在.bashrc中添加了JAVA_HOME環境變量,這一步能夠省略。
[html] view plaincopyprint?
<span style="background-color:rgb(240,240,240)"><configuration></span>
<property>
<name>io,native.lib.available</name>
<value>true</value>
</property>
<property>
<name>fs.default.name</name>
<value>hdfs://master:54310</value>
<final>true</final>
</property>
</configuration>
[html] view plaincopyprint?
<configuration>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/home/<hostname>/hadoop-data/dfs/name</value>
<description>Determines where on the local filesystem the DFS name node should store the name table.If this is a comma-delimited list of directories,then name table is replicated in all of the directories,for redundancy.</description>
<final>true</final>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/home/<hostname>/hadoop-data/dfs/data</value>
<description>Determines where on the local filesystem an DFS data node should store its blocks.If this is a comma-delimited list of directories,then data will be stored in all named directories,typically on different devices.Directories that do not exist are ignored.
</description>
<final>true</final>
</property>
<property>
<name>dfs.replication</name>
<value>1</value>
<description>副本數目</description>
</property>
<property>
<name>dfs.permission</name>
<value>false</value>
</property>
</configuration>
dfs.datanode.name.dir是NameNode持久存儲名字空間及事務日誌的本地文件系統路徑。 當這個值是一個逗號分割的目錄列表時,nametable數據將會被複制到全部目錄中作冗餘備份。
dfs.datanode.data.dir是DataNode存放塊數據的本地文件系統路徑,逗號分割的列表。 當這個值是逗號分割的目錄列表時,數據將被存儲在全部目錄下,一般分佈在不一樣設備上。
dfs.replication是數據須要備份的數量,默認是3,若是此數大於集羣的機器數會出錯。
相似hadoop-env.sh,配置JAVA_HOME便可
[html] view plaincopyprint?
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
<span style="text-align:justify"><description>設置MapReduce的執行框架爲YARN,這樣mr job會被提交到ResourceManager</description></span>
</property>
<property>
<name>mapreduce.job.tracker</name>
<value>hdfs://master:9001</value>
<final>true</final>
</property>
<property>
<name>mapreduce.map.memory.mb</name>
<value>1536</value>
</property>
<property>
<name>mapreduce.map.java.opts</name>
<value>-Xmx1024M</value>
</property>
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>3072</value>
</property>
<property>
<name>mapreduce.reduce.java.opts</name>
<value>-Xmx2560M</value>
</property>
<property>
<name>mapreduce.task.io.sort.mb</name>
<value>512</value>
</property>
<property>
<name>mapreduce.task.io.sort.factor</name>
<value>100</value>
</property>
<property>
<name>mapreduce.reduce.shuffle.parallelcopies</name>
<value>50</value>
</property>
<property>
<name>mapred.system.dir</name>
<value>file:/home/hadoop/mapred/system</value>
<final>true</final>
</property>
<property>
<name>mapred.local.dir</name>
<value>file:/home/hadoop/mapred/local</value>
<final>true</final>
</property>
</configuration>
[html] view plaincopyprint?
<configuration>
<property>
<name>yarn.resourcemanager.address</name>
<value><span style="font-family:Arial,Helvetica,sans-serif">master</span><span style="font-family:Arial,Helvetica,sans-serif">:8080</value></span>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address</name>
<value>master:8081</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address</name>
<value>master:8082</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.aux-services.mapreduce_shuffle.class</name>
<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
</configuration>
注意這裏的配置文件裏面,有兩處mapreduce_shuffle(本來配置是mapreduce.shuffle,啓動時會報錯,緣由是**命名不能包含.字符)。
2.0.5.alpha版本中,這裏須要配置成mapreduce.shuffle,不然會報錯【java.lang.IllegalStateException: Invalid shuffle port number -1 returned】
yarn中shuffle部分被獨立成一個service,須要在nodemanager啓動的時候做爲auxiliary service一塊兒啓動,這樣能夠自定義第三方的shuffle provider,和ShuffleConsumer,好比能夠替換現階段的HTTP Shuffle爲RDMA Shuffle,對於中間結果merge能夠採用更合適的策略來獲得更好的性能提高。
masters文件,告訴系統那個節點是master,填寫的是master節點的hostname(因爲咱們配置了其就叫master,因此內容填master,注意這裏必須是hostname,若是填IP,會出錯)
[html] view plaincopyprint?
master
slaves文件,告訴系統哪些節點是slave,填寫的是全部slave節點的hostname,每行一個。注意事項同master。
[html] view plaincopyprint?
slave1
默認的環境裏面可能沒有masters和slaves文件,本身創建便可。
格式化HDFS:
$HADOOP_HOME/bin/hdfs namenode -format
注意,若是不是第一次格式化,那麼須要先清理tmp目錄中的數據(默認的tmp目錄在/tmp/hadoop-<username>下面),以及hdfs-site.xml中配置的dfs.datanode.data.dir目錄,不然可能出錯。
啓動集羣
$HADOOP_HOME/sbin/start-all.sh
該命令會依次啓動hdfs和yarn,分別調用start-hdfs.sh和start-yarn.sh;
start-hdfs.sh依次啓動namenode、secondarynamenode、datanode,也能夠單獨啓動,對應的命令爲
[html] view plaincopyprint?
hdfs namenode
hdfs secondarynamenode
hdfs datanode
在master上執行jps,輸出:
[html] view plaincopyprint?
3716 ResourceManager
3456 DataNode
4193 Jps
3350 NameNode
3587 SecondaryNameNode
3807 NodeManager
在slaver上執行jps,輸出:
[html] view plaincopyprint?
2032 DataNode
2118 NodeManager
2274 Jps
查看端口打開狀態
[html] view plaincopyprint?
netstat -nap | grep 54310
訪問http://<master-ip>:8088
NameNode:http://<master-ip>:50070
JobTracker:http://<master-ip>:50030
在HDFS上建立新目錄,可進一步測試HDFS是否工做正常:
[html] view plaincopyprint?
hdfs dfs -mkdir /xxx
hdfs dfs -ls /
簡單的map-reduce任務,在hadoop的根目錄下執行:
[html] view plaincopyprint?
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.2.0.jar pi 2 2
其中最後兩個參數是map數和reduce數目
或者使用以下方式調用:
[html] view plaincopyprint?
yarn jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.2.0.jar pi -Dmapreduce.clientfactory.class.name=org.apache.hadoop.mapred.YarnClientFactory -libjars $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.2.0.jar 2 2
其它的例子:
[html] view plaincopyprint?
// 將數據上傳到hdfs,若是這時出現 <span style="padding-right:0.3em; padding-left:0.3em; border:1px solid rgb(221,221,221); display:inline-block; margin-top:-1px; margin-bottom:-1px">SafeModeException</span> 異常,不用擔憂,等待幾分鐘便可。由於hadoop剛剛啓動時,會進入安全模式進行自檢。
bin/hadoop fs -put etc/hadoop/*.xml input
// 運行 Hadoop 自帶的例子:
<pre name="code" class="html">hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.2.0.jar grep input output 'dfs[a-z.]+'</pre><pre name="code" class="html">// 查看運行結果</pre>hadoop fs -cat output/*
添加一個新的節點到現有的Hadoop集羣須要作的事情包括:
1. 將這個新節點添加到網絡環境中,處理好ssh免密碼登陸(包括從master到該機器以及從該機器到master)
2. 在該機器上部署hadoop,並設置masters文件中的master爲現有集羣的master(name node)
3. 在master的slaves文件中添加該新的機器
4. start-all.sh啓動系統
而後能夠經過http://(Masternode的主機名):50070查看新添加的DataNode
出錯的時候,能夠設置logger級別,看下具體緣由:export HADOOP_ROOT_LOGGER=DEBUG,console
1. INFO util.NativeCodeLoader - Unable to load native-hadoop library for your platform... using builtin-java classes where applicable -- hadoop的本地庫加載失敗。
Hadoop默認會從$HADOOP_HOME/lib/native/Linux-*目錄中加載本地庫。若是加載成功,輸出爲:
DEBUG util.NativeCodeLoader - Trying to load the custom-built native-hadoop library...
INFO util.NativeCodeLoader - Loaded the native-hadoop library
若是加載失敗,則報錯爲Unable to load native-hadoop library for your platform...
相關的配置:
在Hadoop的配置文件core-site.xml中能夠設置是否使用本地庫:
[html] view plaincopyprint?
<property>
[html] view plaincopyprint?
<name>hadoop.native.lib</name>
[html] view plaincopyprint?
<value>true</value>
[html] view plaincopyprint?
<description>Should native hadoop libraries, if present, be used.</description>
[html] view plaincopyprint?
</property>
Hadoop默認的配置爲啓用本地庫。另外,能夠在環境變量中設置使用本地庫的位置:
export JAVA_LIBRARY_PATH=/path/to/hadoop-native-libs
出錯緣由:
檢查native庫的版本信息,32bit的版本和64bit的版本在不匹配的機器上會加載失敗,檢查的命令是file <native-so-file>。
native庫依賴的glibc的版本問題。若是在高版本gcc(glibc)的機器上編譯的native庫,放到低版本的機器上使用,會因爲glibc版本不一致致使該錯誤。
2. java.io.IOException: Failed on local exception: java.io.EOFException; Host Details : local host is: "master/192.168.216.135"; destination host is: "master":54310;
從新格式化namenode
3. maps to localhost, but this does not map back
是由於DNS服務器把 192.168.x.x 的地址都反向解析成 localhost ,而DNS服務器不是本身的,不能改。 解決的辦法就是,編輯 ssh 客戶端的 /etc/hosts 文件,把出問題的IP 地址和主機名加進去,就不會報這樣的錯了。
4. java.io.IOException: Incompatible clusterIDsin /home/wangming/hadoop-data/dfs/data
format 前 rm 一下
5. jps命令正常,可是8088端口的WEB頁面沒法訪問
檢查一下防火牆,selinux & iptables
6. 8088端口訪問正常,可是看不到datanode節點
查看配置中,發現yarn-site.xml中,yarn.resourcemanager.address屬性配置的端口號爲8080,啓動的時候,打開這個端口失敗(多是被其它進程佔用,maybe tomcat等),改爲8085,從新啓動,問題解決。
7. java.io.IOException: Failed on local exception: java.io.EOFException; Host Details : local host is: "master/192.168.216.135"; destination host is: "master":54310;
不知道爲何,從新格式化namenode,再啓動,沒有再報錯。
8. java.lang.IllegalStateException: Invalid shuffle port number -1 returned
參見yarn-site.xml的配置,2.0.5.alpha版本中,這裏須要配置成mapreduce.shuffle
9. org.apache.hadoop.ipc.Client: Retrying connect to server: master/192.168.216.131:54310
一是檢查slave機器到master機器的連通性;
二是檢查master機器上,是否打開了192.168.216.131:54310的監聽(netstat -nap | grep 54310)
注意hostname的問題,同時,namenode與data node的/etc/hosts內容都必須是ip位址與host name的對應,不能使用127.0.0.1代替本機的ip地址,不然hadoop使用hostname找ip時,會以"127.0.0.1"做爲ip位址。
10. FATAL org.apache.hadoop.hdfs.server.datanode.DataNode: Exception in secureMain:
hostname不在hosts列表裏面,檢查hostname和/etc/hosts文件
11. INFO org.apache.hadoop.hdfs.server.datanode.DataNode: Exiting Datanode 或者 INFO org.apache.hadoop.hdfs.server.datanode.DataNode: Removed Block pool
fs.data.dir參數設置的目錄權限必需爲755,要不啓動datanode節點啓動就會由於權限檢測錯誤而自動關閉。
5. YARN安裝配置初體驗
Apache有另外一個項目叫作Ambari,旨在讓你們可以方便快速的配置和部署Hadoop生態圈相關的組件的環境,並提供維護和監控的功能,本文沒有涉及到這個工具,有興趣的同窗能夠一試。