Hadoop-手動建立單節點的Hadoop叢集

2017.12.01 DockerCon Briefing 2017 Taipei
2017-12-27
如何在Pivotal Greenplum Database擴充節點
2017-12-28

引言

在學習Hadoop時,建議使用Hortonworks打包好的Sandbox,或Cloudera的QuickStart VM。內心深處,肯定有肢解它們的衝動。本專欄的目的,就是以描述如何手動架設Hadoop「偽分佈模式」(pseudo-distributed mode),來適度反向滿足心中的野獸。

準備安裝環境

以下Hadoop的安裝環境,是在VMware Worstation 11上運作的CentOS 7 Linux作業系統。倘若您偏好使用甲骨文的VirtualBox虛擬平台,也無不可。若您有使用純文字介面的癖好,在安裝CentOS時建議選擇Infrastructure Server以上(含)的級別,且務必勾選加裝Java Platform。若您無自虐傾向,則建議安裝至Gnome Desktop級別。

在開工前,不妨將作業系統整體更新一次;以root身份,執行

# yum –y update

下載及安裝Hadoop 程式包

以root身份,執行

# wget http://apache.stu.edu.tw/hadoop/common/hadoop-2.7.1/hadoop-2.7.1.tar.gz

Hadoop-2.7.1是本專欄下筆時的最新版本。您可至http://hadoop.apache.org/releases.html檢視當下的最新版。記得點選binary而非source。

下載完成後,解壓,再將資料夾移至 /usr/local 目錄底下:

# tar xvf hadoop-2.7.1.tar.gz

# mv hadoop-2.7.1 /usr/local

Hadoop就此「安裝」完成!但談上陣還早,請往下看。

設定環境變數

首先,要編輯在 /usr/local/hadoop-2.7.1/etc/hadoop目錄下一個叫hadoop-env.sh的檔案,以設定重要環境變數。這些變數的意義,檔案裡有官方注釋,在此也就不贅述。

把#export JAVA_HOME=${JAVA_HOME}改成(務必删去井字符號)

export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.75-2.5.4.2.el7_0.x86_64/jre

把 #export HADOOP_LOG_DIR=${HADOOP_LOG_DIR}/$USER改成

export HADOOP_LOG_DIR=/var/log/hadoop/$USER

緊接著這行,加入

export HADOOP_MAPRED_LOG_DIR=/var/log/hadoop-mapreduce/$USER

再來,編輯同目錄下的yarn-env.sh,在IFS=那行下面,加入

export YARN_LOG_DIR=/var/log/hadoop-yarn/$USER

最後,為往後操作上的便利,新增檔案/etc/profile.d/hadoop.sh,並編輯以下內容:

export HADOOP_PREFIX=/usr/local/hadoop-2.7.1

export PATH=$HADOOP_PREFIX/sbin:$HADOOP_PREFIX/bin:$PATH

export MR_EXAMPLES=$HADOOP_PREFIX/share/hadoop/mapreduce

階段性確認Hadoop生命跡象:

# source /etc/profile.d/hadoop.sh

# hadoop version

Hadoop 2.7.1

Subversion https://git-wip-us.apache.org/repos/asf/hadoop.git -r 15ecc87ccf4a0228f35af08fc56de536e6ce657a

Compiled by jenkins on 2015-06-29T06:04Z

Compiled with protoc 2.5.0

From source with checksum fc0a1a23fc1868e4d5ee7fa2b28a58a

This command was run using /usr/local/hadoop-2.7.1/share/hadoop/common/hadoop-common-2.7.1.jar

建立標準帳戶

建立方便Hadoop權限管理的群組和帳戶:

# groupadd hadoop

# groupadd hdfs

# useradd -g hadoop yarn

# useradd -g hadoop hdfs

# useradd -g hadoop mapred

建立存放日誌的目錄

接著,建立之前我們在hadoop-env.sh和yarn-env.sh裡指定存放日誌的目錄:

# mkdir /var/log/hadoop

# chgrp hadoop /var/log/hadoop

# chmod 775 /var/log/hadoop

# mkdir /var/log/hadoop-mapreduce

