安裝 HADOOP 2.6.0

< 下載 >

下載 hadoop-2.6.0 壓縮檔 & 檢驗檔

> $ cd ~  # 回到家目錄
> $ wget http://apache.stu.edu.tw/hadoop/common/hadoop-2.6.0/hadoop-2.6.0.tar.gz
> $ wget http://apache.stu.edu.tw/hadoop/common/hadoop-2.6.0/hadoop-2.6.0.tar.gz.mds

檢查 hadoop-2.6.0.tar.gz 是否毀損或不完整

> $ cat hadoop-2.6.0.tar.gz.mds | grep 'MD5'  # 列出md5檢驗值
> $ md5sum hadoop-2.6.0.tar.gz | tr "a-z" "A-Z"  # 計算md5值,並轉換成大寫,方便比對

將 Hadoop 安裝至 /usr/local/ 中:

> $ tar -zxvf hadoop-2.6.0.tar.gz  # 解壓
> $ mv hadoop-2.6.0 hadoop  # 將資料夾改名為:hadoop
> $ sudo mv hadoop /usr/local
> $ sudo chown -R hduser:hadoop /usr/local/hadoop  # 修改 hadoop 資料夾權限
> $ sudo chmod +x -R /usr/local/hadoop  # 增加可執行權限

< 設定環境變數 >

> $ update-alternatives --config java  # 尋找 java 在哪
( 此例:「/usr/lib/jvm/java-7-openjdk-i386」 )

讓 Hadoop 知道 JAVA_HOME 變數:

> $ vim /usr/local/hadoop/etc/hadoop/hadoop-env.sh  # 修改 JAVA_HOME 路徑

將以下的資訊附加到 ~/.bashrc 與 ~/.profile 檔案末端:

# Java path
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-i386
# Hadoop-related environment variables
export HADOOP_HOME=/usr/local/hadoop
export HADOOP_MAPRED_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export YARN_HOME=$HADOOP_HOME
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export HADOOP_OPTS="-Djava.library.path=$HADOOP_HOME/lib"
# Add Hadoop bin/ directory to Path
export PATH=$PATH:$HADOOP_HOME/sbin
export PATH=$PATH:$HADOOP_HOME/bin

讓新設定生效:

> $ source ~/.bashrc
> $ source ~/.profile

測試:

> $ echo $JAVA_HOME
> $ echo $HADOOP_HOME

single-node clusters

Hadoop 單節點的安裝流程如下:

  1. 安装Java環境、SSH Server、設定hadoop使用者 - hduser、設定hduser 無密碼登錄、安装Hadoop環境
  2. 完成Hadoop單節點配置

「安装 Java 環境、SSH Server、設定hadoop使用者 - hduser、設 定hduser 無密碼登錄、安装 Hadoop 環境」已經講過了。因此,接著只要講解 Hadoop 的單節點配置。

< 修改配置文件 >

  1. core-site.xml
  2. hdfs-site.xml
  3. yarn-site.xml
  4. mapred-site.xml

1. core-site.xml ( $HADOOP_CONF_DIR/core-site.xml )

<configuration>
  <property>
    <name>fs.default.name</name>
    <value>hdfs://localhost:9000</value>
  </property>
  <property>
    <name>hadoop.tmp.dir</name>
    <value>/home/hduser/hadoop/hadoop-tmp</value>
  </property>
</configuration>

2. hdfs-site.xml ( $HADOOP_CONF_DIR/hdfs-site.xml )

<configuration>
  <property>
    <name>dfs.namenode.name.dir</name>
    <value>/home/hduser/hdfs/namenode</value>
  </property>
  <property>
    <name>dfs.datanode.data.dir</name>
    <value>/home/hduser/hdfs/datanode</value>
  </property>
  <property>
    <name>dfs.replication</name>
    <value>1</value>
  </property>
  <property>
    <name>dfs.permissions</name>
    <value>false</value>
  </property>
</configuration>