# chown yarn:hadoop /var/log/hadoop-mapreduce

# mkdir /var/log/hadoop-yarn

# chown yarn:hadoop /var/log/hadoop-yarn

建立構成HDFS的目錄

接下來要建的,是HDFS常駐程式(Namendoe、Secondary Namenode、Datanode)的專屬目錄。稍後,我們會把一些配置檔裡的設定指向它們。Hadoop就是靠這些設定得知HDFS的內容要在何處讀寫。由於本「叢集」僅有單一節點,我們只能委屈這些常駐程式,把它們的專屬「硬碟」全塞在一個子目錄底下:

# mkdir –p /hadoop/hdfs

# cd /hadoop/hdfs

# mkdir nn snn dn

# chown –R hdfs:hdfs .

如果這是個企業級別的Hadoop叢集,這些常駐程式會在各自的伺服器上跑,並各自擁有一至多個專屬硬碟。

配置HDFS和YARN

接下來我們著手一連串的配置。這些配置的意義,可在Apache官網上查到。

回到 $HADOOP_PREFIX/etc/hadoop目錄,先編輯檔案core-site.xml如下:

<!–core-site.xml–>

<configuration>

<property>

<name>fs.defaultFS</name>

<value>hdfs://localhost</value>

</property>

<property>

<name>hadoop.http.staticuser.user</name>

<value>hdfs</value>

</property>

</configuration>

這裡的重點是第一個設定,宣告本機就是Namenode,而且要Hadoop用HDFS檔案系統。

編輯hdfs-site.xml如下:

<!–hdfs-site.xml–>

<configuration>

<property>

<name>dfs.replication</name>

<value>1</value>

</property>

<property>

<name>dfs.namenode.name.dir</name>

<value>file:/hadoop/hdfs/nn</value>

</property>

<property>

<name>dfs.checkpoint.dir</name>

<value>file:/hadoop/hdfs/snn</value>

</property>

<property>

<name>dfs.checkpoint.edits.dir</name>

<value>file:/hadoop/hdfs/snn</value>

</property>

<property>

<name>dfs.datanode.data.dir</name>

<value>file:/hadoop/hdfs/dn</value>

</property>

</configuration>

設定dfs.replication指定HDFS檔案複製數為1(預設值為3)。接下來的幾個設定指向上個章節建的資料夾。

編輯mapred-site.xml如下:

<!–mapred-site.xml–>

<configuration>

<property>

<name>mapreduce.framework.name</name>

<value>yarn</value>

</property>

<property>

<name>yarn.app.mapreduce.am.staging-dir</name>

<value>/user</value>

</property>

<property>

<name>mapreduce.jobhistory.done-dir</name>

<value>/mr-history/done</value>

</property>

<property>

<name>mapreduce.jobhistory.intermediate-done-dir</name>

<value>/mr-history/tmp</value>

</property>

</configuration>

設定mapreduce.framework.name指明執行MapReduce時要透過YARN。後續設定宣告MapReduce的中繼和結果日誌要放的位置。稍後我們還要建相關的資料夾。

最後,編輯yarn-site.xml,宣告YARN的ResourceManager在本機上跑:

<!–yarn-site.xml–>

<configuration>

<property>

<name>yarn.resourcemanager.hostname</name>

<value>localhost</value>

</property>

<property>

<name>yarn.nodemanager.aux-services</name>

<value>mapreduce_shuffle</value>

</property>

</configuration>

若這是企業級的Hadoop叢集,ResourceManager會有專屬的伺服器,而不是跟Namenode擠同一個機台。

修改Java的預設記憶堆大小

正常情況下,架偽分佈模式是為了學習而非處理大量資料,因此我們會對Hadoop使用的電腦資源加碼限制,其中最重要的一環是記憶堆大小的控制。