3. yarn-site.xml ( $HADOOP_CONF_DIR/yarn-site.xml )

<configuration>
  <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>

4. mapred-site.xml ( $HADOOP_CONF_DIR/mapred-site.xml )

> $ cp $HADOOP_CONF_DIR/mapred-site.xml.template $HADOOP_CONF_DIR/mapred-site.xml  # 產生mapred-site.xml
<configuration>
  <property>
    <name>mapreduce.framework.name</name>
    <value>yarn</value>
  </property>
</configuration>

於家目錄創建 tmp 資料夾 ( 因 core-site.xml 的設置而異 )

> $ mkdir -p  /home/hduser/hadoop/hadoop-tmp

於家目錄建立 hdfs 資料夾 ( 因 hdfs-site.xml 的設置而異 )

> $ mkdir -p /home/hduser/hdfs/namenode
> $ mkdir -p /home/hduser/hdfs/datanode

< 格式化 Hadoop >

> $ rm -rf ~/hdfs/*  # 清空hdfs所有檔案
> $ rm -rf $HADOOP_HOME/logs/*  # 清空記錄檔
> $ rm -rf ~/hadoop/hadoop-tmp/*  # 清空暫存檔
> $ hadoop namenode –format  # 格式化NameNode,格式化完成之後,會自動產生此資料夾:~/hdfs/namenode
※ 註:格式化 NameNode 之前,請務必清除 hdfs 內的所有檔案、暫存檔,要不然執行時會出錯。此外,建議也順便清空記錄檔,方便日後閱讀。

< 執行 Hadoop >

> $ hdfs dfsadmin -safemode leave  # Off the Safe mode of namenode
> $ start-dfs.sh
> $ start-yarn.sh
> $ jps  # 檢查是否啟動成功
※ 註:若啟動成功,會出現 Jps、NameNode、DataNode、NodeManager、ResourceManager、SecondaryNameNode。

< 執行 Hadoop WordCount 範例 >

創建本地端測試資料 file-01.txt 和 file-02.txt:

> $ mkdir -p ~/wordcount/in
> $ cd ~/wordcount/in
> $ echo "I will speak to you later." > file-01.txt
> $ echo "I will call you back as soon as possible." > file-02.txt

將本地端測試資料上傳到 HDFS:

> $ hadoop fs -mkdir -p /user/hduser  # 建立 hduser 在 HDFS 的家目錄
> $ hadoop fs -mkdir -p wordcount/in  # 於 HDFS 家目錄下創建 wordcount/in
> $ hadoop fs -ls wordcount  # 查看子資料夾 in 是否有被創建
> $ hadoop fs -put ~/wordcount/in/*.txt wordcount/in  # 上傳
> $ hadoop fs -ls wordcount/in  # 查看是否上傳成功

執行 WordCount 範例程式:

> $ hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0.jar wordcount wordcount/in wordcount/out

將本地端測試資料上傳到 HDFS:

> $ hadoop fs -ls wordcount/out  # 查看是否有 MapReduce 的輸出
> $ hadoop fs -get wordcount/out ~/wordcount/  # 將 MapReduce 的結果( out 資料夾 ),從 HDFS 端下載到本地端
> $ cat ~/wordcount/out/part-r-00000  # 顯示 MapReduce 結果

※ 註:若再執行 WordCount 範例程式,會出現「output directory hdfs://localhost:9000/user/hduser/wordcount/out already exists」錯誤。這個時候只要把 HDFS 上的輸出目的地的資料夾刪掉即可:

> $ hadoop fs -rmr wordcount/out

multi-node clusters

Hadoop 多節點的安裝流程如下:

  1. 選一台節點作為 Master
  2. 在 Master,安装Java環境、SSH Server、設定hadoop使用者 - hduser、設定hduser 無密碼登錄、安装Hadoop環境
  3. 在 Master,完成Hadoop多節點配置
  4. 在其他節點上,安装Java環境、SSH Server、設定hadoop使用者 - hduser、設定hduser 無密碼登錄、安装Hadoop環境
  5. 將 Master 上的Hadoop多節點配置,複製到其他節點上

看似流程很多,但是「安装Java環境、SSH Server、設定hadoop使用者 - hduser、設定hduser 無密碼登錄、安装Hadoop環境」已經講過了。因此,接著只要講解Hadoop的多節點配置。

< 網路設定 >

我使用四個node搭建集群:

  • node 1:當做 Master,其區網IP為 192.168.0.100
  • node 2:當做 Slave1,其區網IP為 192.168.0.101
  • node 3:當做 Slave2,其區網IP為 192.168.0.102
  • node 4:當做 Slave3,其區網IP為 192.168.0.103 ( Slave1 當作 Secondary NameNode )

於各個 node 的 /etc/hostname 中,分別修改 node 名稱為 Master、Slave1、Slave2 或 Slave3。

所有node都要操作:打開 /etc/hosts,把所有電腦名稱與區網 IP 的 Mapping 關係寫上去,以 Master 為例: ※ 註:127.0.0.1 的 localhost 請保留,要不然會出錯,然後建議重新登入或重新啟動電腦。

測試:可以在各個電腦上執行 ping Master、ping Slave1、ping Slave2 與 ping Slave3,看是否能夠相互 ping 通。

< 設定 Master 無密碼登錄到所有 nodes >

在設定之前,請先確保每部電腦能夠「無密碼」 ssh '自己的hostname'、ssh localhost。

在 Master 執行:(看能不能無密碼登錄)

> $ ssh localhost
> $ ssh Master

在 Slave1 執行:(看能不能無密碼登錄)

> $ ssh localhost
> $ ssh Slave1

在 Slave2 執行:(看能不能無密碼登錄)

> $ ssh localhost
> $ ssh Slave2

在 Slave3 執行:(看能不能無密碼登錄)

> $ ssh localhost
> $ ssh Slave3

接著,登入 Master 電腦。將Master上的公鑰傳送到所有其他nodes:

> $ ssh-copy-id -i ~/.ssh/id_rsa.pub hduser@Slave1
> $ ssh-copy-id -i ~/.ssh/id_rsa.pub hduser@Slave2
> $ ssh-copy-id -i ~/.ssh/id_rsa.pub hduser@Slave3

最後,就可以讓Master以無密碼登錄到所有nodes了

< 修改配置文件:登入 Master 電腦來進行接下來的設定 >

  1. slaves
  2. core-site.xml
  3. hdfs-site.xml
  4. yarn-site.xml
  5. mapred-site.xml

1. slaves( $HADOOP_CONF_DIR/slaves )

主要就是讓 Hadoop 知道有哪些 nodes 要做 Slave 的工作。

Master
Slave1
Slave2
Slave3

2. core-site.xml ( $HADOOP_CONF_DIR/core-site.xml )

<configuration>
  <property>
    <name>fs.default.name</name>
    <value>hdfs://Master:9000</value>
  </property>
  <property>
    <name>hadoop.tmp.dir</name>
    <value>/home/hduser/hadoop/hadoop-tmp</value>
  </property>
</configuration>

3. hdfs-site.xml ( $HADOOP_CONF_DIR/hdfs-site.xml )

建議不要讓同一個機器跑 Secondary NameNode 與 NameNode。( 我是 把Secondary NameNode 丟給 Slave1 )

<configuration>  
  <property>
    <name>dfs.namenode.http-address</name>
    <value>Master:50070</value> 
  </property>
  <property>
    <name>dfs.namenode.secondary.http-address</name>
    <value>Slave1:50090</value>
  </property>
  <property>
    <name>dfs.namenode.name.dir</name>
    <value>/home/hduser/hdfs/namenode</value>
  </property>
  <property>
    <name>dfs.datanode.data.dir</name>
    <value>/home/hduser/hdfs/datanode</value>
  </property>
  <property>
    <name>dfs.replication</name>
    <value>3</value>
  </property>
  <property>
    <name>dfs.permissions</name>
    <value>false</value>
  </property>
</configuration>

4. yarn-site.xml ( $HADOOP_CONF_DIR/yarn-site.xml )

<configuration>
  <property>
    <name>yarn.resourcemanager.hostname</name>
    <value>Master</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>

5. mapred-site.xml ( $HADOOP_CONF_DIR/mapred-site.xml )

> $ cp $HADOOP_CONF_DIR/mapred-site.xml.template $HADOOP_CONF_DIR/mapred-site.xml  # 產生mapred-site.xml
<configuration>
  <property>
    <name>mapreduce.framework.name</name>
    <value>yarn</value>
  </property>
  <property>
    <name>mapred.task.timeout</name>
    <value>600000</value>
  </property>
  <property>
    <name>mapreduce.job.maps</name>
    <value>3</value> 
  </property>
  <property>
    <name>mapreduce.job.reduces</name>
    <value>6</value> 
  </property>
  <property>
    <name>mapreduce.tasktracker.map.tasks.maximum</name>
    <value>4</value> 
  </property>
  <property>
    <name>mapreduce.tasktracker.reduce.tasks.maximum</name>
    <value>2</value> 
  </property>
  <property>
    <name>mapreduce.map.memory.mb</name>
    <value>1536</value>
  </property>
  <property>
    <name>mapreduce.reduce.memory.mb</name>
    <value>2048</value>
  </property>
  <property>
    <name>mapred.child.java.opts</name>
    <value>-Xmx1024m</value>
    <description>默認值是-Xmx200m,說明:與內存相關的參數,同時這是這個參數用於JVM 調優的主要參數。這給每個子任務線程分配最多200 MB 內存。如果作業很大,可以增加這個值,但是應該確保這不會造成交換,交換會嚴重降低性能。我們來研究一下這個參數如何影響總內存使用量。假設map/reduce 任務的最大數量設置為7,mapred.child.java.opts 保持默認值。那麼,正在運行的任務的內存開銷為2x7x200 MB =2800 MB。如果每個工作者節點都有DN 和TT 守護進程,每個守護進程在默認情況下佔用1 GB 內存,那麼分配的總內存大約為4.8 GB。 jvms啟動的子線程可以使用的最大內存。改為-Xmx1024m,內存再大也可以繼續增加。但是如果一般任務文件小,邏輯不復雜用不了那麼多的話太大也浪費。</description>
   </property>
</configuration>

※ 註:若是想要了解更多配置,可以參考官方文件:

接下來,將此新的配置,複製到所有nodes:

> $ scp -r $HADOOP_CONF_DIR hduser@Slave1:$HADOOP_HOME/etc/
> $ scp -r $HADOOP_CONF_DIR hduser@Slave2:$HADOOP_HOME/etc/
> $ scp -r $HADOOP_CONF_DIR hduser@Slave3:$HADOOP_HOME/etc/

所有 node 的 hadoop 格式化:(每個 node 都要執行)

> $ rm -rf /home/hduser/hdfs/*  # 清空hdfs所有檔案
> $ rm -rf $HADOOP_HOME/logs/*  # 清空記錄檔
> $ rm -rf ~/hadoop/hadoop-tmp/*  # 清空暫存檔

回到 Master 節點。格式化 NameNode:

> $  hadoop namenode -format

< 執行 Hadoop ( 在 Master 節點 ) >

> $ hdfs dfsadmin -safemode leave  # Off the Safe mode of namenode
> $ start-dfs.sh
> $ start-yarn.sh
> $ jps  # 檢查是否啟動成功

啟動 JobHistoryServer

> $ mr-jobhistory-daemon.sh start historyserver

可以在Master執行此指令,來查看其他nodes是否有與Master正確連接:

> $ hadoop dfsadmin -report

< Hadoop 有以下三個常用的 Web GUI,方便查看Hadoop狀態 >