進$HADOOP_PREFIX/etc/hadoop目錄,對hadoop-env.sh做下列修改:

  • 將#export HADOOP_HEAPSIZE=改成export HADOOP_HEAPSIZE=”100″
  • 將#export HADOOP_NAMENODE_INIT_HEAPSIZE=”1000″改成export HADOOP_NAMENODE_INIT_HEAPSIZE=”100″
  • 進mapred-env.sh,把export HADOOP_JOB_HISTORYSERVER_HEAPSIZE=1000改成export HADOOP_JOB_HISTORYSERVER_HEAPSIZE=50。
  • 進yarn-env.sh,把JAVA_HEAP_MAX=-Xmx1000m改為JAVA_HEAP_MAX=-Xmx100m,接著再加YARN_HEAPSIZE=100。

 「格式化」Namenode

在HDFS第一次使用前,需要先「格式化」Namenode,目的是把HDFS的初始狀態寫進Namenode的紀錄。為此,執行下列指令:

# su – hdfs

$ hdfs namenode –format

若無差錯,在一長串訊息的尾端會看到類似下列的「成功」回報:

15/08/23 22:17:46 INFO common.Storage: Storage directory /var/data/hadoop/hdfs/nn has been successfully formatted.

15/08/23 22:17:47 INFO namenode.NNStorageRetentionManager: Going to retain 1 images with txid >= 0

15/08/23 22:17:47 INFO util.ExitUtil: Exiting with status 0

15/08/23 22:17:47 INFO namenode.NameNode: SHUTDOWN_MSG:

/************************************************************

SHUTDOWN_MSG: Shutting down NameNode at hadoop2.localdomain/192.168.204.142

************************************************************/

如果現在回頭去看/hadoop/hdfs/nn目錄,會看到一個叫current的子目錄,底下有幾個暗藏HDFS玄機的檔案:

[hdfs@localhost ~]$ ls -l /hadoop/hdfs/nn/current

total 16

-rw-r–r–. 1 hdfs hadoop 351 Sep 19 14:54 fsimage_0000000000000000000

-rw-r–r–. 1 hdfs hadoop  62 Sep 19 14:54 fsimage_0000000000000000000.md5

-rw-r–r–. 1 hdfs hadoop   2 Sep 19 14:54 seen_txid

-rw-r–r–. 1 hdfs hadoop 201 Sep 19 14:54 VERSION

至於/hadoop/hdfs/snn/hadoop/hdfs/dn,則依然是空無一物。

一路走到這裡,差不多是收割勞動果實的時候了。HDFS已經就緒,就等著我們點火啟動。

啟動HDFS

欲啟動HDFS,須個別發動HDFS三大組件:

# su – hdfs

$ hadoop-daemon.sh start namenode

starting namenode, logging to /var/log/hadoop/hadoop-hdfs-namenode-hadoop2.kosmos.out

$ hadoop-daemon.sh start secondarynamenode

starting secondarynamenode, logging to /var/log/hadoop/hadoop-hdfs-secondarynamenode-hadoop2.kosmos.out

$ hadoop-daemon.sh start datanode

starting datanode, logging to /var/log/hadoop/hadoop-hdfs-datanode-hadoop2.kosmos.out

看起來是成功了,但可能還是要有其它方式確認會比較心安,畢竟常駐程式在啟動後不久默默掛點的事在報紙上常看到。為此,可使用指令hdfs dfsadmin -report:

$ hdfs dfsadmin -report

Configured Capacity: 18746441728 (17.46 GB)

Present Capacity: 14292144128 (13.31 GB)

DFS Remaining: 14292131840 (13.31 GB)

DFS Used: 12288 (12 KB)

DFS Used%: 0.00%

Under replicated blocks: 0

Blocks with corrupt replicas: 0

Missing blocks: 0

Missing blocks (with replication factor 1): 0

————————————————-

Live datanodes (1):

Name: 127.0.0.1:50010 (localhost)

Hostname: hadoop2.localdomain

Decommission Status : Normal

Configured Capacity: 18746441728 (17.46 GB)

DFS Used: 12288 (12 KB)

Non DFS Used: 4454297600 (4.15 GB)

DFS Remaining: 14292131840 (13.31 GB)

DFS Used%: 0.00%

DFS Remaining%: 76.24%

Configured Cache Capacity: 0 (0 B)

Cache Used: 0 (0 B)

Cache Remaining: 0 (0 B)

Cache Used%: 100.00%

Cache Remaining%: 0.00%

Xceivers: 1

Last contact: Mon Aug 24 14:06:55 CST 2015

另一個監控HDFS狀況的方式是透過Namenode的Web UI。網址是http://localhost:50070。

建立基本HDFS目錄

接下來,我們要在HDFS上建立一些Hadoop應用程式會使用的暫存目錄,和讓HDFS用戶存放個人資料用的目錄:

# su – hdfs

$ hdfs dfs –mkdir /tmp

$ hdfs dfs –chown hdfs:hdfs /tmp

$ hdfs dfs –chmod 777 /tmp

$ hdfs dfs –mkdir /mr-history

$ hdfs dfs –chown mapred:hadoop /mr-history

$ hdfs dfs –chmod 777 /mr-history

$ hdfs dfs –mkdir /user

$ hdfs dfs –chown hdfs:hdfs /user

我們假設有個叫noob的HDFS用戶,並為他在/user底下建一個個人目錄:

$ hdfs dfs –mkdir /user/noob

$ hdfs dfs –chown noob:hdfs /user/noob

啟動YARN

YARN可透過yarn-daemon.sh腳本啟動。先啟動ResourceManager:

# su – yarn

$ yarn-daemon.sh start resourcemanager

starting resourcemanager, logging to /var/log/hadoop-yarn/yarn/yarn-yarn-resourcemanager-hadoop2.kosmos.out

接著啟動NodeManager:

$ yarn-daemon.sh start nodemanager

starting nodemanager, logging to /var/log/hadoop-yarn/yarn/yarn-yarn-nodemanager-hadoop2.kosmos.out

也順手啟動MapReduce的HistoryServer,因為馬上會用到:

$ mr-jobhistory-daemon.sh start historyserver

starting historyserver, logging to /var/log/hadoop-mapreduce/yarn/mapred-yarn-historyserver-hadoop2.kosmos.out

ResourceManager本身也經營一個Web UI,網址是http://localhost:8088,我們可透過它監控YARN的狀態:

試跑MapReduce

以一般用戶noob的身份,試跑一個官方標配MapReduce「任務」– 以蒙地卡羅手法估算圓週率:

# su – noob

$ hadoop jar $MR_EXAMPLES/hadoop-mapreduce-examples-2.7.1.jar pi 1 10000

如果沒什麼差錯,應該會看到類似下列,一貫落落長的訊息:

Number of Maps  = 1

Samples per Map = 10000

Wrote input for Map #0

Starting Job

15/09/15 11:16:00 INFO client.RMProxy: Connecting to ResourceManager at localhost/127.0.0.1:8032

15/09/15 11:16:00 INFO input.FileInputFormat: Total input paths to process : 1

15/09/15 11:16:01 INFO mapreduce.JobSubmitter: number of splits:1

15/09/15 11:16:01 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1442285540714_0002

15/09/15 11:16:02 INFO impl.YarnClientImpl: Submitted application application_1442285540714_0002

15/09/15 11:16:02 INFO mapreduce.Job: The url to track the job: http://hadoop2.kosmos:8088/proxy/application_1442285540714_0002/

15/09/15 11:16:02 INFO mapreduce.Job: Running job: job_1442285540714_0002

15/09/15 11:16:13 INFO mapreduce.Job: Job job_1442285540714_0002 running in uber mode : false

15/09/15 11:16:13 INFO mapreduce.Job:  map 0% reduce 0%

15/09/15 11:16:24 INFO mapreduce.Job:  map 100% reduce 0%

15/09/15 11:16:34 INFO mapreduce.Job:  map 100% reduce 100%

…..

Job Finished in 34.31 seconds

Estimated value of Pi is 3.14080000000000000000

如果看到最後一行圓週率的回報,就代表任務圓滿結束,單節點叢集狀況OK,更代表您已成功躋身人生勝利組之列!

結語

偽分佈模式雖然成不了什麼大事,但親手架設一次,對了解Hadoop v2的基本架構,還是有極大助益的。希望您一起動手做後,認同這個說法。